1

I want to achieve a tasklet that can skip exceptions and rollback the transaction properly and I don't see a way to accomplish both things.

My tasklet reads from a queue of ids that gets filled in the constructor. In each invocation of the execute method one id is processed and depending on if the queue still has elements to be processed or not a RepeatStatus.FINISHED or RepeatStatus.CONTINUABLE is returned. I am using a tasklet instead of a chunk because the processing of each element is fairly complicated and implies doing multiple queries, instantiation of a lot of objects that all gets written to the database later.

The main problem is if I define a try/catch block to wrap the implementation, I can skip exceptions without problems and still be able to re-execute the tasklet with the next element in the queue, but the problem is that everything gets saved in the database. On the other hand, even if the processing of an element is done correctly without problems, if the commit fails for whatever reason, as the error occurs outside the reach and control of my code, the exception is not caught by my code and the tasklet execution is finished without the possibility to skip and continue with the next element of the queue.

This is a simplified schema of my tasklet:

public MyTasklet() {
    elementsIds = myRepo.findProcessableElements();
    
}

@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) {
    Long id = elementsIds.remove();
    try {
        // Business logic
    } catch (Exception e) {
        // is there a way to tell the framework to rollback ?
        LOG.error("error ...", e);
    }
    if (elementsIds.isEmpty()) {
        return RepeatStatus.FINISHED;
    } else {
        return RepeatStatus.CONTINUABLE;
    }
}

Is there a way to achieve these two requirements with tasklets:

  • To be able to tell the framework to rollback the transaction if an exception is caught in the implementation of the execute method
  • To continue the execution (consecutive calls) of the tasklet if a commit fails
Youssef Khloufi
  • 685
  • 3
  • 13
  • 24
  • `is there a way to tell the framework to rollback ?`: at this point, if you want to tell the framework to rollback, just re-throw the exception (or don't catch it). Is this what you are looking for? What would be the difference between programmatically "telling the framework to rollback" at that point versus throwing the exception? – Mahmoud Ben Hassine Jul 20 '20 at 11:49
  • If I throw the exception then I am not skipping anything, further calls to the tasklet will not happen, the execution flow will be terminated and a rollback will be done automatically. The thing is that I want to skip any exception that can happen in the tasklet and to rollback and on the other hand if everything goes perfect in the tasklet if during the transaction commit anything goes wrong I want to continue with the further calls to the tasklet and not to abort like what the TaskletStep is doing now – Youssef Khloufi Jul 20 '20 at 13:10
  • The closest you can get is to use a custom `TransactionAttribute` and return false in `rollbackOn` for the type of exception you need to rollback on: https://github.com/spring-projects/spring-batch/blob/a7092a21e428cf904f210aff2682b518dc3649c5/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/TaskletStepTests.java#L894-L900. This requires doing whatever you want in the catch block to skip the current item and then re-throw the exception. – Mahmoud Ben Hassine Jul 20 '20 at 14:52

0 Answers0