• Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Distributed transactions on MDB

 
Ramy Nady
Ranch Hand
Posts: 114
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello ,

I have a scenario which I need your input.

A ) If there is a message driven bean with CMT and transaction attribute required

-begin MDB
-Write to DB
-Send message to queue
-Null pointer exception.

I know this is a system exception , the transaction will be rolled back , which mean all my changes to DB will be rolled back.

But what will happen to the message sent to JMS queue ?
It will be removed also ?

I understand from Specs that in CMT with transaction attribute required , sending the message is part of a transaction
That means my message will never sent to the queue ?

B) what will happen if the same above sequence appear with BMT

-Start transaction
-Write to DB
-Send message to queue
-Null pointer exception.

What about my changes at DB and my message at queue ?

Appreciate your response.

 
Frits Walraven
Creator of Enthuware JWS+ V6
Saloon Keeper
Pie
Posts: 2531
112
Android Chrome Eclipse IDE
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
But what will happen to the message sent to JMS queue ?
It will be removed also ?

Yes, well actually it won't be delivered to the JMS queue until the transaction commits. In case of a System Exception it won't make it to the JMS queue.

I understand from Specs that in CMT with transaction attribute required , sending the message is part of a transaction
That means my message will never sent to the queue ?

What is different between a CMT and a BMT is the delivery of a message to the onMessage() method of the MessageDriven bean. The container delivers the message to a CMT in the same transaction in which the onMessage() method runs. This means that if a System Exception is thrown, the message is put back on the incoming queue and the container will try once more to deliver it to the MDB (every messaging provider will have configured some sort of maximum).

In case of a BMT the delivery of a message to the onMessage() method of the MessageDriven bean is outside the transaction. This means that if a System Exception is thrown from the onMessage method, the transaction that you started by UserTransaction.begin() is rolled back, but the message is not put back on the incoming queue for redelivery. You will have to deal with the message that caused the exception.
 
Ramy Nady
Ranch Hand
Posts: 114
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks Frits for your usual help.
 
Himai Minh
Ranch Hand
Posts: 1359
7
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi again,
Quote A from the previous post:
The container delivers the message to a CMT in the same transaction in which the onMessage() method runs. This means that if a System Exception is thrown, the message is put back on the incoming queue and the container will try once more to deliver it to the MDB .

In case of a BMT the delivery of a message to the onMessage() method of the MessageDriven bean is outside the transaction. This means that if a System Exception is thrown from the onMessage method, the transaction that you started by UserTransaction.begin() is rolled back, but the message is not put back on the incoming queue for redelivery.


Frits's notes p.37, it says this:
Quote B from the notes

BMT: a message is redelivered if the onMessage method throws a RuntimeException
CMT: a message is redelivered if the onMessage method throws a RuntimeException.

I am sure the RuntimeException on in this case refers to System Exception.

My questions are:
Q1: Quote A says in BMT the message won't be redelivered when the onMessage throws a system exception or runtime exception which is not application exception. Quote B says in BMT the message will be redelivered when the onMessage throws a system exception.
Which quote is the right one?

Q2: In JSR-318, when a system exception is thrown from the onMessage method, the MDB will be destroyed and the @PreDestroy interceptor is called. So, if MDB does not exist after the system exception is thrown, how can the EJB container put the message to the queue/topic and redeliver to the MDB? The only possibility is the EJB container put the same message to the queue/topic and redeliver the message to a new instance of MDB.



 
Frits Walraven
Creator of Enthuware JWS+ V6
Saloon Keeper
Pie
Posts: 2531
112
Android Chrome Eclipse IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I am sure the RuntimeException on in this case refers to System Exception.

You are right I should change that, thanks.

Q1: Quote A says in BMT the message won't be redelivered when the onMessage throws a system exception or runtime exception which is not application exception. Quote B says in BMT the message will be redelivered when the onMessage throws a system exception. Which quote is the right one?

Good point! I have checked it again and this is what the specs say about it:

For a BM MessageDrivenBean, the message acknowledgement is outside the UserTransaction. The container will acknowlegde the receipt of the message, however
5.4.18 Dealing with Exceptions
If a message-driven bean uses bean-managed transaction demarcation and throws a RuntimeException, the container should not acknowledge the message.

