You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tomee.apache.org by exabrial12 <ex...@gmail.com> on 2019/03/27 15:37:17 UTC

Can't use UserTransaction from @Transaction call

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