hi david, please create a jira-ticket for such an improvement and i'll fix it soon.
regards, gerhard 2015-09-02 23:54 GMT+02:00 David Smalley <[email protected]>: > Hello, > > I am using the Deltaspike JPA module + WELD in a web app targeting Tomcat > (8). I have set up Atomikos Transaction Essentials to provide JTA > transactions, and all of that is working fine. I want to use Deltaspike for > the @Transactional and @TransactionScoped annotations. After enabling the > BeanManagedTransactionStrategy, I received NameNotFound exceptions for > TransactionSynchronizationRegistry. Some quick research showed that > Atomikos implements JTA 1.0 which doesn't include the registry, and > initially I thought this was the problem, but actually, it isn't. > > UserTransactionResolver declares a field @Resource UserTransaction > userTransaction. The code seems to assume the only thing which can go wrong > with this is that injection fails and it might be null, but actually, in > Tomcat, it throws a NameNotFound JNDI exception when it is dynamically > instantiated in resolveUserTransaction(), and so its alternative lookup > logic is never called. resolveUserTransaction() catches this exception and > always returns null, which is interpreted as there being an active CMT, > which causes the lookup for the none-existent registry, but that is already > wrong...there is no EJB and thus no CMT in a plain Tomcat environment. > > I have been able to make this work by changing the code in one of two ways: > either change the annotation to @Resource(mappedName = > "java:comp/UserTransaction") which causes the injection to succeed, or > remove it entirely, in which case the field is null, and the alternative > lookup logic is (successfully) invoked. > > After either of these changes, the BeanManagedUserTransactionStrategy works > correctly, and I have declarative JTA transactions with plain Tomcat + > Atomikos + Eclipselink. However, I don't want to build my own version of > Deltaspike for deployment. > > I have worked around this problem by providing my own transaction strategy > which extends BeanManagedUserTransactionStrategy and overrides > resolveUserTransaction() like this: > > public UserTransaction resolveUserTransaction() { > > UserTransaction userTransaction = super().resolveUserTransaction(); > > if (userTransaction == null) { > userTransaction = JNDIUtils.lookup("java:comp/UserTransaction", > UserTransaction.class); > } > > return userTransaction; > } > > It works, but it feels like a kludge. For what it is worth, the spec > recommends against assigning to injected fields, probably because you > usually get a proxy rather than a plain object. I think the use of > @Resource in UserTransactionResolver is dangerous, since it can throw an > exception during instantiation, which means handling the failure must > happen in the calling code. Because it is dynamically created in > resolveUserTransaction(), this is possible, but if you had injected it > directly into the strategy there would be no workaround other than copying, > modifying, and renaming the source. > > BTW, when I first found this, I tried to find a way to coerce the plain > @Resource annotation into working, either by mapping in web.xml, or trying > to provide my own implementation of WELD's ResourceInjectionServices spi, > but so far, I haven't been able to make it work. WELD's documentation on > replacing that spi seems to be incorrect, though that's not your problem. > > I suppose my question is: is there some way in Deltaspike to cause the > @Resource annotation to have the mappedName attribute dynamically added? I > have already determined that the ProcessInjectionPoint event is never fired > for @Resource fields (I tried to handle them in an extension); they are > deferred to the WELD service, which I have been unable to customize. > > Dave >
