Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Spring 流动中有两个步骤的弹簧批次。为什么第二步从未运行,而第一步处于无限循环中_Spring_Spring Boot_Spring Batch_Spring Scheduled - Fatal编程技术网

Spring 流动中有两个步骤的弹簧批次。为什么第二步从未运行,而第一步处于无限循环中

Spring 流动中有两个步骤的弹簧批次。为什么第二步从未运行,而第一步处于无限循环中,spring,spring-boot,spring-batch,spring-scheduled,Spring,Spring Boot,Spring Batch,Spring Scheduled,我的要求:创建一个调度器来定期调用批处理,在批处理内部,我需要两个步骤。StepA将开始运行,并根据结果调用StepB。 如果您查看控制台日志,您将看到stepA在同一时刻被多次调用。根据@Scheduled(fixedRate=60000),每分钟应该只有一个电话。我想这个问题与Scheduller没有关系,因为我删除了Scheduling,并且遇到了类似的问题。另一个相关的问题是StepB从未被调用。我试图创建customDecider(“…next(customDecider()”),并创

我的要求:创建一个调度器来定期调用批处理,在批处理内部,我需要两个步骤。StepA将开始运行,并根据结果调用StepB。 如果您查看控制台日志,您将看到stepA在同一时刻被多次调用。根据@Scheduled(fixedRate=60000),每分钟应该只有一个电话。我想这个问题与Scheduller没有关系,因为我删除了Scheduling,并且遇到了类似的问题。另一个相关的问题是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();

   }
调度程序

@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());
          }
   }
}

问题出在您的
CustomItemReaderA
上。您需要告诉读取器何时停止“读取”数据。如果您按照下面给出的方式修改读取器,执行将按预期进行

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";
    }
}
公共类CustomItemReaderA实现ItemReader{
专用静态最终记录器日志=LoggerFactory
.getLogger(CustomItemReaderA.class);
私有int readCount=0;
@凌驾
public String read()引发异常,UnexpectedInputException,
ParseException,非TransientResourceException{
log.info(“内部CustomItemReaderA”);
if(readCount==1){
返回null;
}
readCount++;
返回“Read CustomItemReaderA”;
}
}

那么,返回null是否是停止CustomItemReaderA的唯一方法?以避免重复调用(第二种方法仅用于返回null)如果第一次很成功,我可以创建一个逻辑来返回null。如果ItemReader的设计考虑到了这样的想法,这对于这个场景来说是可以的,但是,假设有一个CustomItemProcessor期望从CustomItemReaderA读取数据,CustomItemWriterA期望从CustomItemReaderB处理数据,则不会返回n你会破坏这一批的目的,或者强迫我做一个难看的变通方法?或者必须至少读两遍吗?其他疑问非常接近最后一个:在我的要求中,我必须根据CustomItemReaderB决定是否调用CustomItemReaderB。为此,我理解我必须使用某种方式的作业执行决策器,并通过……来决定(FlowExecutionStatus)。如何从CustomItemReaderA更改状态?好吧,只考虑两个选项(失败或成功)我可以使用return null表示well successful,使用throw exception表示failed。但是,让我们考虑三个选项?如何从CustomItemReaderA返回三个状态中的一个?我可以从CustomItemReaderA更改FlowExecutionStatus吗?
@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());
          }
   }
}
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";
    }
}