java - 即使抛出 NullPointerException 后,Spring Batch 指数重试也不会启动

标签 java spring spring-batch spring-retry

我有以下 Spring Batch 指数重试配置,但当我故意抛出 NullPointerException 时,我没有看到重试启动。为什么?

Spring 批量指数重试配置:

<bean id="stepParentExponentialRetry" class="org.springframework.batch.core.step.item.FaultTolerantStepFactoryBean" abstract="true">
    <property name="backOffPolicy">
        <bean class="org.springframework.batch.retry.backoff.ExponentialBackOffPolicy">
            <property name="initialInterval" value="10" />
            <property name="maxInterval" value="15" />
            <property name="multiplier" value="5" />
        </bean>
        </property>
</bean>

<!-- Batch Job -->     
<bean id="checkNextRetryTasklet" class="com.XX.XX.XX.RetrySubmitJob" />
    <batch:job id="expoRetryJob" job-repository="jobRepository">
        <batch:step id="expoRetryStep" parent="stepParentExponentialRetry">
            <batch:tasklet ref="checkNextRetryTasklet" transaction-manager="txManager"/>
        </batch:step>
    </batch:job>

重试提交作业:

    public class RetrySubmitJob implements Tasklet{
       @Override
        public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
   try {        
        logger.debug("--Logger in --Spring batch--- expo --- retry----");
        String orderId = (String)    chunkContext.getStepContext().getJobParameters().get(CommonConstants.ORDER_NUMBER);
        Orders order = null;
        order.getStatus(); // To throw Null pointer exception
        } catch (Exception e) {
            logger.debug(e.fillinStackTrace());
            throw e;
        }

        return RepeatStatus.FINISHED;
        }
    }

在我的单元测试场景中调用此批处理的类:

 JobParameters jobParameters = 
                          new JobParametersBuilder()
                          .addString(CommonConstants.ORDER_NUMBER, orderNmb).toJobParameters();
jobLauncher.run(expoRetryJob, jobParameters);

相关日志:

