-1

Taking as reference Retry not working with Spring Batch with Java Config I checked in the code of the following spring batch reader retry example https://github.com/atulkulkarni18/spring-batch-reader-retry and the retry functionality works as expected. However implementing the CommandLineRunner (as showed in the below code), the retry functionality doesn't work... can anybody advise?

@SpringBootApplication
@EnableBatchProcessing
@Data
@NoArgsConstructor
@AllArgsConstructor
@EnableRetry
public class Stack56170179Application implements CommandLineRunner {

    @Autowired
    JobLauncher jobLauncher;

    @Autowired
    private JobBuilderFactory jobs;

    @Autowired
    private StepBuilderFactory steps;

    public static void main(String[] args) {
        SpringApplication.run(Stack56170179Application.class, args);
    }

    @Bean
    public Job job() {
        return jobs.get("myJob").start(step1()).build();
    }

    @Bean
    public Step step1() {
        return steps.get("step1").<String, String>chunk(1).reader(myReader())
                .processor(myProcessor())
                .writer(myWriter())
                .build();
    }

    @Override
    public void run(String... args) throws Exception {
        JobParameters params = new JobParametersBuilder()
                .addString("JobID", String.valueOf(System.currentTimeMillis()))
                .toJobParameters();
        jobLauncher.run(job(), params);
    }

    @Bean
    @StepScope
    public MyReader myReader() {
        return new MyReader();
    }

    @Bean
    @StepScope
    public MyProcessor myProcessor() {
        return new MyProcessor();
    }

    @Bean
    @StepScope
    public MyWriter myWriter() {
        return new MyWriter();
    }

}

public class MyReader implements ItemReader<String> {

    private long count;
    private long retryCount;

    @Override
    @Retryable(include = { MyException.class }, maxAttempts = 5)
    public String read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException {
        final long value = count;
        System.out.println("MyReader : " + value);

        if (value == 3 && retryCount <= 2) {
            retryCount++;
            System.out.println("****");
            Thread.sleep(500);
            throw new MyException();
        }

        if (value < 5) {
            count++;
            Thread.sleep(500);
            return String.valueOf(value);
        } else {
            return null;
        }
    }
}


public class MyProcessor implements ItemProcessor<String, String> {

    @Override
    public String process(final String arg0) throws Exception {
        System.out.println("MyProcessor : " + arg0);
        return arg0;
    }

}


public class MyWriter implements ItemWriter<String> {

    @Override
    public void write(final List<? extends String> arg0) throws Exception {
        System.out.println("MyWriter : " + arg0);
    }

}

public class MyException extends Exception {

    private static final long serialVersionUID = 1L;

}

Expected output:

MyReader : 0
MyProcessor : 0
MyWriter : [0]
MyReader : 1
MyProcessor : 1
MyWriter : [1]
MyReader : 2
MyProcessor : 2
MyWriter : [2]
MyReader : 3
****
MyReader : 3
****
MyReader : 3
****
MyReader : 3
MyProcessor : 3
MyWriter : [3]
MyReader : 4
MyProcessor : 4
MyWriter : [4]
MyReader : 5
JeromeTech
  • 13
  • 4
  • From the code you shared, what are you expecting to be retried? – Mahmoud Ben Hassine Feb 24 '20 at 08:32
  • Sorry, I added the missing classes and following is the expected output: MyReader : 0 MyProcessor : 0 MyWriter : [0] MyReader : 1 MyProcessor : 1 MyWriter : [1] MyReader : 2 MyProcessor : 2 MyWriter : [2] MyReader : 3 **** MyReader : 3 **** MyReader : 3 **** MyReader : 3 MyProcessor : 3 MyWriter : [3] MyReader : 4 MyProcessor : 4 MyWriter : [4] MyReader : 5 – JeromeTech Feb 25 '20 at 03:05
  • Put the expected output into the question. – Stephen C Feb 25 '20 at 03:41
  • Hi Stephen, I added it to the question – JeromeTech Feb 26 '20 at 16:36

1 Answers1

1

The problem is not with CommandLineRunner but with the MyReader object. You have created plain object and it is not Spring managed. Try creating spring managed bean like

 @Bean
 @StepScope
 public MyReader myReader() {
    return new MyReader();
 }

and use myReader() inside method step1() instead of new MyReader().

Hope this help!

  • Hi Neetesh, I applied the change you commented (refer to the original post) but it didn't work. Btw, I added to the application.properties file spring.batch.job.enabled=false so the that batch is not executed at the app startup but executed through the run(String... args) method. Doing that the execution is thrown and retry is not executed. – JeromeTech Feb 25 '20 at 03:23
  • I have added the code to github with the output. Please check https://github.com/neeteshbhardwaj/batch-retry-command-line-runner – Neetesh Bhardwaj Feb 25 '20 at 06:04
  • Please check your pom and java version. FYI, I am using java8. – Neetesh Bhardwaj Feb 25 '20 at 06:07
  • Neetesh, thank you so much for your example, it works awesome; my mistake, after I checked deeply my project I realized I didn't have the @EnableRetry annotation. – JeromeTech Feb 26 '20 at 16:40
  • Btw, my final goal is to use JdbcCursorItemReader in my Reader and I was able to do it. For practicality, I created an example with FlatFileItemReader and it works very well https://github.com/jeronimogalicia/batch-retry-flatfile-item-reader – JeromeTech Feb 26 '20 at 16:43