Message dequeuing in case of Exceptions in MDB
Hi,
I am using SJSAS 8.1 . A MDB's (MDB with Container managed Required transaction attribute) onMessage catching a java.rmi.RemoteException (Please look at the code below) results in aborting the container started transaction and putting the message back on the queue .
public void onMessage() {
try {
//look up EJB
// invoke a business method
} catch(java.rmi.RemoteException re} {
}
}
But if I move the above try-catch block from onMessage() to a separate method say foo() and call foo() from onMessage() , message gets dequeued. Is this a expected behavior ?
public void onMessage () {
foo();
}
private void foo() {
try {
//look up EJB
// invoke a business method
} catch(java.rmi.RemoteException re} {
}
}
Thanks,
Manisha.
Hi Manisha
As long as you throw a runtimeexception or set rollback only, every time you want to rollback the tx, the container managed transaction would be rolledback and the message redelivered. It should not ideally matter that you do it in onMessage or foo(). Could you setRollBackOnly on the MessageContext? [17.6.3.3 of the EJB 2.1 spec]
Thanks
--Siva.
Hi Siva,
In my scneario, EJB invocation resulted in a RemoteException with cause as TransactionRolledBack. When this RemoteException is caught in foo() , message is taken off the transaction as nothing specidic is coded to handle the remote exception. If the RemoteException is caught in onMessage(), without setRollbackOnly() invocation on MessageContext, transaction gets aborted with message put back on the queue and without Message Redelivery Semantics applicable, resulting in a endless loop.Looks like a bug in application server .
Thanks,
Manisha.
> When this RemoteException is caught in foo() ,
> message is taken off the transaction as nothing
> specidic is coded to handle the remote exception.
In this case, are you indicating the transaction commits?
Are you throwing a RTE or RemoteException or setting setRollbackOnly when you catch the RemoteException in foo()? As indicated at https://glassfish.dev.java.net/javaee5/docs/DG/beahl.html#beaja
"If the bean method encounters a runtime exception or error, it should simply propagate the error from the bean method to the container.", foo should simply throw the error/exception,so that the container could abort the transaction.
> If the RemoteException is caught in onMessage(),
> without setRollbackOnly() invocation on
> MessageContext, transaction gets aborted with
> message put back on the queue and without Message
> Redelivery Semantics applicable, resulting in a
> endless loop.Looks like a bug in application
Are you setting the cmt-max-runtime-exceptions property
https://glassfish.dev.java.net/javaee5/docs/DG/beahl.html#beaja ?
Thanks
--Siva.
The foo() used to look like below :
private void foo() {
try {
//look up EJB
// invoke a business method
} catch(java.rmi.RemoteException re} {
System.out.println(" Exception occurred : " + re.getMessage());
}
}
when RemoteException with TransactionRolledbackException as cause, gets caught in foo(), message is getting removed from the queue ie transaction is getting commited, which is correct behavior as MDB is not explicitely rolling back the transaction by invoking setRollbackOnly() on the context in above catch block.
If I move the above try..catch block from foo() to onMessage(), without any change in the code, transaction gets aborted, with message put back on the queue and without Message Redelivery Semantics applicable, resulting in a endless loop.
I am trying to find out why there is difference in behavior when the same piece of code gets moved from foo() to onMessage().
I am not explicitely setting cmt-max-runtime-exceptions, hence using the default.
Regards,
Manisha.