Reputation: 224
I have a spring batch job which has multiple steps.
Step 1 : Loads 10 records from the database. (Tasklet does that job)
Step 2: Chunk Oriented processing in configured here using ItemReader,ItemProcessor,ItemWriter implementations with commit -interval =1
Now as I understand , for every record this would happen
Begin Transaction ( Read - Process - Write ) Commit Tx
My problem is imagine it processed six records and now with the 7th Record it got an exception in the ItemProcessor Implementation, It tries to rollback but not able to rollback due to transaction in unknown state
Even if it is not able to rollback tx for 7th record it does not processes 8th,9th,10th record at all and job is STOPPED.
Note: ItemProcessor implementation is calling services (@Service annotated) which are marked as transactional using @Transactional(readOnly=false) annotation.
Please suggest the solution.
ItemProcessor Code Below
public Long process(LoanApplication loanApplication)throws Exception {
Long createLoan = null;
LoanStatus loanStatus = null;
StaffUser user = staffUserService.getStaffUserByName(Constants.AUTO_USER);
String notes = null;
try{
try{
loanValidationService.validate(loanApplication);
loanStatus=LoanStatus.U;
}catch(LoanValidationException e){
loanStatus=LoanStatus.UC;
notes=e.getMessage();
}
dataLoadLoanManagementService.setText(notes);
createLoan = dataLoadLoanManagementService.createLoan(loanApplication, user,loanStatus);
}catch(Exception le){
logger.error("Error creating the loan application ; Parent Application Ref : "
+ loanApplication
+ " with status as " +(loanStatus!=null ?loanStatus.getStatus():loanStatus)
+"\n"
+" School Ref :"
+ loanApplication.getSchoolRef()
+"\n"
+" Client Details :"
+loanApplication.getClientDetails()
+ "Error Details: " + ExceptionUtils.getStackTrace(le));
}
return createLoan;
}
Even with Skippable Exception Classes configured this does not work.
To explain bit more i get Persistence Exception in Item Processor and i catch it , therefore Spring batch executes the writer but after writer execution i get the exception below
INFO 06-21 11:38:00 Commit failed while step execution data was already updated. Reverting to old version. (TaskletStep.java:342)
ERROR 06-21 11:38:00 Rolling back with transaction in unknown state (TaskletStep.java:351)
ERROR 06-21 11:38:00 Encountered an error executing the step (AbstractStep.java:212)
org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Transaction marked as rollbackOnly
Upvotes: 2
Views: 23431
Reputation: 131
check transaction propagation option at loanValidationService.validate
Guess from "Transaction marked as rollbackOnly", "Commit failed while step execution data was already updated"
Current transaction was rollbacked and parent Transaction should be commit but transaction already over.
if chunk's transaction is same at LoanValidationService.validate
change propagation option to REQUIRES_NEW
following article may help to understand metadata's transaction. http://blog.codecentric.de/en/2012/03/transactions-in-spring-batch-part-1-the-basics/
class LoanValidationServiceImpl implements LoanValidationService {
@Trasnactional(propagation=REQUIRES_NEW, rollbackFor=Exception.class)
validate(LoanApplication loanApplication) {
// business logic
}
}
Upvotes: 2
Reputation: 5609
For both of your questions, skipping the exception occured during the prosessor phase will solve your problems.
This may be configured by skippable-exception-classes
element if you know the root cause of the exception. For example, if you get a divide by zero exception during the processor phase and do want to neglect it, a sample configuration might be:
<chunk reader="reader" processor="processor" writer="writer"
commit-interval="1" >
<skippable-exception-classes>
<include class="java.lang.ArithmeticException" />
</skippable-exception-classes>
</chunk>
Since the given exception class and its subclasses will be skipped, you may even try java.lang.Exception
Upvotes: 2