TransactionSynchronizationManager
is kind of inconsistent in how it deals with "resources".
In the code I see:
private static final ThreadLocal<Map<Object, Object>> resources =
new NamedThreadLocal<>("Transactional resources");
suggesting that these resources are bound to a transaction. Further down in the Javadoc of the various methods that handle resource bind/unbind, there is no mention about transaction though, only thread local.
I was kind of caught by surprise that resources are not cleaned up after a transaction completes or stored away and restored on suspend/resume. As the implementation is right now, this resources
ThreadLocal
is not useful i.e. I could have just used my own ThreadLocal
myself.
IMO the transaction implementations should be changed to really bind these resources to a transaction. Otherwise, there is also a potential for a memory leak when somebody binds something to this resources
, but doesn't cleanup the value in a TransactionSynchronization
which really is transaction bound.
Comment From: jhoeller
That's intentional: The same resource binding is also used for reuse across demarcated scopes in general, even without an actual transaction, e.g. on @Transactional(propagation=SUPPORTS)
or for OpenEntityManagerInViewFilter
. The javadoc of those methods does not talk about automatic unbinding or even a transaction scope at all either. It's just meant to be a pair of bind/unbind method for a centralized ThreadLocal that all of Spring's transaction manager and data access implementations commonly use, and that integration code can use to interact with the managed resources of those common Spring transaction managers.
Now you could make an argument that there should be a convenient way to actually register a transaction-scoped resource with automatic unbinding, similar to how SimpleTransactionScope
is implemented: for example, a bindTransactionScopedResource
method that not only delegates to bindResource
but also implicitly registers a TransactionSynchronization
for unbinding.
Comment From: beikov
Thanks for confirming that the behavior is intended. I still think it is a bit confusing, though I also understand that "it is how it is" at this point.
for example, a
bindTransactionScopedResource
method that not only delegates tobindResource
but also implicitly registers aTransactionSynchronization
for unbinding.
IMO this would be a good addition and there should be a callout referring to this variant in the various bind
/unbind
methods that touch just the thread-local.
Comment From: jhoeller
I'm going with bindSynchronizedResource
since that most naturally matches the local terminology in TransactionSynchronizationManager
, without sounding BeanFactory Scope like (which would be confusing in its own right). I'm pointing to SimpleTransactionScope
in the javadoc there, logically connecting those two.