In other words: when the message is not acknowledged (within a certain period) of time, the underlying messaging resource provider will attempt to redeliver the message (note that this redelivery is not specified in the EJB specs, but this is how most messaging providers have implemented it)

However, if you rollback the transaction of a BM MessageDrivenBean by calling UserTransaction.rollback(), there won't be any redelivery as the message receipt will be acknowledged by the container (remember the acknowledgement is outside the transaction)

For a CM MessageDrivenBean everything is simpler: message acknowledgement is inside the container started transaction. The message is acknowledged if the transaction commits and not acknowledged and when the transaction is rolled back (either by calling setRollbackOnly() or by throwing a System Exception). When the transaction is rolled back, the message is put back on the incoming queue, and redelivered to a new instance of the MBD.

Q2: In JSR-318, when a system exception is thrown from the onMessage method, the MDB will be destroyed and the @PreDestroy interceptor is called. So, if MDB does not exist after the system exception is thrown, how can the EJB container put the message to the queue/topic and redeliver to the MDB? The only possibility is the EJB container put the same message to the queue/topic and redeliver the message to a new instance of MDB.

Yes, exactly, it will be redeliverd to a new instance of the MDB.

I will update my notes to make this part clearer, thanks for pointing this out, have a Cow!
 
Himai Minh
Ranch Hand
Posts: 1359
7
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Frits. Thanks so much for your explanation.
Which one actually do the message redelivery when a system exception or rollback happens? The EJB container or the messaging provider or both?
Quote A:

the message is put back on the incoming queue and the container will try once more to deliver it to the MDB.

It seems to me that the container redelivers the message.

Quote B:

when the message is not acknowledged (within a certain period) of time, the underlying messaging resource provider will attempt to redeliver the message (note that this redelivery is not specified in the EJB specs, but this is how most messaging providers have implemented it)



Or, the underlying messaging resource provider redelivers the message to the EJB container and then the container redelivers
the same message to a new instance of MDB?
 
Frits Walraven
Creator of Enthuware JWS+ V6
Saloon Keeper
Pie
Posts: 2531
112
Android Chrome Eclipse IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
the underlying messaging resource provider redelivers the message to the EJB container and then the container redelivers the same message to a new instance of MDB?

Yes, that one is correct in all details
 
Himai Minh
Ranch Hand
Posts: 1359
7
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
For the information, I used Ivan's MDB example to demonstration a system exception thrown by onMessage() :

I have four beans, QueueListener0, QueueListener1, QueueListener2, QueueListener3


Info: *** MessageProducerServlet created.
Info: *** QueueListenerEJB created. 1

Info: *** Bean 1 received message: com.sun.messaging.jms.ra.DirectObjectPacket@442cde28
Info: Received message with number: 1
Info: Message string: Hello Message Driven Beans
Info: Message time: Wed Mar 18 18:35:51 EDT 2015
Warning: MQJMSRA_MR2001: run:Caught Exception from onMessage():Redelivering:
javax.ejb.EJBException: message-driven bean method public abstract void javax.jms.MessageListener.onMessage(javax.jms.Message) system exception
..
at com.ivan.scbcd6.ejbs.QueueListenerEJB.onMessage(QueueListenerEJB.java:39)
....


Warning: MDB00037: [QueueMessageDrivenExample:QueueListener2]: Message-driven bean invocation exception: [javax.ejb.EJBException]
Warning: javax.ejb.EJBException
javax.ejb.EJBException
at com.sun.ejb.containers.BaseContainer.processSystemException(BaseContainer.java:5194)
at com.sun.ejb.containers.BaseContainer.completeNewTx(BaseContainer.java:5092)
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 com.sun.proxy.$Proxy190.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.java:540)
Caused by: java.lang.RuntimeException
at com.ivan.scbcd6.ejbs.QueueListenerEJB.onMessage(QueueListenerEJB.java:39)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.glassfish.ejb.security.application.EJBSecurityManager.runMethod(EJBSecurityManager.java:1052)
at org.glassfish.ejb.security.application.EJBSecurityManager.invoke(EJBSecurityManager.java:1124)
at com.sun.ejb.containers.BaseContainer.invokeTargetBeanMethod(BaseContainer.java:4155)
at com.sun.ejb.containers.BaseContainer.__intercept(BaseContainer.java:5347)
at com.sun.ejb.containers.BaseContainer.intercept(BaseContainer.java:5327)
at com.sun.ejb.containers.MessageBeanContainer.deliverMessage(MessageBeanContainer.java:1093)
at com.sun.ejb.containers.MessageBeanListenerImpl.deliverMessage(MessageBeanListenerImpl.java:81)
at com.sun.enterprise.connectors.inbound.MessageEndpointInvocationHandler.invoke(MessageEndpointInvocationHandler.java:171)
at com.sun.proxy.$Proxy190.onMessage(Unknown Source)
at com.sun.messaging.jms.ra.OnMessageRunner.run(OnMessageRunner.java:260)
... 3 more