Hibernate: SELECT JOB_INSTANCE_ID, JOB_NAME from BATCH_JOB_INSTANCE where JOB_NAME = ? and JOB_KEY = ?
Hibernate: SELECT JOB_INSTANCE_ID, JOB_NAME from BATCH_JOB_INSTANCE where JOB_NAME = ? and JOB_KEY = ?
Hibernate: SELECT JOB_INSTANCE_ID, JOB_NAME from BATCH_JOB_INSTANCE where JOB_NAME = ? and JOB_KEY = ?
Hibernate: select BATCH_JOB_SEQ.nextval from dual
Hibernate: INSERT into BATCH_JOB_INSTANCE(JOB_INSTANCE_ID, JOB_NAME, JOB_KEY, VERSION) values (?, ?, ?, ?)
Hibernate: INSERT into BATCH_JOB_PARAMS(JOB_INSTANCE_ID, KEY_NAME, TYPE_CD, STRING_VAL, DATE_VAL, LONG_VAL, DOUBLE_VAL) values (?, ?, ?, ?, ?, ?, ?)
Hibernate: select BATCH_JOB_EXECUTION_SEQ.nextval from dual
Hibernate: INSERT into BATCH_JOB_EXECUTION(JOB_EXECUTION_ID, JOB_INSTANCE_ID, START_TIME, END_TIME, STATUS, EXIT_CODE, EXIT_MESSAGE, VERSION, CREATE_TIME, LAST_UPDATED) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Hibernate: INSERT INTO BATCH_JOB_EXECUTION_CONTEXT (SHORT_CONTEXT, SERIALIZED_CONTEXT, JOB_EXECUTION_ID) VALUES(?, ?, ?)
Hibernate: SELECT COUNT(*) FROM BATCH_JOB_EXECUTION WHERE JOB_EXECUTION_ID = ?
Hibernate: UPDATE BATCH_JOB_EXECUTION set START_TIME = ?, END_TIME = ?,  STATUS = ?, EXIT_CODE = ?, EXIT_MESSAGE = ?, VERSION = ?, CREATE_TIME = ?, LAST_UPDATED = ? where JOB_EXECUTION_ID = ? and VERSION = ?
Hibernate: SELECT JOB_EXECUTION_ID, START_TIME, END_TIME, STATUS, EXIT_CODE, EXIT_MESSAGE, CREATE_TIME, LAST_UPDATED, VERSION from BATCH_JOB_EXECUTION where JOB_INSTANCE_ID = ? order by JOB_EXECUTION_ID desc
Hibernate: SELECT STEP_EXECUTION_ID, STEP_NAME, START_TIME, END_TIME, STATUS, COMMIT_COUNT, READ_COUNT, FILTER_COUNT, WRITE_COUNT, EXIT_CODE, EXIT_MESSAGE, READ_SKIP_COUNT, WRITE_SKIP_COUNT, PROCESS_SKIP_COUNT, ROLLBACK_COUNT, LAST_UPDATED, VERSION from BATCH_STEP_EXECUTION where JOB_EXECUTION_ID = ? order by STEP_EXECUTION_ID
Hibernate: SELECT JOB_EXECUTION_ID, START_TIME, END_TIME, STATUS, EXIT_CODE, EXIT_MESSAGE, CREATE_TIME, LAST_UPDATED, VERSION from BATCH_JOB_EXECUTION where JOB_INSTANCE_ID = ? order by JOB_EXECUTION_ID desc
Hibernate: SELECT STEP_EXECUTION_ID, STEP_NAME, START_TIME, END_TIME, STATUS, COMMIT_COUNT, READ_COUNT, FILTER_COUNT, WRITE_COUNT, EXIT_CODE, EXIT_MESSAGE, READ_SKIP_COUNT, WRITE_SKIP_COUNT, PROCESS_SKIP_COUNT, ROLLBACK_COUNT, LAST_UPDATED, VERSION from BATCH_STEP_EXECUTION where JOB_EXECUTION_ID = ? order by STEP_EXECUTION_ID
Hibernate: select BATCH_STEP_EXECUTION_SEQ.nextval from dual
Hibernate: INSERT into BATCH_STEP_EXECUTION(STEP_EXECUTION_ID, VERSION, STEP_NAME, JOB_EXECUTION_ID, START_TIME, END_TIME, STATUS, COMMIT_COUNT, READ_COUNT, FILTER_COUNT, WRITE_COUNT, EXIT_CODE, EXIT_MESSAGE, READ_SKIP_COUNT, WRITE_SKIP_COUNT, PROCESS_SKIP_COUNT, ROLLBACK_COUNT, LAST_UPDATED) values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Hibernate: INSERT INTO BATCH_STEP_EXECUTION_CONTEXT (SHORT_CONTEXT, SERIALIZED_CONTEXT, STEP_EXECUTION_ID) VALUES(?, ?, ?)
Hibernate: UPDATE BATCH_STEP_EXECUTION set START_TIME = ?, END_TIME = ?, STATUS = ?, COMMIT_COUNT = ?, READ_COUNT = ?, FILTER_COUNT = ?, WRITE_COUNT = ?, EXIT_CODE = ?, EXIT_MESSAGE = ?, VERSION = ?, READ_SKIP_COUNT = ?, PROCESS_SKIP_COUNT = ?, WRITE_SKIP_COUNT = ?, ROLLBACK_COUNT = ?, LAST_UPDATED = ? where STEP_EXECUTION_ID = ? and VERSION = ?
Hibernate: SELECT VERSION FROM BATCH_JOB_EXECUTION WHERE JOB_EXECUTION_ID=?
Hibernate: UPDATE BATCH_STEP_EXECUTION_CONTEXT SET SHORT_CONTEXT = ?, SERIALIZED_CONTEXT = ? WHERE STEP_EXECUTION_ID = ?
--Logger in --Spring batch--- expo --- retry----
java.lang.NullPointerException
    at com.XX.XX.XX.XX.RetrySubmitJob.execute(RetrySubmitJob.java:88)
    at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:386)
    at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:133)
    at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:264)
    at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:76)
    at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:367)
    at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:214)
    at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:143)
    at org.springframework.batch.core.step.tasklet.TaskletStep.doExecute(TaskletStep.java:250)
    at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:195)
    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:293)
    at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:120)
    at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:50)
    at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:114)

最佳答案

Spring Batch 中的容错机制不适用于自定义 Tasklet。它仅适用于基于 block 的处理。当使用您自己的自定义 Tasklet 实现时,期望您将实现您自己的容错逻辑。

关于java - 即使抛出 NullPointerException 后,Spring Batch 指数重试也不会启动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27513647/

相关文章:

java - 使用 Jersey2.0 访问 JerseyTest 中的 springbean

javascript - 使用嵌套映射的 JSON 对象反序列化,Java Spring

java - Spring 批处理文件编写器直接写入亚马逊 s3 存储,无需 PutObjectRequest

spring - 我希望 MultiResourceItemReader 处理的当前资源在 beforeStep 方法中可用

java - JVM 尝试加载一个未被调用的类

java - EJB - 注入(inject) bean 时出现 NullpointerException

java - 使用流从元组列表中生成列表元组

java - Paypal 定期付款 API - 工作流程

spring - Grails/Spring REQUIRES_NEW回滚外部事务

spring-boot - 在Spring Boot/Spring Batch应用程序上配置Atomikos的问题