Home > database >  Spring Transaction - Do not rollback for error under specific method
Spring Transaction - Do not rollback for error under specific method

Time:12-18

I have a Spring Boot application in which a service is responsible to create a Business Entity. For simplicity, let's consider:

create(Object toCreate) {
  validationService.validate(toCreate);
  Object created = repository.save(toCreate);
  notificationService.notify(created);
}

Business has changed and now I would like the creation to not fail if notification fails.

I therefore wrapped the notify() method in a try-catch block that only logs the error (which is a RuntimeException).

However when tested, a transaction rollback error was thrown, saying the connection was closed. I do not want any rollback, especially since the NotificationService does not modify the database.

How can I tell Spring that any exception happening in the NotificationService is fine and does not require a rollback? I tried annotating the class/method with @Transactional(propagation=NEVER) but got existing transaction found for transaction marked with propagation 'never'

CodePudding user response:

You can use the option norollbackfor of @Transactional so you have to specify an exception class not the service and when an error occurs in notifications try to throw a specifc error which would not cause a rollback.

CodePudding user response:

Perhaps refactoring your code would help better than the introduction of more complex transaction handling.

Assuming your @Transactional is on the create() method, we can see that you have:

  1. Pre-persistence business logic
  2. Persistence logic
  3. Post-persistence business logic

It depends on your use-case, but I would not expect pts. 1 & 3 to contain persistence logic. If that is the case, you could extract your persistence logic in its own service that would itself be a transaction, not the parent.

If you have the need for a transaction in those steps, you could also extract them in their own transaction.

Other leads might be:

  1. The default rollback behavior is for runtime unchecked exceptions. You could use checked exceptions to avoid the rollback.
  2. If your notification is separate from persistence and you do not care about the transaction, you could make it an asynchronous call (e.g. with @Async). It would be scheduled outside of the transaction in its own context.
  • Related