1
votes

I am fairly new to Spring and transactions. I am sure this question has been asked before, but I still cannot figure the correct way to go about it.

I am using Spring and hibernate. I have a service method that goes like this:

@Transactional
public void processPendingReport(Report report) {
  try {
    // Do processing stuff, update report object state
    reportDAO.save(report);
  } catch (Exception e) {
    reportDAO.markReportAsFailed(report);
  }
}

If a RuntimeException occurs during processing, a "Transaction marked as rollbackOnly" RollbackException will be thrown, having as a result that the report will not be marked as failed (although I would like it to be).

I have tried using @Transactional(noRollbackFor=Exception.class), but still get the same issue.. Any suggestions? Could it be a configuration issue?

1
Is the reportDAO class also marked @Transactional? - Luciano
what is transaction propagation used for reportDAO.save and reportDAO.markReportAsFailed? - Jigar Parekh
The reportDAO is marked as @Transactional at the class level. There is no explixit tx:advice declaration in the applicationContext.xml, so it should be the default, REQUIRED propagation level - spyk
This rollbackException you mention, is it ajavax.persistence.RollbackException ? If so, it should only appear at the end of the transaction, when it is committing. Can you check the transaction status before the save method to check if it is not already marked for rollback? Or is it that the method "markReportAsFailed" is the one throwing rollbackException? - Luciano
i think you should try with reportDAO.markReportAsFailed transaction with REQUIRES_NEW as you would like parent transaction as rollback butmarkReportAsFailed to be commited - Jigar Parekh

1 Answers

-1
votes

If a database exception (e.g. constraint violation) occurs in reportDAO.save() or reportDAO.markReportAsFailed() the transaction will be rolled back on the database level no matter what you are doing on the application level.

You can still mark the report as failed if reportDao.save() fails when you create a new transaction for reportDAO.markReportAsFailed(). Since ReportDAO is annotated @Transactional just remove the @Transactional annotation from the service method. You could also change the reportDAO.save() implementation to use a database function or stored procedure that wraps the insert statement and catches any exceptions on the database level.

HTH.