0

I work with Wildfly and OpenJPA. I have a situation of Optimistic Lock Exception.

The error message that I get is:

00:08:29,373 WARN [com.arjuna.ats.arjuna] (default task-39) ARJUNA012125: TwoPhaseCoordinator.beforeCompletion - failed for SynchronizationImple< 0:ffffc0a82f91:-3d767137:5a736fa1:d7c, org.jboss.as.txn.service.internal.tsr.JCAOrderedLastSynchronizationList@244256b9

: org.apache.openjpa.persistence.OptimisticLockException: Optimistic locking errors were detected when flushing to the data store. The following objects may have been concurrently modified in another transaction: [com.earnix.eo.entities.optimizer.PricingMixEntity-30400] ....

00:08:29,381 ERROR [org.jboss.as.ejb3.invocation] (default task-39) WFLYEJB0034: EJB Invocation failed on component PricingRuleAccessor for method public abstract java.util.List com.earnix.eo.sessions.navigator.PricingRuleAccessor.releasePricingMix(int,int) throws com.earnix.utils.EOException,com.earnix.eo.sessions.utils.EODeadlockException,java.rmi.RemoteException: javax.ejb.EJBTransactionRolledbackException: Transaction rolled back at org.jboss.as.ejb3.tx.CMTTxInterceptor.handleEndTransactionException(CMTTxInterceptor.java:137) at org.jboss.as.ejb3.tx.CMTTxInterceptor.endTransaction(CMTTxInterceptor.java:117) at org.jboss.as.ejb3.tx.CMTTxInterceptor.invokeInOurTx(CMTTxInterceptor.java:279) at org.jboss.as.ejb3.tx.CMTTxInterceptor.required(CMTTxInterceptor.java:327) at org.jboss.as.ejb3.tx.CMTTxInterceptor.processInvocation(CMTTxInterceptor.java:239) at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) at org.jboss.as.ejb3.remote.EJBRemoteTransactionPropagatingInterceptor.processInvocation(EJBRemoteTransactionPropagatingInterceptor.java:79) at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) at org.jboss.as.ejb3.component.interceptors.CurrentInvocationContextInterceptor.processInvocation(CurrentInvocationContextInterceptor.java:41) at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) at org.jboss.as.ejb3.component.invocationmetrics.WaitTimeInterceptor.processInvocation(WaitTimeInterceptor.java:47) at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) at org.jboss.as.ejb3.security.SecurityContextInterceptor.processInvocation(SecurityContextInterceptor.java:100) at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) at org.jboss.as.ejb3.deployment.processors.StartupAwaitInterceptor.processInvocation(StartupAwaitInterceptor.java:22) at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) at org.jboss.as.ejb3.component.interceptors.ShutDownInterceptorFactory$1.processInvocation(ShutDownInterceptorFactory.java:64) at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) at org.jboss.as.ejb3.deployment.processors.EjbSuspendInterceptor.processInvocation(EjbSuspendInterceptor.java:53) at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) at org.jboss.as.ejb3.component.interceptors.LoggingInterceptor.processInvocation(LoggingInterceptor.java:67) at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) at org.jboss.as.ejb3.component.interceptors.EjbExceptionTransformingInterceptorFactories$1.processInvocation(EjbExceptionTransformingInterceptorFactories.java:75) at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) at org.jboss.as.ee.component.NamespaceContextInterceptor.processInvocation(NamespaceContextInterceptor.java:50) at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) at org.jboss.invocation.ContextClassLoaderInterceptor.processInvocation(ContextClassLoaderInterceptor.java:64) at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) at org.jboss.invocation.InterceptorContext.run(InterceptorContext.java:356) at org.wildfly.security.manager.WildFlySecurityManager.doChecked(WildFlySecurityManager.java:636) at org.jboss.invocation.AccessCheckingInterceptor.processInvocation(AccessCheckingInterceptor.java:61) at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) at org.jboss.invocation.InterceptorContext.run(InterceptorContext.java:356) at org.jboss.invocation.PrivilegedWithCombinerInterceptor.processInvocation(PrivilegedWithCombinerInterceptor.java:80) at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) at org.jboss.invocation.ChainedInterceptor.processInvocation(ChainedInterceptor.java:61) at org.jboss.as.ee.component.ViewService$View.invoke(ViewService.java:198) at org.jboss.as.ejb3.remote.protocol.versionone.MethodInvocationMessageHandler.invokeMethod(MethodInvocationMessageHandler.java:328) at org.jboss.as.ejb3.remote.protocol.versionone.MethodInvocationMessageHandler.access$100(MethodInvocationMessageHandler.java:67) at org.jboss.as.ejb3.remote.protocol.versionone.MethodInvocationMessageHandler$1.run(MethodInvocationMessageHandler.java:201) at org.jboss.as.ejb3.remote.protocol.versionone.MethodInvocationMessageHandler.processMessage(MethodInvocationMessageHandler.java:263) at org.jboss.as.ejb3.remote.protocol.versionone.VersionOneProtocolChannelReceiver.processMessage(VersionOneProtocolChannelReceiver.java:213) at org.jboss.as.ejb3.remote.protocol.versiontwo.VersionTwoProtocolChannelReceiver.processMessage(VersionTwoProtocolChannelReceiver.java:76) at org.jboss.as.ejb3.remote.protocol.versionone.VersionOneProtocolChannelReceiver.handleMessage(VersionOneProtocolChannelReceiver.java:159) at org.jboss.remoting3.remote.RemoteConnectionChannel$5.run(RemoteConnectionChannel.java:456) at org.jboss.remoting3.EndpointImpl$TrackingExecutor$1.run(EndpointImpl.java:731) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748) Caused by: javax.transaction.RollbackException: ARJUNA016053: Could not commit transaction. at com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionImple.commitAndDisassociate(TransactionImple.java:1212) at com.arjuna.ats.internal.jta.transaction.arjunacore.BaseTransaction.commit(BaseTransaction.java:126) at com.arjuna.ats.jbossatx.BaseTransactionManagerDelegate.commit(BaseTransactionManagerDelegate.java:89) at org.jboss.as.ejb3.tx.CMTTxInterceptor.endTransaction(CMTTxInterceptor.java:91) ... 47 more Caused by: org.apache.openjpa.persistence.OptimisticLockException: Optimistic locking errors were detected when flushing to the data store. The following objects may have been concurrently modified in another transaction: [com.earnix.eo.entities.optimizer.PricingMixEntity-30400] at org.apache.openjpa.kernel.BrokerImpl.newFlushException(BrokerImpl.java:2357) at org.apache.openjpa.kernel.BrokerImpl.flush(BrokerImpl.java:2205) at org.apache.openjpa.kernel.BrokerImpl.flushSafe(BrokerImpl.java:2103) at org.apache.openjpa.kernel.BrokerImpl.beforeCompletion(BrokerImpl.java:2021) at org.jboss.as.txn.service.internal.tsr.JCAOrderedLastSynchronizationList.beforeCompletion(JCAOrderedLastSynchronizationList.java:116) at com.arjuna.ats.internal.jta.resources.arjunacore.SynchronizationImple.beforeCompletion(SynchronizationImple.java:76) at com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator.beforeCompletion(TwoPhaseCoordinator.java:368) at com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator.end(TwoPhaseCoordinator.java:91) at com.arjuna.ats.arjuna.AtomicAction.commit(AtomicAction.java:162) at com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionImple.commitAndDisassociate(TransactionImple.java:1200) ... 50 more Caused by: org.apache.openjpa.persistence.OptimisticLockException: An optimistic lock violation was detected when flushing object instance "com.earnix.eo.entities.optimizer.PricingMixEntity-30400" to the data store. This indicates that the object was concurrently modified in another transaction. FailedObject: com.earnix.eo.entities.optimizer.PricingMixEntity-30400 at org.apache.openjpa.jdbc.kernel.PreparedStatementManagerImpl.flushAndUpdate(PreparedStatementManagerImpl.java:124) at org.apache.openjpa.jdbc.kernel.BatchingPreparedStatementManagerImpl.batchOrExecuteRow(BatchingPreparedStatementManagerImpl.java:100) at org.apache.openjpa.jdbc.kernel.BatchingPreparedStatementManagerImpl.flushAndUpdate(BatchingPreparedStatementManagerImpl.java:83) at org.apache.openjpa.jdbc.kernel.PreparedStatementManagerImpl.flushInternal(PreparedStatementManagerImpl.java:100) at org.apache.openjpa.jdbc.kernel.PreparedStatementManagerImpl.flush(PreparedStatementManagerImpl.java:88) at org.apache.openjpa.jdbc.kernel.ConstraintUpdateManager.flush(ConstraintUpdateManager.java:550) at org.apache.openjpa.jdbc.kernel.ConstraintUpdateManager.flush(ConstraintUpdateManager.java:107) at org.apache.openjpa.jdbc.kernel.BatchingConstraintUpdateManager.flush(BatchingConstraintUpdateManager.java:59) at org.apache.openjpa.jdbc.kernel.AbstractUpdateManager.flush(AbstractUpdateManager.java:104) at org.apache.openjpa.jdbc.kernel.AbstractUpdateManager.flush(AbstractUpdateManager.java:77) at org.apache.openjpa.jdbc.kernel.JDBCStoreManager.flush(JDBCStoreManager.java:731) at org.apache.openjpa.kernel.DelegatingStoreManager.flush(DelegatingStoreManager.java:131)

