Hi All,
I have encountered a problem when launching a multi-threaded job triggered by JMS.
Here is my scenario:
Client pushes message in the queue, MDB listens to the queue and picks up the message, then MDB launch a multi-threaded job.
When Job had been started and the first time Step(the first thread finished the Tasklet) committed the changes in table BATCH_STEP_EXECUTION according to ‘commitIntervel’ property of Step, it threw the following exception:
Then I debugged and went into the snippet code:Code:SystemErr R org.springframework.batch.core.UnexpectedJobExecutionException: Encountered an error saving batch meta data. SystemErr R at org.springframework..batch.core.step.item.ItemOrientedStep.execute(ItemOrientedStep.java:415) SystemErr R at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) SystemErr R at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64) SystemErr R at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) SystemErr R at java.lang.reflect.Method.invoke(Method.java:615) SystemErr R at org.springframework..aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:296) SystemErr R at org.springframework..aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:177) ... SystemErr R at org.springframework..aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204) SystemErr R at $Proxy9.execute(Unknown Source) SystemErr R at org.springframework..batch.core.job.SimpleJob.execute(SimpleJob.java:121) SystemErr R at org.springframework..batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:90) SystemErr R at org.springframework..core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:49) SystemErr R at org.springframework..batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:85) SystemErr R at com.test.batch.sample.JobLauncherService.launchJob(JobLauncherService.java:54) ... SystemErr R at com.ibm.ejs.container.MDBWrapper.onMessage(MDBWrapper.java:132) SystemErr R at com.ibm.ejs.jms.listener.ServerSession.run(ServerSession.java:481) SystemErr R at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1469) SystemErr R Caused by: org.springframework.dao.EmptyResultDataAccessException: Incorrect result size: expected 1, actual 0 at org.springframework.dao.support.DataAccessUtils.requiredSingleResult(DataAccessUtils.java:71) at org.springframework.jdbc.core.JdbcTemplate.queryForObject(JdbcTemplate.java:668) at org.springframework.jdbc.core.JdbcTemplate.queryForObject(JdbcTemplate.java:678) at org.springframework.jdbc.core.JdbcTemplate.queryForInt(JdbcTemplate.java:705) at org.springframework.batch.core.repository.dao.JdbcStepExecutionDao.updateStepExecution(JdbcStepExecutionDao.java:327) at org.springframework.batch.core.repository.support.SimpleJobRepository.saveOrUpdate(SimpleJobRepository.java:238) at org.springframework.batch.core.repository.support.SimpleJobRepository.saveOrUpdateExecutionContext(SimpleJobRepository.java:247) at org.springframework.batch.core.step.item.ItemOrientedStep$1.doInIteration(ItemOrientedStep.java:315) at org.springframework.batch.repeat.support.TaskExecutorRepeatTemplate$ExecutingRunnable.run(TaskExecutorRepeatTemplate.java:215) at org.springframework.scheduling.commonj.DelegatingWork.run(DelegatingWork.java:61) at com.ibm.ws.asynchbeans.J2EEContext.run(J2EEContext.java:1114) at com.ibm.ws.asynchbeans.WorkWithExecutionContextImpl.go(WorkWithExecutionContextImpl.java:195) at com.ibm.ws.asynchbeans.CJWorkItemImpl.run(CJWorkItemImpl.java:187) at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1469) SystemErr R at org.springframework..dao.support.DataAccessUtils.requiredSingleResult(DataAccessUtils.java:71) SystemErr R at org.springframework..jdbc.core.JdbcTemplate.queryForObject(JdbcTemplate.java:668) SystemErr R at org.springframework..jdbc.core.JdbcTemplate.queryForObject(JdbcTemplate.java:678) SystemErr R at org.springframework..jdbc.core.JdbcTemplate.queryForInt(JdbcTemplate.java:705) SystemErr R at org.springframework..batch.core.repository.dao.JdbcStepExecutionDao.updateStepExecution(JdbcStepExecutionDao.java:327) SystemErr R at org.springframework..batch.core.repository.support.SimpleJobRepository.saveOrUpdate(SimpleJobRepository.java:238) SystemErr R at org.springframework..batch.core.repository.support.SimpleJobRepository.saveOrUpdateExecutionContext(SimpleJobRepository.java:247) SystemErr R at org.springframework..batch.core.step.item.ItemOrientedStep$1.doInIteration(ItemOrientedStep.java:315) SystemErr R at org.springframework..batch.repeat.support.TaskExecutorRepeatTemplate$ExecutingRunnable.run(TaskExecutorRepeatTemplate.java:215) SystemErr R at org.springframework..scheduling.commonj.DelegatingWork.run(DelegatingWork.java:61) SystemErr R at com.ibm.ws.asynchbeans.J2EEContext.run(J2EEContext.java:1114) SystemErr R at com.ibm.ws.asynchbeans.WorkWithExecutionContextImpl.go(WorkWithExecutionContextImpl.java:195) SystemErr R at com.ibm.ws.asynchbeans.CJWorkItemImpl.run(CJWorkItemImpl.java:187) SystemErr R ... 1 more
org.springframework.batch.core.repository.support. SimpleJobRepository
It is correct that stepExecution.getId() is not null after the first time executing stepExecutionDao.saveStepExecution(stepExecution); , but its corresponding record is not found in table BATCH_STEP_EXECUTION, so that count is 0 below and it fails when executing the follow snnipet:Code:public void saveOrUpdate(StepExecution stepExecution) { ... if (stepExecution.getId() == null) { stepExecutionDao.saveStepExecution(stepExecution); } else { // existing execution, update stepExecutionDao.updateStepExecution(stepExecution); } }
org.springframework.batch.core.repository.dao.Jdbc StepExecutionDao
It appears that there is transaction matter, which leads not commit on DB level.Code:public void updateStepExecution(StepExecution stepExecution) { ... int count = getJdbcTemplate().update( getQuery(UPDATE_STEP_EXECUTION), parameters, new int[] { Types.TIMESTAMP, Types.TIMESTAMP, Types.VARCHAR, Types.INTEGER, Types.INTEGER, Types.CHAR, Types.VARCHAR, Types.VARCHAR, Types.INTEGER, Types.INTEGER, Types.INTEGER }); // Avoid concurrent modifications... if (count == 0) { int curentVersion = getJdbcTemplate().queryForInt( getQuery(CURRENT_VERSION_STEP_EXECUTION), new Object[] { stepExecution.getId() }); throw new OptimisticLockingFailureException("Attempt to update step execution id=" + stepExecution.getId() + " with wrong version (" + stepExecution.getVersion() + "), where current version is "+curentVersion); } stepExecution.incrementVersion(); ... }
Here’s my environment:
Spring Batch 1.0.0.rc1
WebSphere Application Server 6.1.0.11
Oracle 10g
MQ 6.0
DB and MDB’s XA resources ablility are enabled, also configured on WAS 6.1
I used ‘JtaTransactionManager’ as my transaction manager, and ‘WorkManagerTaskExecutor’ as TaskManager for thread pools management.
Could anyone give me a solution? Thank you!
BTW, the 2 scenarios I have tried below are OK:
JMS trigger single-threaded job. (JMS resource + JDBC resource)
Multi-threaded job run on web container. (JDBC resource)


Reply With Quote