File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
The moose likes EJB and other Java EE Technologies and the fly likes How to not acknowledge a JMS message from an MDB Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » EJB and other Java EE Technologies
Bookmark "How to not acknowledge a JMS message from an MDB" Watch "How to not acknowledge a JMS message from an MDB" New topic
Author

How to not acknowledge a JMS message from an MDB

Paul Boyce
Greenhorn

Joined: May 31, 2004
Posts: 7
Hello!

Any ideas how I can not acknowledge a message from a message driven bean (MDB) so it returns to the queue to be delivered again later???

My intention is to use a queue to store messages, and if the message cannot be processed when it comes off the queue (there is business logic in theMDB that decides if the message has to wait), i want the message to remain on the queue, to be redelivered later.

As I understand, an MDB will auto-acknowledge a message when the onMessage() method completes. By the J2EE spec, I cant throw an exception from the MDB, so how do I not acknowledge a message so it stays on the queue?

By the way, I am using a queue on JBoss 3.2.3.

Many thanks for your help,
Paul
Ajai
Ranch Hand

Joined: May 29, 2002
Posts: 198
Just throwing an idea.

How about using two queues.
Put the message that you can not process on second queue.
But you will have to use 2MDBs then.

Thks.
Nathaniel Stoddard
Ranch Hand

Joined: May 29, 2003
Posts: 1258
There are other "values" for the acknowledgement portion of your deployment descriptors. You should read up in the spec for your options.


Nathaniel Stodard<br />SCJP, SCJD, SCWCD, SCBCD, SCDJWS, ICAD, ICSD, ICED
Paul Boyce
Greenhorn

Joined: May 31, 2004
Posts: 7
Hey! I got it sorted!

Its a pretty simple solution as follows:

1) Make Message Bean run with Container managed transaction and "Requires Transaction". (This ensures each execution of onMessage() runs in its own transaction.) The important settings in the deployment descriptor are:

<transaction-type>Container</transaction-type>
<acknowledge-mode>Auto-acknowledge</acknowledge-mode>

<trans-attribute>Required</trans-attribute>

2) A message is automatically acknowledged when the onMessage() method returns. To fail a message (i.e. not acknowledge it and leave it on the queue) simply call setRollBackOnly() on the MessageDrivenContext.

sample code:

public void setMessageDrivenContext(MessageDrivenContext newContext)
throws EJBException {
this.ctx = newContext;
}


public void onMessage(Message msg) {


// Cast the message to the expected type of object
TextMessage message = (TextMessage) msg;

boolean returnToQueue = true;
if (returnToQueue)
{
// Send message back ionto the queue to get reprocessed.
System.out.println("Message not cancelled - sending back to queue...");
ctx.setRollbackOnly();
}
}




For example my ebj-jar.xml contains as follows:

<ejb-jar >

<enterprise-beans>

<message-driven >

<ejb-name>RTSCRequestManagerBean</ejb-name>

<ejb-class>com.rtel.mdb.RTSCRequestManagerBean</ejb-class>

<transaction-type>Container</transaction-type>
<acknowledge-mode>Auto-acknowledge</acknowledge-mode>

<message-driven-destination>
<destination-type>javax.jms.Queue</destination-type>
</message-driven-destination>

<resource-ref >
<res-ref-name>jms/QueueConnectionFactory</res-ref-name>
<res-type>javax.jms.QueueConnectionFactory</res-type>
<res-auth>Container</res-auth>
</resource-ref>

</message-driven>
</enterprise-beans>

<container-transaction >
<method >
<ejb-name>RTSCRequestManagerBean</ejb-name>
<method-name>*</method-name>
</method>
<trans-attribute>Required</trans-attribute>
</container-transaction>

</ejb-jar>


cheers,
Paul
Andy Zhong
Greenhorn

Joined: Nov 03, 2004
Posts: 1
I tried the solution you posted. But it seems the message is still be consumed after setRollBackOnly. Any idea?

The code is specified below: Both system print messages are displayed on the prompt.
boolean isStop=true;
try{
if(isStop){
System.out.println("The Message will send back to the queue for redelivering");
context.setRollbackOnly();
}
String msgFileName = (StreamMessage)message.readString();
System.out.println("Get sourceFile:"+msgFileName );
nilesh Katakkar
Ranch Hand

Joined: Oct 27, 2004
Posts: 35
Just a wild guess... Can you try setting context.setRollbackOnly as your last statement. In your code after setting rollback you are reading back from the message again. May be that causes a new transaction to start.

boolean isStop=true;
try{
String msgFileName = (StreamMessage)message.readString();
System.out.println("Get sourceFile:"+msgFileName );
if(isStop){
System.out.println("The Message will send back to the queue for redelivering");
context.setRollbackOnly();
}


nilesh<br />neilindallas@hotmail.com
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: How to not acknowledge a JMS message from an MDB
 
Similar Threads
Message Driven Beans
JMS Message Driven Bean
application up but Messages not processed
CLIENT_ACKNOWLEDGE
Message-driven bean acknowledgment.