I've been using the AbstractRoutingDataSource with great success, but have hit upon an issue I can't resolve: when I kick off an asynchronous method using @Async
, it loses the local thread's context, and I can't figure out the place to set the database context switch. Usually I do it an aspect or in a HandlerInterceptor
, but @Async
doesn't go through any of those usual routes. Is there an interceptor or something similar I can configure to fire at the beginning and end of the asynch call so that I can set the database context?
Found a similar question on the Spring message boards. No answer, though: http://forum.springsource.org/showthread.php?83792-Async-annotated-method-hanging-on-session-scoped-bean
EDIT: I've debugged the execution flow, and the AbstractRoutingData source is in fact getting called in the async thread, but its getting called before the aspect is getting called, so the DataSource
is already set in the Hibernate session before the ThreadLocal
value is getting set. Looking at the source code for AsyncExecutionInterceptor
, which backs @Async
, its because the interceptor returns its Order
value as HIGHEST_PRECEDENCE
, so its getting fired before anything else.
Think I've found the answer: method execution interception will fail to set the variable on the ThreadLocal
, as the AsyncExecutionInterceptor
will always have higher precedence and start the Hibernate transaction. Instead, what I've done is externalized the logic from the async method to its own class, and marked that method as requiring its own transaction, via @Transactional(propagation=Propagation.REQUIRES_NEW)
. Since the sub-method now runs in its own transaction, the variable on the ThreadLocal
is correctly picked up by the AbstractRoutingDataSource
at the onset of the new Hibernate transaction.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With