Info: *** QueueListenerEJB created. 2
Info: *** Bean 2 received message: com.sun.messaging.jms.ra.DirectObjectPacket@442cde28
Info: Received message with number: 1
Info: Message string: Hello Message Driven Beans
Info: Message time: Wed Mar 18 18:35:51 EDT 2015
Warning: MQJMSRA_MR2001: run:Caught Exception from onMessage():Redelivering:
javax.ejb.EJBException: message-driven bean method public abstract void javax.jms.MessageListener.onMessage(javax.jms.Message) system exception
....
Caused by: java.lang.RuntimeException
.....
Info: MQJMSRA_MR1101: run:Message returned & marked for routing to the DMQ
Warning: MDB00037: [QueueMessageDrivenExample:QueueListener2]: Message-driven bean invocation exception: [javax.ejb.EJBException]
Warning: javax.ejb.EJBException
javax.ejb.EJBException
...
Caused by: java.lang.RuntimeException
....
Info: Server shutdown initiated
Warning: [MDBContainer] Current thread done cleanup()...
Warning: [MDBContainer] Current thread done cleanup()...
Warning: [MDBContainer] Current thread done cleanup()...
Warning: [MDBContainer] Current thread done cleanup()...
Info: MQJMSRA_RA1101: GlassFish MQ JMS Resource Adapter stopping...

Info: MQJMSRA_RA1101: GlassFish MQ JMS Resource Adapter stopped.
Info: RAR7094: jmsra shutdown successful.

Info: JMXStartupService: Stopped JMXConnectorServer: null
Info: JMXStartupService and JMXConnectors have been shut down.
Info: Shutdown procedure finished




What I see is only 2 beans are created and the container attempts to redelivery the 2 messages.
 
Himai Minh
Ranch Hand
Posts: 1359
7
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
With BMT, the message is redelivered when a runtime exception occur (?)


It seems like the message is redelivered even with BMT:

MessageProducerServlet created.
Info: *** QueueListenerEJB created. 1
Severe: MDB00050: Message-driven bean [QueueMessageDrivenExample:QueueListener2]: Exception in creating message-driven ejb : [com.sun.enterprise.container.common.spi.util.InjectionException: Exception attempting to inject Env-Prop: com.ivan.scbcd6.ejbs.QueueListenerEJB/mBeanContext@Field-Injectable Resource. Class name = com.ivan.scbcd6.ejbs.QueueListenerEJB Field name=mBeanContext@java.lang.String@com.ivan.scbcd6.ejbs.QueueListenerEJB/mBeanContext@@ into class com.ivan.scbcd6.ejbs.QueueListenerEJB]
Severe: com.sun.enterprise.container.common.spi.util.InjectionException
com.sun.enterprise.container.common.spi.util.InjectionException: Exception attempting to inject Env-Prop: com.ivan.scbcd6.ejbs.QueueListenerEJB/mBeanContext@Field-Injectable Resource. Class name = com.ivan.scbcd6.ejbs.QueueListenerEJB Field name=mBeanContext@java.lang.String@com.ivan.scbcd6.ejbs.QueueListenerEJB/mBeanContext@@ into class com.ivan.scbcd6.ejbs.QueueListenerEJB
...
at com.sun.ejb.containers.MessageBeanContainer.beforeMessageDelivery(MessageBeanContainer.java:989)
at com.sun.ejb.containers.MessageBeanListenerImpl.beforeMessageDelivery(MessageBeanListenerImpl.java:77)
at com.sun.enterprise.connectors.inbound.MessageEndpointInvocationHandler.invoke(MessageEndpointInvocationHandler.java:163)
at com.sun.proxy.$Proxy189.onMessage(Unknown Source)
.....
Caused by: java.lang.IllegalArgumentException: Can not set javax.ejb.SessionContext field com.ivan.scbcd6.ejbs.QueueListenerEJB.mBeanContext to com.sun.ejb.containers.MessageBeanContextImpl
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:146)
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:150)
at sun.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:63)
at java.lang.reflect.Field.set(Field.java:657)
at com.sun.enterprise.container.common.impl.util.InjectionManagerImpl._inject(InjectionManagerImpl.java:649)
... 17 more

