[
https://issues.jboss.org/browse/WFLY-4384?page=com.atlassian.jira.plugin....
]
Tobias Rötschke edited comment on WFLY-4384 at 3/3/15 3:33 AM:
---------------------------------------------------------------
Please let me eloborate on Maxim's question. What we are trying to do, is to execute
code in concurrent threads, but within the same transaction. Our guiding example is
Gupta's "Java EE 7 Essentials", chapter 10. I understand that invoking the
contextual object -- not creating it -- is influenced by the
USE_TRANSACTION_OF_EXECUTION_THREAD property value. That results from the
beforeProxyMethod() of the TransactionSetupProviderImpl class. However, the code seemingly
expects that the thread, where the proxy method is executed in, is already attached to the
transaction of the invoking thread.
This turns out not be the case in our setting. As you point out, ManagedExecutorService
runs in an internal thread outside a transaction. So we used
Executors.newFixedThreadPool() instead as in Gupta's example. We passed the default
ManagedThreadFactory to this method. We supplied the contextual object with the
TransactionManager injected to the class inside the invoking thread. We verified that the
contextual object is invoked directly from the invoking thread. However,
TransactionManager.getTransaction() yielded null inside the thread of the contextual
object.
Question is: What are we supposed to do in order to attach the thread of the contextual
object to the transaction of the invoking thread in the first place so that
TransactionSetupProviderImpl.beforeProxy does what it is meant to do? Unfortunately, the
javadoc example you cited did not help to explain that to us.
was (Author: tobias.roetschke):
Please let me eloborate on Maxim's question. What we are trying to do, is to execute
code in concurrent thread, but within the same transaction. Our guiding example is
Gupta's "Java EE 7 Essentials", chapter 10. I understand that invoking the
contextual object -- not creating it -- is influenced by the
USE_TRANSACTION_OF_EXECUTION_THREAD property value. That results from the
beforeProxyMethod() of the TransactionSetupProviderImpl class. However, the code seemingly
expects that the thread, where the proxy method is executed in, is already attached to the
transaction of the invoking thread.
This turns out not be the case in our setting. As you point out, ManagedExecutorService
runs in an internal thread outside a transaction. So we used
Executors.newFixedThreadPool() instead as in Gupta's example. We passed the default
ManagedThreadFactory to this method. We supplied the contextual object with the
TransactionManager injected to the class inside the invoking thread. We verified that the
contextual object is invoked directly from the invoking thread. However,
TransactionManager.getTransaction() yielded null inside the thread of the contextual
object.
Question is: What are we supposed to do in order to attach the thread of the contextual
object to the transaction of the invoking thread in the first place so that
TransactionSetupProviderImpl.beforeProxy does what it is meant to do? Unfortunately, the
javadoc example you cited did not help to explain that to us.
ContextService (JSR236): transactional context always suspended
---------------------------------------------------------------
Key: WFLY-4384
URL:
https://issues.jboss.org/browse/WFLY-4384
Project: WildFly
Issue Type: Bug
Components: EE
Affects Versions: 8.2.0.Final, 9.0.0.Alpha1
Reporter: Maxim Frolov
Assignee: Eduardo Martins
Priority: Critical
According to §3.3.5 of JSR-236 specification:
??By using an execution property when creating the contextual proxy object, application
components can choose to not suspend the transactional context on the thread ...??
Given the following EJB and Task:
{code:java}
@WebService(serviceName = "Jsr236WebService")
@Stateless
public class Jsr236WebService {
@Inject Jsr236ManagedTask jsr236ManagedTask;
@Resource ManagedExecutorService executor;
@Resource ContextService contextService;
@WebMethod(operationName = "hello")
public String hello(@WebParam(name = "name") String txt) {
Map<String, String> execProps = new HashMap<>();
execProps.put(ManagedTask.TRANSACTION,
ManagedTask.USE_TRANSACTION_OF_EXECUTION_THREAD);
Future<String> future = executor.submit(
contextService.createContextualProxy(jsr236ManagedTask, execProps,
Callable.class));
try {
return future.get();
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}
}
}
{code}
{code:java}
@Dependent
@Transactional(Transactional.TxType.MANDATORY)
public class Jsr236ManagedTask implements Callable<String>, ManagedTask {
@Override
public String call() {
return "called";
}
@Override
public Map<String, String> getExecutionProperties() {
Map<String, String> execProps = new HashMap<>();
execProps.put(ManagedTask.TRANSACTION,
ManagedTask.USE_TRANSACTION_OF_EXECUTION_THREAD);
return execProps;
}
}
{code}
When the {{call()}} Method of the task is called the following exception occurs:
{noformat}
javax.transaction.TransactionalException: ARJUNA016110: Transaction is required for
invocation
{noformat}
See maven test project [
https://github.com/wrungel/bugs/tree/master/jsr236-test] on
GitHub.
--
This message was sent by Atlassian JIRA
(v6.3.11#6341)