Do Not Expect Catch Exception Across JPA Transactions

Let’s first take a look at some code here and see if you can find some issue inside.

@Transactional
 @Service
 public class StudentService {
 public List<String> getAllStudentNames() throw StudentNotFoundException {
 ... ...
 }
 }

@Transactional
 @Service
 public class SchoolService {
 @Autowired
 private StudentService studentService;

public String getBestStudent() {
 String bestStudentName = null;
 try {
 List<String> allStudentNames = studentService.getAllStudentNames();
 ... ...
 bestStudentName = ...;
 } catch (StudentNotFoundException e) {
 ...
 bestStudentName = "No Found";
 }
 return bestStudentName;
 }
 }

It is very strait forward,  the SchoolService calls StudentService to get the list of names then figures out the best student name, since StudentService might throw StudentNotFoundException then it is very natural to catch the exception from SchoolService and then convert the exception to some logic condition without further rethrow the exception.  Also, both StudentService and SchoolService are declared as @Transsactional , that is fine, Spring will take care of any transaction for you, no worry needed.

Seems everything is gonna be fine. However, when you run the application,  you will find that RollbackException is thrown from SchoolService method and crashes down the whole code logic.  The root cause is a little complicated, especially when Spring’s transaction framework is involved and you might need take a look at the Spring’s transaction propagation model from Spring’s documentation, we are not going check the details of Spring JPA transaction extension framework here.

What we want to highlight today is the way of using exception inside a transaction context, a lot programming practices might be related into the blogger here, but one fundamental programming practice is,  do not use Exception to manage your expected business logic inside one JPA transaction environment or do not let your expected transaction to be used across JPA transactions.

Each transaction is intercepted by Spring’s transaction interceptor to enforce its own JPA transaction extension including Spring’s @Transsactional, it detects any uncaught exception and rollback will be marked into the current transaction, how the rollback of the current transaction impacts other transaction really depends on the current transaction propagation configurations, but one thing is for sure that is, the exception will not be ignored by current transaction.

Pasted_Image_2_25_18__1_50_PM.png

 

 

 

 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s