Severe: MDB00042: [QueueMessageDrivenExample:QueueListener2]: No invocation for message []
Warning: MQJMSRA_MR2001: run:Caught Exception from onMessage():Redelivering:
javax.ejb.EJBException: QueueMessageDrivenExample:QueueListener2: message-driven bean invocation closed by container
....

Info: *** QueueListenerEJB created. 2
Severe: MDB00050: Message-driven bean [QueueMessageDrivenExample:QueueListener2]: Exception in creating message-driven ejb : [com.sun.enterprise.container.common.spi.util.InjectionException: Exception attempting to inject Env-Prop: com.ivan.scbcd6.ejbs.QueueListenerEJB/mBeanContext@Field-Injectable Resource. Class name = com.ivan.scbcd6.ejbs.QueueListenerEJB Field name=mBeanContext@java.lang.String@com.ivan.scbcd6.ejbs.QueueListenerEJB/mBeanContext@@ into class com.ivan.scbcd6.ejbs.QueueListenerEJB]
Severe: com.sun.enterprise.container.common.spi.util.InjectionException
com.sun.enterprise.container.common.spi.util.InjectionException: Exception attempting to inject Env-Prop: com.ivan.scbcd6.ejbs.QueueListenerEJB/mBeanContext@Field-Injectable Resource. Class name = com.ivan.scbcd6.ejbs.QueueListenerEJB Field name=mBeanContext@java.lang.String@com.ivan.scbcd6.ejbs.QueueListenerEJB/mBeanContext@@ into class com.ivan.scbcd6.ejbs.QueueListenerEJB
...
at com.sun.enterprise.connectors.inbound.MessageEndpointInvocationHandler.invoke(MessageEndpointInvocationHandler.java:163)
at com.sun.proxy.$Proxy189.onMessage(Unknown Source)
at com.sun.messaging.jms.ra.OnMessageRunner.run(OnMessageRunner.java:260)
...
Caused by: java.lang.IllegalArgumentException: Can not set javax.ejb.SessionContext field com.ivan.scbcd6.ejbs.QueueListenerEJB.mBeanContext to com.sun.ejb.containers.MessageBeanContextImpl
...

Severe: MDB00042: [QueueMessageDrivenExample:QueueListener2]: No invocation for message []
Warning: MQJMSRA_MR2001: run:Caught Exception from onMessage():Redelivering:
....

Info: MQJMSRA_MR1101: run:Message returned & marked for routing to the DMQ


 
Himai Minh
Ranch Hand
Posts: 1359
7
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

When the BMT is rollback, the message is redelivered in Glassfish:

