• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

How to not acknowledge a JMS message from an MDB

 
Greenhorn
Posts: 7
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
 
Ranch Hand
Posts: 198
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.
 
Ranch Hand
Posts: 1258
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
There are other "values" for the acknowledgement portion of your deployment descriptors. You should read up in the spec for your options.
 
Paul Boyce
Greenhorn
Posts: 7
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
 
Greenhorn
Posts: 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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 );
 
Ranch Hand
Posts: 35
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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();
}
 
With a little knowledge, a cast iron skillet is non-stick and lasts a lifetime.
reply
    Bookmark Topic Watch Topic
  • New Topic