[JBoss JIRA] (JBTM-2350) CDI Transactional interceptors are not thread safe. (previousUserTransactionAvailability)
by Tomasz Krakowiak (JIRA)
[ https://issues.jboss.org/browse/JBTM-2350?page=com.atlassian.jira.plugin.... ]
Tomasz Krakowiak updated JBTM-2350:
-----------------------------------
Description:
The problem is with availability of `UserTransaction`.
Availability of UserTransaction is stored in `ServerVMClientUserTransaction.isAvailables` which is `ThreadLocal<Boolean>`.
`TransactionalInterceptorRequired` when intercepting call, stores thread local value of `isAvailables` in `TransactionalInterceptorBase.previousUserTransactionAvailability` field of interceptor - which is of type boolean(not thread local).
Here's a story:
We have a bean - `beanA` - with single method annotated transactional - `beanA.transactional()`.
This method is being called from two threads, where:
- Thread 1 is participating in BMT, therefore it's `ServerVMClientUserTransaction.isAvailables` value is true.
- Thread 2 is participating in CMT, therefore it's `ServerVMClientUserTransaction.isAvailables` value is false.
Both threads call `beanA.transactional()` at the same time.
What may happen:
1. Thread 1 - enters method `beanA.transactional()`.
Interceptor sets previousUserTransactionAvailability to true.
2. Thread 2 - enters method `beanA.transactional()`.
Interceptor sets previousUserTransactionAvailability to false.
3. Thread 1 - exits method `beanA.transactional()`
Interceptor restores thread local value of `isAvailables` to false (leaked value from thread 2!)
was:
The problem is with availability of `UserTransaction`.
Availability of UserTransaction is stored in `ServerVMClientUserTransaction.isAvailables` which is `ThreadLocal<Boolean>`.
`TransactionalInterceptorRequired` when intercepting call, stores thread local value of `isAvailables` in `TransactionalInterceptorBase.previousUserTransactionAvailability` field of interceptor - which is of type boolean(not thread local).
Here's a story:
We have a bean (beanA) with single method annotated transactional (beanA.transactional()).
This method is being called from two threads, where:
- Thread 1 is participating in BMT, therefore it's ServerVMClientUserTransaction.isAvailables value is true.
- Thread 2 is participating in CMT, therefore it's ServerVMClientUserTransaction.isAvailables value is false.
Both threads call beanA.transactional() at the same time.
What may happen:
1. Thread 1 - enters method beanA.transactional.
Interceptor sets previousUserTransactionAvailability to true.
2. Thread 2 - enters method beanB.transactional.
Interceptor sets previousUserTransactionAvailability to false.
3. Thread 1 - exits method beanA.transactional
Interceptor restores thread local value of `isAvailables` to false (leaked value from thread 2!)
> CDI Transactional interceptors are not thread safe. (previousUserTransactionAvailability)
> -----------------------------------------------------------------------------------------
>
> Key: JBTM-2350
> URL: https://issues.jboss.org/browse/JBTM-2350
> Project: JBoss Transaction Manager
> Issue Type: Bug
> Components: JTA
> Affects Versions: 5.0.0, 5.0.1, 5.0.2, 5.0.3, 5.0.4
> Environment: Wildfly 8.1.0, Wildfly 8.2.0, linux, OS X
> Reporter: Tomasz Krakowiak
> Assignee: Tom Jenkinson
>
> The problem is with availability of `UserTransaction`.
> Availability of UserTransaction is stored in `ServerVMClientUserTransaction.isAvailables` which is `ThreadLocal<Boolean>`.
> `TransactionalInterceptorRequired` when intercepting call, stores thread local value of `isAvailables` in `TransactionalInterceptorBase.previousUserTransactionAvailability` field of interceptor - which is of type boolean(not thread local).
> Here's a story:
> We have a bean - `beanA` - with single method annotated transactional - `beanA.transactional()`.
> This method is being called from two threads, where:
> - Thread 1 is participating in BMT, therefore it's `ServerVMClientUserTransaction.isAvailables` value is true.
> - Thread 2 is participating in CMT, therefore it's `ServerVMClientUserTransaction.isAvailables` value is false.
> Both threads call `beanA.transactional()` at the same time.
> What may happen:
> 1. Thread 1 - enters method `beanA.transactional()`.
> Interceptor sets previousUserTransactionAvailability to true.
> 2. Thread 2 - enters method `beanA.transactional()`.
> Interceptor sets previousUserTransactionAvailability to false.
> 3. Thread 1 - exits method `beanA.transactional()`
> Interceptor restores thread local value of `isAvailables` to false (leaked value from thread 2!)
--
This message was sent by Atlassian JIRA
(v6.3.11#6341)