MessageProducerServlet created.
Info: *** QueueListenerEJB created. 1
Severe: MDB00050: Message-driven bean [QueueMessageDrivenExample:QueueListener1]: Exception in creating message-driven ejb : [com.sun.enterprise.container.common.spi.util.InjectionException: Exception attempting to inject Env-Prop: com.ivan.scbcd6.ejbs.QueueListenerEJB/mBeanContext@Field-Injectable Resource. Class name = com.ivan.scbcd6.ejbs.QueueListenerEJB Field name=mBeanContext@java.lang.String@com.ivan.scbcd6.ejbs.QueueListenerEJB/mBeanContext@@ into class com.ivan.scbcd6.ejbs.QueueListenerEJB]
Severe: com.sun.enterprise.container.common.spi.util.InjectionException
com.sun.enterprise.container.common.spi.util.InjectionException: Exception attempting to inject Env-Prop: com.ivan.scbcd6.ejbs.QueueListenerEJB/mBeanContext@Field-Injectable Resource. Class name = com.ivan.scbcd6.ejbs.QueueListenerEJB Field name=mBeanContext@java.lang.String@com.ivan.scbcd6.ejbs.QueueListenerEJB/mBeanContext@@ into class com.ivan.scbcd6.ejbs.QueueListenerEJB
...
Caused by: java.lang.IllegalArgumentException: Can not set javax.ejb.SessionContext field com.ivan.scbcd6.ejbs.QueueListenerEJB.mBeanContext to com.sun.ejb.containers.MessageBeanContextImpl
....
Severe: MDB00042: [QueueMessageDrivenExample:QueueListener1]: No invocation for message []
Warning: MQJMSRA_MR2001: run:Caught Exception from onMessage():Redelivering:
javax.ejb.EJBException: QueueMessageDrivenExample:QueueListener1: message-driven bean invocation closed by container
at com.sun.ejb.containers.MessageBeanContainer.deliverMessage(MessageBeanContainer.java:1163)
at com.sun.ejb.containers.MessageBeanListenerImpl.deliverMessage(MessageBeanListenerImpl.java:81)
....
Info: *** QueueListenerEJB created. 2
Severe: MDB00050: Message-driven bean [QueueMessageDrivenExample:QueueListener1]: Exception in creating message-driven ejb : [com.sun.enterprise.container.common.spi.util.InjectionException: Exception attempting to inject Env-Prop: com.ivan.scbcd6.ejbs.QueueListenerEJB/mBeanContext@Field-Injectable Resource. Class name = com.ivan.scbcd6.ejbs.QueueListenerEJB Field name=mBeanContext@java.lang.String@com.ivan.scbcd6.ejbs.QueueListenerEJB/mBeanContext@@ into class com.ivan.scbcd6.ejbs.QueueListenerEJB]
Severe: com.sun.enterprise.container.common.spi.util.InjectionException
com.sun.enterprise.container.common.spi.util.InjectionException: Exception attempting to inject Env-Prop: com.ivan.scbcd6.ejbs.QueueListenerEJB/mBeanContext@Field-Injectable Resource. Class name = com.ivan.scbcd6.ejbs.QueueListenerEJB Field name=mBeanContext@java.lang.String@com.ivan.scbcd6.ejbs.QueueListenerEJB/mBeanContext@@ into class com.ivan.scbcd6.ejbs.QueueListenerEJB
....
at com.sun.proxy.$Proxy189.onMessage(Unknown Source)
at com.sun.messaging.jms.ra.OnMessageRunner.run(OnMessageRunner.java:260)
....
Caused by: java.lang.IllegalArgumentException: Can not set javax.ejb.SessionContext field com.ivan.scbcd6.ejbs.QueueListenerEJB.mBeanContext to com.sun.ejb.containers.MessageBeanContextImpl
...

Severe: MDB00042: [QueueMessageDrivenExample:QueueListener1]: No invocation for message []
Warning: MQJMSRA_MR2001: run:Caught Exception from onMessage():Redelivering:
javax.ejb.EJBException: QueueMessageDrivenExample:QueueListener1: message-driven bean invocation closed by container
at com.sun.ejb.containers.MessageBeanContainer.deliverMessage(MessageBeanContainer.java:1163)
....
Info: MQJMSRA_MR1101: run:Message returned & marked for routing to the DMQ

Info: Server shutdown initiated
Warning: [MDBContainer] Current thread done cleanup()...
.....


 
Himai Minh
Ranch Hand
Posts: 1359
7
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Based on the three experiment above, it seems to me that Glassfish redelivers the message when UserTransaction.rollback() or system exception occurs during BMT. And Glassfish redelivers the message when the system exception occurs during CMT.
 
Frits Walraven
Creator of Enthuware JWS+ V6
Saloon Keeper
Pie
Posts: 2531
112
Android Chrome Eclipse IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Based on the three experiment above, it seems to me that Glassfish redelivers the message when UserTransaction.rollback() or system exception occurs during BMT

If you do a UserTransaction.rollback() (in BMT) there shouldn't be a redelivery of the message. When I look at your stacktrace it seems there was an EJBException and that caused the redelivery.
Warning: MQJMSRA_MR2001: run:Caught Exception from onMessage():Redelivering:
javax.ejb.EJBException: QueueMessageDrivenExample:QueueListener1: message-driven bean invocation closed by container
 
Himai Minh
Ranch Hand
Posts: 1359
7
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thank for Frits' suggestion. That is true. The EJBException comes from the failure to inject the SessionContext to the MDB.
Instead of using @Resource SessionContext mBeanContext, use @MessageDrivenContext mBeanContext.

