我有一个简单的工作设置:
<job id="myJob" restartable="false"
xmlns="http://www.springframework.org/schema/batch"
job-repository="dbJobRepository">
<step id="myStep">
<tasklet>
<chunk reader="myReader"
processor="myProcessor"
writer="myWriter"
commit-interval="100">
</chunk>
</tasklet>
</step>
</job>
<bean id="dbJobRepository" class="org.springframework.batch.core.repository.support.JobRepositoryFactoryBean">
<property name="databaseType" value="mysql" />
<property name="dataSource" ref="dataSource" />
<property name="transactionManager" ref="transactionManager"/>
<property name="isolationLevelForCreate" value="ISOLATION_DEFAULT"/>
</bean>
通过Quartz容器进程触发作业:
public void runHook() throws Exception {
...
this.jobParameters = jobParamsBuilder.toJobParameters();
JobExecution jobExecution = jobLauncher.run(this.job, this.jobParameters);
BatchStatus batchStatus = jobExecution.getStatus();
...
}
public void abort() {
...
JobOperator jobOperator = KBeansProvider.getBean("jobOperator");
JobRepository jobRepository = KBeansProvider.getBean("dbJobRepository");
JobExecution jobExecution = jobRepository.getLastJobExecution(this.jobBeanId,this.jobParameters);
try {
jobExecution.stop();
jobOperator.stop(jobExecution.getJobId());
...
}
在调用abort()时,找到执行并且步骤本身以秒的方式停止:
2012-02-13 13:59:37,566 INFO [org.springframework.batch.core.repository.support.SimpleJobRepository] - <Parent JobExecution is stopped, so passing message on to StepExecution>
2012-02-13 13:59:37,569 INFO [org.springframework.batch.core.step.ThreadStepInterruptionPolicy] - <Step interrupted through StepExecution>
2012-02-13 13:59:37,573 ERROR [org.springframework.batch.core.step.AbstractStep] - <Encountered an error executing the step>
org.springframework.batch.core.JobInterruptedException: Job interrupted status detected.
at org.springframework.batch.core.step.ThreadStepInterruptionPolicy.checkInterrupted(ThreadStepInterruptionPolicy.java:42)
at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:277)
如预期的那样,batch_step_execution表中的步骤状态设置为STOPPED。 问题是runHook方法被阻止: JobExecution jobExecution = jobLauncher.run(this.job,this.jobParameters); (由于系统限制,我必须在这里使用同步的jobLauncher) 并且该作业的batch_job_execution条目位于&#39; STOPPING&#39;状态。
需要注意的一个奇怪的行为是,有时状态会更改为STOPPED并且jobLauncher.run()将返回,但仅在相当长的时间后,最少10分钟,最多一个小时或两个小时。
这是runHook()线程的堆栈跟踪:
MyClusteredReadyScheduler_Worker-3@8362, prio=3, in group 'main', status: 'RUNNING'
at java.net.SocketInputStream.socketRead0(SocketInputStream.java:-1)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at com.mysql.jdbc.util.ReadAheadInputStream.fill(ReadAheadInputStream.java:113)
at com.mysql.jdbc.util.ReadAheadInputStream.readFromUnderlyingStreamIfNecessary(ReadAheadInputStream.java:160)
at com.mysql.jdbc.util.ReadAheadInputStream.read(ReadAheadInputStream.java:188)
at com.mysql.jdbc.MysqlIO.readFully(MysqlIO.java:2499)
at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:3010)
at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:2943)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3486)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:919)
at com.mysql.jdbc.MysqlIO.nextRow(MysqlIO.java:1416)
at com.mysql.jdbc.RowDataDynamic.nextRecord(RowDataDynamic.java:416)
at com.mysql.jdbc.RowDataDynamic.next(RowDataDynamic.java:395)
at com.mysql.jdbc.RowDataDynamic.close(RowDataDynamic.java:173)
at com.mysql.jdbc.ResultSetImpl.realClose(ResultSetImpl.java:7623)
at com.mysql.jdbc.ResultSetImpl.close(ResultSetImpl.java:907)
at org.apache.tomcat.dbcp.dbcp.DelegatingResultSet.close(DelegatingResultSet.java:152)
at org.springframework.jdbc.support.JdbcUtils.closeResultSet(JdbcUtils.java:107)
at org.springframework.batch.item.database.AbstractCursorItemReader.doClose(AbstractCursorItemReader.java:375)
at org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader.close(AbstractItemCountingItemStreamItemReader.java:124)
at org.springframework.batch.item.support.CompositeItemStream.close(CompositeItemStream.java:83)
at org.springframework.batch.core.step.tasklet.TaskletStep.close(TaskletStep.java:297)
at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:255)
at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:135)
at org.springframework.batch.core.job.flow.JobFlowExecutor.executeStep(JobFlowExecutor.java:61)
at org.springframework.batch.core.job.flow.support.state.StepState.handle(StepState.java:60)
at org.springframework.batch.core.job.flow.support.SimpleFlow.resume(SimpleFlow.java:144)
at org.springframework.batch.core.job.flow.support.SimpleFlow.start(SimpleFlow.java:124)
at org.springframework.batch.core.job.flow.FlowJob.doExecute(FlowJob.java:135)
at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:281)
at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:120)
at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:48)
at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:114)
查看堆栈跟踪,看起来故障与jdbc连接有某种关系, 所以我会提供一些可能有用的额外信息。
我的读者扩展了AbstractCursorItemReader,相关方法包括:
@Override
public void afterPropertiesSet() throws Exception {
setSql(this.sql);
this.setSaveState(false);
this.setVerifyCursorPosition(false);
this.setIgnoreWarnings(true);
this.setUseSharedExtendedConnection(false);
this.setQueryTimeout(10000);
}
protected void cleanupOnClose() throws Exception {
JdbcUtils.closeStatement(this.preparedStatement);
}
protected void openCursor(Connection con) {
try {
if (isUseSharedExtendedConnection()) {
preparedStatement = con.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY,
ResultSet.HOLD_CURSORS_OVER_COMMIT);
}
else {
preparedStatement = con.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
}
applyStatementSettings(preparedStatement);
if (this.preparedStatementSetter != null) {
preparedStatementSetter.setValues(preparedStatement);
}
preparedStatement.setFetchSize(Integer.MIN_VALUE);
this.rs = preparedStatement.executeQuery();
ProcessLogger.getLogger().debug("Executed query: " + this.rs.getStatement());
}
}
我所希望的行为是让工作立即停止 - 或者至少在步骤停止后不久停止。