Use Case #02 — Spring transactional REQUIRES_NEW propagation mode

  • can inner transaction be committed, when outer transaction will rollback?
  • can outer transaction be committed, when inner transaction will rollback?
  • when both transactions be rolled back, and should they?

Code setup

Notification entity
Service with outer transaction
Service with inner transaction

Initial state

Test 1 — no exception thrown, everything committed

notificationsService.sendNotification(1);

Test 2 — exception thrown in an inner transaction, no handling in outer transaction

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void updateNotificationStatus(Long id) {
Notification notification = notificationsRepository.findById(id).get();
notification.setStatus(Notification.NotificationStatus.SENT);
throw new NotificationStatusFailureException("Will it rollback?");
}
notificationsService.sendNotification(1);

Test 3— exception thrown in an inner transaction, noRollbackFor=NotificationStatusFailureException in outer transaction

@Transactional(noRollbackFor = NotificationStatusFailureException.class)
public void sendNotification(Long id) {
notificationStatusUpdateService.updateNotificationStatus(id);

Notification notification = notificationsRepository.findById(id).get();
notification.setMessage("UPDATED MESSAGE");
}
notificationsService.sendNotification(1);

Test 4— exception thrown in an inner transaction, try/catch block in outer transaction

@Transactional
public void sendNotification(Long id) {
try {
notificationStatusUpdateService.updateNotificationStatus(id);
} catch (NotificationStatusFailureException e) {
log.error("Inner transaction has thrown an exception", e);
}


Notification notification = notificationsRepository.findById(id).get();
notification.setMessage("UPDATED MESSAGE");
}
notificationsService.sendNotification(1);

Test 5— exception thrown in outer transaction

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void updateNotificationStatus(Long id) {
Notification notification = notificationsRepository.findById(id).get();
notification.setStatus(Notification.NotificationStatus.SENT);
}
@Transactional
public void sendNotification(Long id) {
notificationStatusUpdateService.updateNotificationStatus(id);

Notification notification = notificationsRepository.findById(id).get();
notification.setMessage("UPDATED MESSAGE");
throw new NotificationStatusFailureException("Outer rollback?");
}

Bonus 1 — monitor where Your transaction is being initialised and committed/rollbacked

logging:
level:
org:
springframework:
orm:
jpa: trace
transaction:
interceptor: trace
Suspending current transaction, creating new transaction with name [pl.akolata.exercises.transactions.nested.NotificationStatusUpdateService.updateNotificationStatus]Opened new EntityManager [SessionImpl(809522138<open>)] for JPA transaction
...
Completing transaction for [pl.akolata.exercises.transactions.nested.NotificationStatusUpdateService.updateNotificationStatus]
...
Initiating transaction commit
Committing JPA transaction on EntityManager [SessionImpl(809522138<open>)]
Closing JPA EntityManager [SessionImpl(809522138<open>)] after transaction
...
Resuming suspended transaction after completion of inner transaction

Summary

--

--

--

Senior Full Stack Developer — Java (Spring) and TypeScript (Angular). DDD and software architecture enthusiast.

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Learn Git in just 10 easy steps

Collection framework in java

The Black Magic of Oauth in Golang

A little journey toward Image Processing — part 1

LeetCode — Two Sum

How to Integrate Plaid SDK to React Native Using Expo Config Plugins

[Delio LABS] DeFi Research 04 STABLECOIN

5 Python Algorithms On Sets To Solve Before Your Next Interview

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Aleksander Kołata

Aleksander Kołata

Senior Full Stack Developer — Java (Spring) and TypeScript (Angular). DDD and software architecture enthusiast.

More from Medium

AspectJ + Gradle — Retry Java Method on exception

Authorisation with Spring Security — Part 2

Spring Cloud Config| Configuring Random Values in properties.

How to connect to multiple RabbitMQ instances using Spring Cloud Stream