How to store messages in the JMS message queue if there are any errors after using the message?

My scenario is I send a message to the queue and when the message is consumed, I send it to a third-party middleware application. If this middleware application does not work, my message is sent for sending. I do not want to lose this message if the middleware application is omitted; instead, I want it to be paused or pending in the queue. Please suggest how to handle this scenario?

+7
java middleware jms message-queue
source share
4 answers

You should create a session as follows:

Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE); 

when you try to deliver a message to a third-party application:

  • If it works, you should acknoledge a message.

  • If it does not work, you should not ignore it, so the JMS provider will be able to update it and the message will not be lost. message.acknowledge();

Also, you can take a look at this: JMS AUTO_ACKNOWLEDGE when is it confirmed?

+4
source share

JMS Queues are not message stores.

If you have a "bad message" for which processing continues to fail, then the JMS server (if configured) will inevitably drop this message into the "dead message queue", which will slowly fill up until another process depletes it.

You donโ€™t want bad messages in the queue, since they can potentially block the queue (imagine that you have 10 users, and the top 10 messages are bad, so all processes continue, messages stop the queue).

So, you need some kind of mechanism for storing messages in the exception receiver, where later they can be introduced into the main queue for processing.

The dead message queue is not this mechanism (do not store messages in the JMS queue), rather it may be a mechanism for exclusive ROUTE messages for a more permanent storage area (i.e. db table or something else).

After that, they can be checked (automatically, manually, independently) and either re-added or canceled.

But the key point is the need for an external mechanism for this, the JMS server itself is not suitable for such messages.

+5
source share

This can be achieved by using session confirmation. To do this, first change your producer code to use Session.AUTO_ACKNOWLEDGE. When creating a queue session, set AUTO_ACKNOWLEDGE to false. This means that the consumer must recognize. When the consumer sends a confirmation message, the message will be removed from the queue, otherwise it will remain in the queue.

Below is the manufacturer code.

 try { QueueConnectionFactory qcf = AppUtils.getQueueConnectionFactory(); Queue q = AppUtils.getDestination(); QueueConnection qConnection = qcf.createQueueConnection(); QueueSession qSession = qConnection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); QueueSender qSender = qSession.createSender(q); qConnection.start(); TextMessage msg = qSession.createTextMessage("Hello"); qSender.send(msg); qSender.close(); qConnection.close(); } catch (JMSException e) { // log your error to log file e.printStackTrace(); } 

On the consumer side, you must do the same, create a queue session with AUTO_ACKNOWLEDGE as false.

After working with your message, you can send a confirmation to remove the message from the queue, or the message will remain in the queue.

 try { QueueConnectionFactory qcf = getQueueConnectionFactory(); Queue q = getDestination(); QueueConnection qConnection = qcf.createQueueConnection(); QueueSession qSession = qConnection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); QueueReceiver qReceiver = qSession.createReceiver(q); qConnection.start(); Message msg = qReceiver.receive(); // here send your message to third party application //if your third party application is down if(thirdpartyapp is down){ //here you can raise an exception //or just do nothing // you're not sending acknowledgement here so the msg will //remain in the queue }else{ msg.acknowledge();//here youre sending ack, so msg will be deleted qReceiver.close(); qConnection.close(); } } catch (JMSException e) { // TODO Auto-generated catch block e.printStackTrace(); } 
+3
source share

Although itโ€™s not entirely clear how your application is designed that consumes messages, I suggest you change the consumer application to consume messages within a local transaction and send a message to a third-party tool. If the message is successful, you can commit the transaction, which will remove the message from the JMS queue. If your application cannot send the message, you can simply execute a rollback transaction that will make the message reappear in the JMS queue. This message will be delivered again.

0
source share

All Articles