users@glassfish.java.net

infinite message redelivery in the case of a DatabaseException at commit time

From: <forums_at_java.net>
Date: Wed, 13 Apr 2011 10:26:25 -0500 (CDT)

Hi,

I struggle with an infinte redelivery of some messages, when using CMT for my
MDB's in the case of a DatabaseException at commit time. I'm using Glassfish
3.1 in conjunction with a remote conventional OpenMQ cluster (Version 4.4
Update 2) and a PostgreSQL 9.0.3 - No XA Resources are configured. A little
bit more in detail, I have plain MDB as follow, which just receives a message
and stores some data in the database:

@MessageDriven(mappedName = "jms/myQueue", activationConfig = {
@ActivationConfigProperty(propertyName = "destinationType", propertyValue =
"javax.jms.Queue"),
@ActivationConfigProperty(propertyName = "messageSelector", propertyValue =
"someKey like '" + "foo%") })
public class MyMDB implements MessageListener {
@PersistenceContext(unitName = "my-pu")
private EntityManager entityManager;
@Override
public void onMessage(final Message _message) {
....
entityManager.persist(entity);
}
}
 

In some cases a database constraint is violated resulting in a
org.postgresql.util.PSQLException thrown at commit time:

 

Exception [EclipseLink-4002] (Eclipse Persistence Services -
2.2.0.v20110202-r8913): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: org.postgresql.util.PSQLException: ERROR: duplicate key
....
at
org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.issueSQLbeforeCompletion(RepeatableWriteUnitOfWork.java:331)
at
org.eclipse.persistence.transaction.AbstractSynchronizationListener.beforeCompletion(AbstractSynchronizationListener.java:157)
at
org.eclipse.persistence.transaction.JTASynchronizationListener.beforeCompletion(JTASynchronizationListener.java:68)
at
com.sun.jts.jta.SynchronizationImpl.before_completion(SynchronizationImpl.java:99)
at
com.sun.jts.CosTransactions.RegisteredSyncs.distributeBefore(RegisteredSyncs.java:158)
at
com.sun.jts.CosTransactions.TopCoordinator.beforeCompletion(TopCoordinator.java:2561)
at
com.sun.jts.CosTransactions.CoordinatorTerm.commit(CoordinatorTerm.java:279)
at com.sun.jts.CosTransactions.TerminatorImpl.commit(TerminatorImpl.java:250)
at com.sun.jts.CosTransactions.CurrentImpl.commit(CurrentImpl.java:623)
at
com.sun.jts.jta.TransactionManagerImpl.commit(TransactionManagerImpl.java:319)
at
com.sun.enterprise.transaction.jts.JavaEETransactionManagerJTSDelegate.commitDistributedTransaction(JavaEETransactionManagerJTSDelegate.java:173)
at
com.sun.enterprise.transaction.JavaEETransactionManagerSimplified.commit(JavaEETransactionManagerSimplified.java:873)
at
com.sun.ejb.containers.BaseContainer.completeNewTx(BaseContainer.java:5115)
at com.sun.ejb.containers.BaseContainer.postInvokeTx(BaseContainer.java:4880)
at
com.sun.ejb.containers.MessageBeanContainer.afterMessageDeliveryInternal(MessageBeanContainer.java:1207)
at
com.sun.ejb.containers.MessageBeanContainer.afterMessageDelivery(MessageBeanContainer.java:1180)
at
com.sun.ejb.containers.MessageBeanListenerImpl.afterMessageDelivery(MessageBeanListenerImpl.java:86)
at
com.sun.enterprise.connectors.inbound.MessageEndpointInvocationHandler.invoke(MessageEndpointInvocationHandler.java:143)
at $Proxy261.afterDelivery(Unknown Source)
at com.sun.messaging.jms.ra.OnMessageRunner.run(OnMessageRunner.java:328)
at com.sun.enterprise.connectors.work.OneWork.doWork(OneWork.java:114)
at
com.sun.corba.ee.impl.orbutil.threadpool.ThreadPoolImpl$WorkerThread.performWork(ThreadPoolImpl.java:497)
at
com.sun.corba.ee.impl.orbutil.threadpool.ThreadPoolImpl$WorkerThread.run(ThreadPoolImpl.jav 
 

Whenever this happens, the same message will be redelivered over and over
again and never send to the DMQ, even though property the useDMQ is to true
for the queue. I'm able to work around this issue in two ways: First,whenever
I flush the persistence context right after persisting the entity and a
PersistenceException is thrown in the onMessage(..) method, the message is
moved to the DMQ as expected. The same happens when the bean manage the
transaction by itself (BMT):

 

@Override
public void onMessage(final Message _message) {
try {
tx.begin();
...
entityManager.persist(entity);
tx.commit();
} catch (Exception e) {
try {
tx.rollback();
} catch (Exception e1) { throw new RuntimeException(e); }
throw new RuntimeException(e);
}
}
 

At present I have no clear idea why this happens, whether this is a bug or I
have an unclear understanding of what is happening behind the scenes.

Any help is appreciated.

 Thanks in advance, Carsten


--
[Message sent by forum member 'c_krebs']
View Post: http://forums.java.net/node/791533