My problem is that EJBTransactionRolledbackException is thrown and not OptimisticLockException. Therefore, my code doesn't consider the exception as OptimisticLockException. Do you know how I can make Wildfly/JPA throw an EJBTransactionRolledbackException ?

I also looked at the 'cause' field of TransactionRolledbackException and I see there null. enter image description here

Some code:

@Override
    public List<PricingMixHeader> releasePricingRule(PricingMixHeader header) throws EOException {
        for (int i = 0; ; i++) {
            try {
                return pricingRuleAccessor.releasePricingMix(header.getPk(), getSessionPk());
            } catch (RemoteException e) {
                DeadlockUtils.handleRemoteException(e, i);
            } catch (EODeadlockException e) {
                // recover from the deadlock
                DeadlockUtils.recover(i, e.getOriginalExceptionStack());
            }
        }
    }

This is the code in the client side. pricingRuleAccessor.releasePricingMix(...) is a remote-mothod invocation call to a method in server side. In the server side Optimistic Lock Exception occured and then RemoteException was caught (TransactionRolledbackException inherits from RemoteException).

CrazySynthax
  • 13,662
  • 34
  • 99
  • 183

2 Answers2

2

I would suggest 2 things:

1) You could call a em.flush() before the point that the 'OptimisticLockException' exception occurs, to get this exception and then throw it as you want.

2) Other possibility is to ignore the details that are ocurring an OptimisticLockException, and create a new 'MyRemoteException' ( an ApplicationException that extends EJBException). It'd be like that:

@ApplicationException(rollback = true)
public class MyRemoteException extends EJBException {
  ...
}

Throw this exception to be caught by your 'view layer' and then it will decide what information to show.

Dherik
  • 17,757
  • 11
  • 115
  • 164
0

JBoss always wraps the thrown exception, in your case OptimisticLockException, in a EJBTransactionRollbackException when the thrown exception is a RuntimeException that causes a rollback.

In your client code you must check for EJBTransactionRollbackException and then check if the cause is a OptimisticLockException:

try {
...
} catch (EJBTransactionRollbackException e) {
    if (e.getCause() instanceof OptimisticLockException) {
       ...
    }
}
Simon Martinelli
  • 34,053
  • 5
  • 48
  • 82