Spring Batch Job Running in Infinite loop

11,249

Solution 1

A step will run until your ItemReader returns null. In your case, your ItemReader never does (it always returns a new Person) so it will never end.

Solution 2

Add a flag to resist the reader to run in infinite loop.

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;
    }
}

Solution 3

Is someone came here with the same error, but using FlatFileItemReader (what is a Reader implementation), see if you have more than one step with the same name.

I had two steps on my Spring Batch project with the same name. The last step among this two executed caused a infinite loop.

Solution 4

Use the interface StepExecutionListener. This will provide two methods

Use a variable boolean FLAG at instance level.

public class PersonReader implements ItemReader,StepExecutionListener { private boolean 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. before read() method execution beforeStep method executes.
  2. read() method set a flag to true.
  3. after read() method execution, afterStep method will executes and set the flag as false.
  4. Whenever your scheduler start the job after 10 minutes the value will be false initially.
Share:
11,249
MRX
Author by

MRX

it's Easy, if you Try.

Updated on June 06, 2022

Comments

  • MRX
    MRX almost 2 years

    I am working on simple Spring Batch Job. When I launch job its running in infinite loop. It doesn't stop. According to my scheduler time it should run after every 10 seconds. But when job starts it doesn't stop. Its just keeps printing sysouts from reader, processor and writer respectively. I am creating job with reader, processor and writer. And I am doing all configuration by annotations. Not by xml.

    Here is Batch Configuration

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