首页 > 解决方案 > 可重试和恢复未在 SpringBatch 步骤中执行

问题描述

在 Spring 批处理应用程序中,我有一组 TaskletSteps 和 Steps。在运行期间,Spring 批处理从不执行 Retryable 和 Recovery 块,而是抛出错误并退出。

期望的行为:在 RuntimeException 上,我希望 Retryable 能够工作,并且代码应该重试方法执行 3 次。

步:

@Bean
public Step processCaseClaimsStep(ItemProcessor<CaseClaim, CaseClaimResponse> processor,
                                 ItemWriter<CaseClaimResponse> writer) {
    return this.stepBuilderFactory.get("processCaseClaimsStep")
            .<CaseClaim, CaseClaimResponse>chunk(10000)
            .reader(reader(null, null, null))
            .processor(processor)
            .writer(writer)
            .faultTolerant()
            .listener(processClaimsListener())
            .listener(redEventExecutionListener)
            .build();
}

处理器类:


 int retries = 0;
 @Retryable(maxAttemptsExpression = "4", backoff = @Backoff(delayExpression = "20_000",
        multiplierExpression = "3", maxDelayExpression = "100_000"))
 public void populateCaseClientData(CaseClaim caseClaim) {
         log.info("Entering block");
         if(retries>0) {
             log.info("--Retrying populateClientData. Retry count: " + retries);
         } else {
             log.info("The code has started!");
             retries++;
         }
         throw new RuntimeException();
    
 }

 @Recover
 public void recover(Exception e, CaseClaim caseClaim) {
     // Some logging operations.
 }

控制台日志:

2021-10-12 21:14:05.909  INFO 25319 --- [ taskExecutor-1] c.c.p.r.component.ClaimProcessor           : -Entering block
2021-10-12 21:14:05.909  INFO 25319 --- [ taskExecutor-1] c.c.p.r.component.ClaimProcessor           : The code has started!
2021-10-12 21:14:17.428 ERROR 25319 --- [ taskExecutor-1] o.s.batch.core.step.AbstractStep         : Encountered an error executing step processCaseClaimsStep in job Case MainProject
 
org.springframework.retry.RetryException: Non-skippable exception in recoverer while processing; nested exception is java.lang.RuntimeException
                at org.springframework.batch.core.step.item.FaultTolerantChunkProcessor$2.recover(FaultTolerantChunkProcessor.java:299) ~[spring-batch-core-4.2.4.RELEASE.jar:4.2.4.RELEASE]
                at org.springframework.retry.support.RetryTemplate.handleRetryExhausted(RetryTemplate.java:512) ~[spring-retry-1.2.5.RELEASE.jar:na]
                at org.springframework.retry.support.RetryTemplate.doExecute(RetryTemplate.java:351) ~[spring-retry-1.2.5.RELEASE.jar:na]
                at org.springframework.retry.support.RetryTemplate.execute(RetryTemplate.java:211) ~[spring-retry-1.2.5.RELEASE.jar:na]
                at org.springframework.batch.core.step.item.BatchRetryTemplate.execute(BatchRetryTemplate.java:217) ~[spring-batch-core-4.2.4.RELEASE.jar:4.2.4.RELEASE]
                at org.springframework.batch.core.step.item.FaultTolerantChunkProcessor.transform(FaultTolerantChunkProcessor.java:308) ~[spring-batch-core-4.2.4.RELEASE.jar:4.2.4.RELEASE]
                at org.springframework.batch.core.step.item.SimpleChunkProcessor.process(SimpleChunkProcessor.java:210) ~[spring-batch-core-4.2.4.RELEASE.jar:4.2.4.RELEASE]
                at org.springframework.batch.core.step.item.ChunkOrientedTasklet.execute(ChunkOrientedTasklet.java:77) ~[spring-batch-core-4.2.4.RELEASE.jar:4.2.4.RELEASE]
                at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:407) ~[spring-batch-core-4.2.4.RELEASE.jar:4.2.4.RELEASE]
                at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:331) ~[spring-batch-core-4.2.4.RELEASE.jar:4.2.4.RELEASE]
                at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140) ~[spring-tx-5.2.8.RELEASE.jar:5.2.8.RELEASE]
                at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:273) ~[spring-batch-core-4.2.4.RELEASE.jar:4.2.4.RELEASE]
                at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:82) ~[spring-batch-core-4.2.4.RELEASE.jar:4.2.4.RELEASE]
                at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:375) ~[spring-batch-infrastructure-4.2.4.RELEASE.jar:4.2.4.RELEASE]
                at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:215) ~[spring-batch-infrastructure-4.2.4.RELEASE.jar:4.2.4.RELEASE]
                at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:145) ~[spring-batch-infrastructure-4.2.4.RELEASE.jar:4.2.4.RELEASE]
                at org.springframework.batch.core.step.tasklet.TaskletStep.doExecute(TaskletStep.java:258) ~[spring-batch-core-4.2.4.RELEASE.jar:4.2.4.RELEASE]
                at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:208) ~[spring-batch-core-4.2.4.RELEASE.jar:4.2.4.RELEASE]
                at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:148) ~[spring-batch-core-4.2.4.RELEASE.jar:4.2.4.RELEASE]
                at org.springframework.batch.core.job.flow.JobFlowExecutor.executeStep(JobFlowExecutor.java:68) ~[spring-batch-core-4.2.4.RELEASE.jar:4.2.4.RELEASE]
                at org.springframework.batch.core.job.flow.support.state.StepState.handle(StepState.java:68) ~[spring-batch-core-4.2.4.RELEASE.jar:4.2.4.RELEASE]
                at org.springframework.batch.core.job.flow.support.SimpleFlow.resume(SimpleFlow.java:169) ~[spring-batch-core-4.2.4.RELEASE.jar:4.2.4.RELEASE]
                at org.springframework.batch.core.job.flow.support.SimpleFlow.start(SimpleFlow.java:144) ~[spring-batch-core-4.2.4.RELEASE.jar:4.2.4.RELEASE]
                at org.springframework.batch.core.job.flow.FlowJob.doExecute(FlowJob.java:137) ~[spring-batch-core-4.2.4.RELEASE.jar:4.2.4.RELEASE]
                at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:319) ~[spring-batch-core-4.2.4.RELEASE.jar:4.2.4.RELEASE]
                at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:147) ~[spring-batch-core-4.2.4.RELEASE.jar:4.2.4.RELEASE]
                at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[na:na]
                at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[na:na]
                at java.base/java.lang.Thread.run(Thread.java:830) ~[na:na]
