Spring 无限循环中的批处理作业 运行

Spring Batch Job Running in Infinite loop

我正在处理简单的 Spring 批处理作业。当我在无限循环中启动它的 运行ning 作业时。它不会停止。根据我的调度程序时间,它应该每 10 秒后 运行。但是当工作开始时它不会停止。它只是分别从 reader、处理器和写入器打印系统输出。我正在使用 reader、处理器和编写器创建作业。我正在通过注释进行所有配置。不是 xml。

这里是批量配置

@Configuration
@EnableBatchProcessing
@EnableScheduling
public class BatchJobConfig {

    @Autowired
    private JobBuilderFactory jobBuilderFactory;

    @Autowired
    private StepBuilderFactory stepBuilderFactory;

    @Autowired
    private SimpleJobLauncher jobLauncher;

    @Scheduled(cron="*/10 * * * * *")
    public void perform() throws Exception 
    {
        Job job = job(step1());
        JobParameters jobParameters = new JobParameters();
        jobLauncher.run(job, jobParameters);        
    }

    @Bean
    public Step step1() 
    {
        return stepBuilderFactory.get("step1").<Person, Person> chunk(1)
                .reader(reader()).processor(processor()).writer(writer())
                .build();
    }

    @Bean
    public Job job(Step step1) throws Exception 
    {
        return jobBuilderFactory.get("job")
                .incrementer(new RunIdIncrementer()).flow(step1())
                .end().build();
    }

    @Bean
    public DataSource dataSource()
    {
        EmbeddedDatabaseBuilder embeddedDatabaseBuilder = new EmbeddedDatabaseBuilder();
        return embeddedDatabaseBuilder.addScript("classpath:org/springframework/batch/core/schema-drop-hsqldb.sql")
                .addScript("classpath:org/springframework/batch/core/schema-hsqldb.sql")
                .setType(EmbeddedDatabaseType.HSQL)
                .build();
    }

    @Bean
    public PersonReader reader() {
        return new PersonReader();
    }
    @Bean
    public PersonWriter writer() {
        return new PersonWriter();
    }
    @Bean
    public PersonProcessor processor() {
        return new PersonProcessor();
    }

    @Bean
    public MapJobRepositoryFactoryBean mapJobRepositoryFactory(ResourcelessTransactionManager txManager) throws Exception  {    
        MapJobRepositoryFactoryBean factory = new MapJobRepositoryFactoryBean(txManager);
        factory.afterPropertiesSet();
        return factory;
    }
    @Bean
    public JobRepository jobRepository(MapJobRepositoryFactoryBean factory) throws Exception {
        return factory.getObject();
    }
    @Bean
    public SimpleJobLauncher jobLauncher(JobRepository jobRepository) {
        SimpleJobLauncher launcher = new SimpleJobLauncher();
        launcher.setJobRepository(jobRepository);
        return launcher;
    }
    @Bean
    public ResourcelessTransactionManager transactionManager() {
        return new ResourcelessTransactionManager();
    }
}

PersonReader.java

  public class PersonReader implements ItemReader<Person> {
    @Override
    public Person read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException {
        Person person = new Person();
        System.out.println("In PersonReader");
        return person;
    }
}

PersonWriter.java

public class PersonWriter implements ItemWriter<Person> {
    @Override
    public void write(List<? extends Person> arg0) throws Exception {
        System.out.println("IN PersonWriter");
    }
}

PersonProcessor.java

public class PersonProcessor implements ItemProcessor<Person, Person> {
    @Override
    public Person process(Person arg0) throws Exception  {
        System.out.println("In PersonProcessor");
        return arg0;
    }
}

一步将 运行 直到您的 ItemReader returns 无效。在你的情况下,你的 ItemReader 永远不会(它总是 returns 一个新的 Person)所以它永远不会结束。

添加一个标志来抵抗reader到运行的无限循环

Reader:

public class PersonReader implements ItemReader<Person> {
    private boolean batchJobState = false;

    @Override
    public Person read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException {
        if(!batchJobState){
            Person person = new Person();
            System.out.println("In PersonReader");
            batchJobState=true;
            return person;
        }
        return null;
    }
}

是否有人来到这里遇到同样的错误,但是使用 FlatFileItemReader(什么是 Reader 实现),看看您是否有多个 step同名.

我的 Spring 批处理项目有两个同名步骤。这两个执行中的最后一步导致死循环。

使用接口StepExecutionListener。 这将提供两种方法

在实例级别使用变量布尔值 FLAG。

public class PersonReader 实现 ItemReader,StepExecutionListener { 私人布尔值 jobState = false;

@Override
public Person read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException {
    if(!**jobState**){
        Person person = new Person();
        System.out.println("In PersonReader");
        jobState=true;
        return person;
    }
    return null;
}

}

@Override public void beforeStep(StepExecution stepExecution) { }

@Override public ExitStatus afterStep(StepExecution stepExecution) {

    **jobState** = false;
    return stepExecution.getExitStatus();
}

}

  1. 在 read() 方法执行之前 beforeStep 方法执行。
  2. read() 方法将标志设置为 true。
  3. read()方法执行后,afterStep方法将执行并设置flag为false。
  4. 每当您的调度程序在 10 分钟后开始作业时,该值最初将为 false。