Spring Batch 在流程中有两个步骤。为啥第二步永远不会运行,第一步是无限循环
Posted
技术标签:
【中文标题】Spring Batch 在流程中有两个步骤。为啥第二步永远不会运行,第一步是无限循环【英文标题】:Spring Batch with two Steps in flow. Why second step never run and first step is in infinite loopSpring Batch 在流程中有两个步骤。为什么第二步永远不会运行,第一步是无限循环 【发布时间】:2016-04-24 10:27:05 【问题描述】:我的要求:创建一个调度程序来定期调用批处理,并且在批处理内部,我需要两个步骤。 StepA 将开始运行,根据结果,StepB 将调用。 如果您查看控制台日志,您将看到 stepA 被多次调用,比如说,完全相同的时刻。根据@Scheduled(fixedRate=60000) 每分钟应该只有一个电话。我猜这个问题与调度程序没有关系,因为我删除了调度程序并且我遇到了类似的问题。其他相关问题是从未调用过 StepB。我试图创建customDecider(“...next(customDecider()”)并创建一个私有方法来返回JobExecutionDecider。似乎两者都没有生效。 我最好的猜测是池线程在 StepA 中导致了一些“无限循环”,因为我没有正确设置一些东西,但我没有找到可能是什么。
BatchConfig.java
/*@Bean
public JobExecutionDecider customDecider() throws Exception
return new CustomDecider();
*/
private JobExecutionDecider decider(boolean decision)
return(jobExecution, stepExecution) -> new FlowExecutionStatus(decision ? "OK" : "FAILED");
@Bean
public Job job(Step stepA, Step stepB)
return jobBuilderFactory.get("job1")
//.flow(stepA).on("FAILED").to(stepB).end().build();
.start(stepA)
.next(decider(true))
.on("FAILED")
.stop()
.from(stepA)
.next(stepB)
.build()
.build();
@Bean
public Step stepA(ItemReader<String> readerA, ItemWriter<String> writerA)
return stepBuilderFactory.get("stepA").<String, String> chunk(1)
.reader(readerA)
.writer(writerA)
.allowStartIfComplete(true)
.build();
@Bean
@StepScope
public ItemReader<String> readerA()
return new CustomItemReaderA();
@Bean
public ItemWriter<String> writerA()
return new CustomItemWriterA();
@Bean
public Step stepB(ItemReader<String> readerB, ItemWriter<String> writerB)
return stepBuilderFactory.get("stepB").<String, String> chunk(1)
.reader(readerB)
.writer(writerB)
.allowStartIfComplete(true)
.build();
@Bean
@StepScope
public ItemReader<String> readerB()
return new CustomItemReaderB();
@Bean
public ItemWriter<String> writerB()
return new CustomItemWriterB();
CustomDecider.java
public class CustomDecider implements JobExecutionDecider
@Override
public FlowExecutionStatus decide(JobExecution jobExecution,
StepExecution stepExecution)
return new FlowExecutionStatus("OK");
CustomItemReaderA
public class CustomItemReaderA implements ItemReader<String>
private static final Logger log = LoggerFactory.getLogger(CustomItemReaderA.class);
@Override
public String read() throws Exception, UnexpectedInputException,
ParseException, NonTransientResourceException
log.info("rA");
return "A";
CustomItemWriterA
public class CustomItemWriterA implements ItemWriter<String>
private static final Logger log = LoggerFactory.getLogger(CustomItemWriterA.class);
@Override
public void write(List<? extends String> items) throws Exception
log.info("wA");
CustomItemReaderB 和 CustomItemReaderB 与 Custom...A 相同,只是在 log.info 期间从 A 变为 B 字母并返回
控制台日志
2016-01-18 21:40:37.488 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemReaderA : rA
2016-01-18 21:40:37.488 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemWriterA : wA
2016-01-18 21:40:37.488 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemReaderA : rA
2016-01-18 21:40:37.488 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemWriterA : wA
2016-01-18 21:40:37.488 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemReaderA : rA
2016-01-18 21:40:37.488 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemWriterA : wA
2016-01-18 21:40:37.488 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemReaderA : rA
2016-01-18 21:40:37.488 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemWriterA : wA
2016-01-18 21:40:37.488 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemReaderA : rA
2016-01-18 21:40:37.488 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemWriterA : wA
2016-01-18 21:40:37.488 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemReaderA : rA
2016-01-18 21:40:37.488 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemWriterA : wA
2016-01-18 21:40:37.488 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemReaderA : rA
2016-01-18 21:40:37.488 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemWriterA : wA
2016-01-18 21:40:37.488 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemReaderA : rA
2016-01-18 21:40:37.488 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemWriterA : wA
2016-01-18 21:40:37.488 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemReaderA : rA
2016-01-18 21:40:37.488 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemWriterA : wA
2016-01-18 21:40:37.488 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemReaderA : rA
2016-01-18 21:40:37.488 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemWriterA : wA
2016-01-18 21:40:37.488 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemReaderA : rA
2016-01-18 21:40:37.488 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemWriterA : wA
2016-01-18 21:40:37.488 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemReaderA : rA
2016-01-18 21:40:37.488 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemWriterA : wA
2016-01-18 21:40:37.488 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemReaderA : rA
2016-01-18 21:40:37.488 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemWriterA : wA
2016-01-18 21:40:37.488 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemReaderA : rA
2016-01-18 21:40:37.488 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemWriterA : wA
2016-01-18 21:40:37.488 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemReaderA : rA
2016-01-18 21:40:37.488 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemWriterA : wA
2016-01-18 21:40:37.488 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemReaderA : rA
2016-01-18 21:40:37.488 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemWriterA : wA
2016-01-18 21:40:37.488 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemReaderA : rA
2016-01-18 21:40:37.488 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemWriterA : wA
2016-01-18 21:40:37.488 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemReaderA : rA
2016-01-18 21:40:37.488 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemWriterA : wA
2016-01-18 21:40:37.488 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemReaderA : rA
2016-01-18 21:40:37.488 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemWriterA : wA
2016-01-18 21:40:37.488 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemReaderA : rA
2016-01-18 21:40:37.488 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemWriterA : wA
2016-01-18 21:40:37.504 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemReaderA : rA
2016-01-18 21:40:37.504 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemWriterA : wA
2016-01-18 21:40:37.504 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemReaderA : rA
2016-01-18 21:40:37.504 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemWriterA : wA
2016-01-18 21:40:37.504 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemReaderA : rA
2016-01-18 21:40:37.504 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemWriterA : wA
2016-01-18 21:40:37.504 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemReaderA : rA
2016-01-18 21:40:37.504 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemWriterA : wA
2016-01-18 21:40:37.504 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemReaderA : rA
2016-01-18 21:40:37.504 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemWriterA : wA
2016-01-18 21:40:37.504 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemReaderA : rA
2016-01-18 21:40:37.504 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemWriterA : wA
2016-01-18 21:40:37.504 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemReaderA : rA
2016-01-18 21:40:37.504 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemWriterA : wA
2016-01-18 21:40:37.504 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemReaderA : rA
2016-01-18 21:40:37.504 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemWriterA : wA
2016-01-18 21:40:37.504 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemReaderA : rA
2016-01-18 21:40:37.504 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemWriterA : wA
2016-01-18 21:40:37.504 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemReaderA : rA
2016-01-18 21:40:37.504 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemWriterA : wA
2016-01-18 21:40:37.504 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemReaderA : rA
2016-01-18 21:40:37.504 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemWriterA : wA
2016-01-18 21:40:37.504 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemReaderA : rA
2016-01-18 21:40:37.504 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemWriterA : wA
2016-01-18 21:40:37.504 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemReaderA : rA
2016-01-18 21:40:37.504 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemWriterA : wA
2016-01-18 21:40:37.504 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemReaderA : rA
2016-01-18 21:40:37.504 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemWriterA : wA
2016-01-18 21:40:37.519 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemReaderA : rA
2016-01-18 21:40:37.519 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemWriterA : wA
2016-01-18 21:40:37.519 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemReaderA : rA
2016-01-18 21:40:37.519 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemWriterA : wA
2016-01-18 21:40:37.519 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemReaderA : rA
2016-01-18 21:40:37.519 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemWriterA : wA
2016-01-18 21:40:37.519 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemReaderA : rA
2016-01-18 21:40:37.519 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemWriterA : wA
2016-01-18 21:40:37.519 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemReaderA : rA
2016-01-18 21:40:37.519 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemWriterA : wA
2016-01-18 21:40:37.519 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemReaderA : rA
2016-01-18 21:40:37.519 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemWriterA : wA
2016-01-18 21:40:37.519 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemReaderA : rA
2016-01-18 21:40:37.519 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemWriterA : wA
2016-01-18 21:40:37.519 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemReaderA : rA
2016-01-18 21:40:37.519 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemWriterA : wA
2016-01-18 21:40:37.519 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemReaderA : rA
2016-01-18 21:40:37.519 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemWriterA : wA
2016-01-18 21:40:37.519 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemReaderA : rA
2016-01-18 21:40:37.519 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemWriterA : wA
2016-01-18 21:40:37.519 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemReaderA : rA
2016-01-18 21:40:37.519 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemWriterA : wA
2016-01-18 21:40:37.519 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemReaderA : rA
2016-01-18 21:40:37.519 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemWriterA : wA
2016-01-18 21:40:37.519 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemReaderA : rA
2016-01-18 21:40:37.519 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemWriterA : wA
2016-01-18 21:40:37.519 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemReaderA : rA
2016-01-18 21:40:37.519 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemWriterA : wA
2016-01-18 21:40:37.519 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemReaderA : rA
2016-01-18 21:40:37.519 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemWriterA : wA
2016-01-18 21:40:37.519 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemReaderA : rA
2016-01-18 21:40:37.519 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemWriterA : wA
2016-01-18 21:40:37.519 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemReaderA : rA
2016-01-18 21:40:37.519 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemWriterA : wA
2016-01-18 21:40:37.519 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemReaderA : rA
2016-01-18 21:40:37.519 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemWriterA : wA
2016-01-18 21:40:37.519 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemReaderA : rA
2016-01-18 21:40:37.519 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemWriterA : wA
2016-01-18 21:40:37.519 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemReaderA : rA
2016-01-18 21:40:37.519 INFO 7340 --- [pool-2-thread-1] com.example.CustomItemWriterA : wA
and so on ...
调度器
@Component
public class QueueScheduler
private static final Logger log = LoggerFactory
.getLogger(QueueScheduler.class);
private Job job;
private JobLauncher jobLauncher;
@Autowired
public QueueScheduler(JobLauncher jobLauncher, @Qualifier("job") Job job)
this.job = job;
this.jobLauncher = jobLauncher;
@Scheduled(fixedRate=60000)
public void runJob()
try
jobLauncher.run(job, new JobParameters());
catch(Exception ex)
log.info(ex.getMessage());
【问题讨论】:
【参考方案1】:问题在于您的CustomItemReaderA
。您需要告诉 Reader 何时停止“读取”数据。如果您按照下面给出的修改阅读器,执行将按预期进行。
public class CustomItemReaderA implements ItemReader<String>
private static final Logger log = LoggerFactory
.getLogger(CustomItemReaderA.class);
private int readCount = 0;
@Override
public String read() throws Exception, UnexpectedInputException,
ParseException, NonTransientResourceException
log.info("Inside CustomItemReaderA");
if (readCount == 1)
return null;
readCount++;
return "Read CustomItemReaderA";
【讨论】:
那么,返回 null 是停止 CustomItemReaderA 的唯一方法吗?为了避免重复调用(第二个仅用于返回 null),如果第一次成功,我可以创建一个逻辑以返回 null。如果 ItemReader 的设计考虑到了这样的想法,那么对于这种情况是可以的,但是假设有一个 CustomItemProcessorA 期望从 CustomItemReaderA 读取数据,而 CustomItemWriterA 期望从 CustomItemReaderB 处理数据,则不会返回 null 破坏此类批处理的目的还是强迫我做出一个丑陋的解决方法?还是必须至少阅读两次? 其他疑问非常接近最后一个:在我的要求中,我必须根据 CustomItemReaderA 决定是否调用 CustomItemReaderB。为此,我知道我必须以某种方式使用 JobExecutionDecider 并通过 ...on(FlowExecutionStatus) 决定它。如何更改 CustomItemReaderA 的状态?好吧,考虑两个选项(失败或成功),我可以使用 return null 表示成功并抛出异常表示失败。但是,让我们考虑三个选项?如何从 CustomItemReaderA 返回三种状态之一?我可以从 CustomItemReaderA 更改 FlowExecutionStatus 吗?以上是关于Spring Batch 在流程中有两个步骤。为啥第二步永远不会运行,第一步是无限循环的主要内容,如果未能解决你的问题,请参考以下文章
(Spring Batch)为啥表'batch_job_instance'已经存在?
Spring Batch JpaItemWriter vs HibernateItemWriter 以及为啥在使用 HibernateItemWriter 时需要 HibernateTransacti
为啥在尝试对整个 Spring Batch Job 进行单元测试时出现此错误?没有可用的“org.springframework.batch.core.Job”类型的合格bean