Caused by: java.lang.RuntimeException: null
                at com.myclasshealth.packageName.component.CaseProcessor.populateCaseClientData(CaseProcessor.java:92) ~[main/:na]
                at com.myclasshealth.packageName.component.CaseProcessor.process(CaseProcessor.java:57) ~[main/:na]
                at com.myclasshealth.packageName.component.CaseProcessor.process(CaseProcessor.java:31) ~[main/:na]
                at com.myclasshealth.packageName.component.CaseProcessor$$FastClassBySpringCGLIB$$e5db3e0d.invoke(<generated>) ~[main/:na]
                at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.2.8.RELEASE.jar:5.2.8.RELEASE]
                at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:771) ~[spring-aop-5.2.8.RELEASE.jar:5.2.8.RELEASE]
                at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.2.8.RELEASE.jar:5.2.8.RELEASE]
                at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749) ~[spring-aop-5.2.8.RELEASE.jar:5.2.8.RELEASE]
                at org.springframework.retry.annotation.AnnotationAwareRetryOperationsInterceptor.invoke(AnnotationAwareRetryOperationsInterceptor.java:156) ~[spring-retry-1.2.5.RELEASE.jar:na]
                at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.8.RELEASE.jar:5.2.8.RELEASE]
                at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749) ~[spring-aop-5.2.8.RELEASE.jar:5.2.8.RELEASE]
                at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:691) ~[spring-aop-5.2.8.RELEASE.jar:5.2.8.RELEASE]
                at com.myclasshealth.packageName.component.CaseProcessor$$EnhancerBySpringCGLIB$$60a1968b.process(<generated>) ~[main/:na]
                at com.myclasshealth.packageName.component.CaseProcessor$$FastClassBySpringCGLIB$$e5db3e0d.invoke(<generated>) ~[main/:na]
                at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.2.8.RELEASE.jar:5.2.8.RELEASE]
                at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:771) ~[spring-aop-5.2.8.RELEASE.jar:5.2.8.RELEASE]
                at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.2.8.RELEASE.jar:5.2.8.RELEASE]
                at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749) ~[spring-aop-5.2.8.RELEASE.jar:5.2.8.RELEASE]
                at org.springframework.retry.annotation.AnnotationAwareRetryOperationsInterceptor.invoke(AnnotationAwareRetryOperationsInterceptor.java:156) ~[spring-retry-1.2.5.RELEASE.jar:na]
                at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.8.RELEASE.jar:5.2.8.RELEASE]
                at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749) ~[spring-aop-5.2.8.RELEASE.jar:5.2.8.RELEASE]
                at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:691) ~[spring-aop-5.2.8.RELEASE.jar:5.2.8.RELEASE]
                at com.myclasshealth.packageName.component.CaseProcessor$$EnhancerBySpringCGLIB$$1ccf9e5f.process(<generated>) ~[main/:na]
                at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
                at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
                at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
                at java.base/java.lang.reflect.Method.invoke(Method.java:567) ~[na:na]
                at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) ~[spring-aop-5.2.8.RELEASE.jar:5.2.8.RELEASE]
                at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198) ~[spring-aop-5.2.8.RELEASE.jar:5.2.8.RELEASE]
                at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.2.8.RELEASE.jar:5.2.8.RELEASE]
                at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:136) ~[spring-aop-5.2.8.RELEASE.jar:5.2.8.RELEASE]
                at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:124) ~[spring-aop-5.2.8.RELEASE.jar:5.2.8.RELEASE]
                at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.8.RELEASE.jar:5.2.8.RELEASE]
                at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) ~[spring-aop-5.2.8.RELEASE.jar:5.2.8.RELEASE]
                at com.sun.proxy.$Proxy129.process(Unknown Source) ~[na:na]
                at org.springframework.batch.core.step.item.SimpleChunkProcessor.doProcess(SimpleChunkProcessor.java:134) ~[spring-batch-core-4.2.4.RELEASE.jar:4.2.4.RELEASE]
                at org.springframework.batch.core.step.item.FaultTolerantChunkProcessor$1.doWithRetry(FaultTolerantChunkProcessor.java:239) ~[spring-batch-core-4.2.4.RELEASE.jar:4.2.4.RELEASE]
                at org.springframework.retry.support.RetryTemplate.doExecute(RetryTemplate.java:287) ~[spring-retry-1.2.5.RELEASE.jar:na]
                ... 26 common frames omitted

Spring 可重试版本: org.springframework.retry:spring-retry:1.2.5-RELEASE

有什么建议么?

标签: javaspringspring-bootspring-batch

解决方案


推荐阅读