This is the code demonstrating a redelivery when the onMessage throws a non-recoverable exception.
The container discards the first instance of MDB when it throws the exception. Then, the container creates another instance of the MDB and attempts to redeliver the message.



Notes that two MDB are created. The first instance of the bean throws an exception and it is discarded. The second instance of the MDB is created and the container tried to re-delivery within a new BMT. But it still fail as the exception is thrown again. Then, the container does not make a third attempt and it stops until the next request comes in.

Info: *** QueueListenerEJB created. 1
Info: *** Transaction begin...
Info: *** Bean 1 received message: com.sun.messaging.jms.ra.DirectObjectPacket@cd7e6ef
Info: Received message with number: 1
Info: Message string: Hello Message Driven Beans
Info: Message time: Thu Mar 19 17:06:18 EDT 2015
Warning: MDB00037: [QueueMessageDrivenExample:QueueListener1]: Message-driven bean invocation exception: [javax.ejb.EJBException: MessageDrivenBean method returned without completing transaction]
Warning: javax.ejb.EJBException
javax.ejb.EJBException: MessageDrivenBean method returned without completing transaction
at com.sun.ejb.containers.BaseContainer.checkExceptionBeanMgTx(BaseContainer.java:4999)
...
Warning: MQJMSRA_MR2001: run:Caught Exception from onMessage():Redelivering:
javax.ejb.EJBException: message-driven bean method public abstract void javax.jms.MessageListener.onMessage(javax.jms.Message) system exception
at com.sun.ejb.containers.MessageBeanContainer.deliverMessage(MessageBeanContainer.java:1128)
...
Caused by: java.lang.RuntimeException
...
at com.sun.ejb.containers.MessageBeanContainer.deliverMessage(MessageBeanContainer.java:1093)

Info: *** QueueListenerEJB created. 2
Info: *** Transaction begin...
Info: *** Bean 2 received message: com.sun.messaging.jms.ra.DirectObjectPacket@cd7e6ef
Info: Received message with number: 1
Info: Message string: Hello Message Driven Beans
Info: Message time: Thu Mar 19 17:06:18 EDT 2015
Warning: MDB00037: [QueueMessageDrivenExample:QueueListener1]: Message-driven bean invocation exception: [javax.ejb.EJBException: MessageDrivenBean method returned without completing transaction]
Warning: javax.ejb.EJBException
javax.ejb.EJBException: MessageDrivenBean method returned without completing transaction
...

Warning: MQJMSRA_MR2001: run:Caught Exception from onMessage():Redelivering:
javax.ejb.EJBException: message-driven bean method public abstract void javax.jms.MessageListener.onMessage(javax.jms.Message) system exception
...
Caused by: java.lang.RuntimeException
at com.ivan.scbcd6.ejbs.QueueListenerEJB.extractMessagePayload(QueueListenerEJB.java:107)
...
 
Himai Minh
Ranch Hand
Posts: 1359
7
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
This demonstrates a BMT transaction rollback in onMessage(). No redelivery is attempted by the EJB container.



Info: *** QueueListenerEJB created. 1
Info: *** Transaction begin...
Info: *** Bean 1 received message: com.sun.messaging.jms.ra.DirectObjectPacket@61fbfb1e
Info: Received message with number: 1
Info: Message string: Hello Message Driven Beans
Info: Message time: Thu Mar 19 17:43:35 EDT 2015
Info: **** Transaction status before rollback: 0
Info: **** Transaction status after rollback : 6


The transaction status = 0 means active transaction. The transaction status = 6 means no transaction. That makes sense.
However, in the status code, there is a Status_ROLLEDBACK constant = 4. I am curious why the transaction status is not 4 after the transaction is rolled back ?
 
Frits Walraven
Creator of Enthuware JWS+ V6
Saloon Keeper
Pie
Posts: 2531
112
Android Chrome Eclipse IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
However, in the status code, there is a Status_ROLLEDBACK constant = 4. I am curious why the transaction status is not 4 after the transaction is rolled back ?

The status is related to the transaction that is associated with the MDB. As soon as you have executed the rollback() method, the transaction is gone and therefore there won't be any transaction related to the MDB (until another message arrives). The Status_ROLLEDBACK is visible for instance when you invoke ut.setRollbackOnly() before you actually invoke the ut.commit() or ut.rollback().
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic