Hey guys, Here's something I should know about Java EE (Since I've put on training classes :D) but I don't.
So we have some batch processes that need to run, but only one instance of the app in the cluster needs to run them. We're trying to implement a cluster-wide lock via a database via a "database locks" table. So when a timer expires, first node to insert the row in the database wins the lock. We have the business logic in an ApplicationScoped CDI bean marked with @Transactional(Required). It starts doing some work, then at some point it's going to need to acquire the cluster-wide lock. I created a Singleton EJB with @TransactionMangement(Bean) where it does utx.begin, insert row, then utx.commit(). See code below. The problem is I'm getting a `Can't use UserTransaction from @Transaction call` message from TomEE. I tried wrapping my bean managed ejb [InternalLockBean in the stack trace below] in another EJB that has @TransactionAttribute(NOT_SUPPORTED) [DatabaseLockService in the stack trace below], but got the same result, which really surprised me. Mar 27, 2019 10:33:19 AM org.apache.openejb.core.transaction.EjbTransactionUtil handleSystemException SEVERE: EjbTransactionUtil.handleSystemException: The bean encountered a non-application exception; nested exception is: java.lang.RuntimeException: java.lang.IllegalStateException: Can't use UserTransaction from @Transaction call javax.ejb.EJBException: The bean encountered a non-application exception; nested exception is: java.lang.RuntimeException: java.lang.IllegalStateException: Can't use UserTransaction from @Transaction call at org.apache.openejb.core.ivm.BaseEjbProxyHandler.convertException(BaseEjbProxyHandler.java:447) at org.apache.openejb.core.ivm.BaseEjbProxyHandler.invoke(BaseEjbProxyHandler.java:351) at com.xxx.service.InternalLockBean$$LocalBeanProxy.acquireLock(com/xxx/service/InternalLockBean.java) at com.xxx.service.DatabaseLockService.acquireLock(DatabaseLockService.java:22) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) @Singleton @Lock(LockType.READ) @TransactionManagement(TransactionManagementType.BEAN) public class InternalLockBean { @Resource private UserTransaction utx; @Resource private UserTransaction utx; public boolean acquireLock(String lockName) { if (lockName == null) { throw new IllegalArgumentException("lockName cannot be null"); } else { lockName = StringUtils.truncate(lockName, MAX_LOCK_LENGTH); try { utx.begin(); DatabaseLock lock = new DatabaseLock(lockName, lockOwner); em.persist(lock); try { utx.commit(); } catch (Exception e) { log.trace("acquireLock() failure on commit, returning false", e); return false; } return true; } catch (Exception e) { throw new RuntimeException(e); } } } } @Singleton @Lock(LockType.WRITE) @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) public class DatabaseLockService { @EJB private InternalLockBean internalBean; public boolean acquireLock(String lockName) { return internalBean.acquireLock(lockName); } } -- Sent from: http://tomee-openejb.979440.n4.nabble.com/TomEE-Users-f979441.html