简体   繁体   中英

How do I delay JMS Message sending?

How do I delay JMS Message sending or proceed uncertain time?

I am using Weblogic, as you know, after JMS sending, the receiver will process the message asynchronously, but, at this time or sometimes the external resource are not ready for the receiver, therefore, I want to have some check logic to delay send or process the message. I guess for example: I put the message into pending queue then frequently check the resource availability, once it is then send or proceed the message?

Do everybody know does Weblogic support this or how to implement it?

You can absolutely do this in JMS, just use a local queue for storing the messages; send to remote queue when receiver is available.

Option 1 (Ideal, Safe)

1) First, create a JMS Server in WebLogic, LocalJMSServer .

2) Make sure to target this resource only to the local WebLogic instance only.

3) Create a queue, tempQueue , for LocalJMSServer .

4) Your application always sends messages to tempQueue . Since that queue is local, the messages just sit on the queue, and they are persisted too which is nice in case server crashes.

5) You'll need a separate JMSServer configuration in WebLogic to host the remoteQueue since that queue will be targeted to a remote WebLogic instance.

6) Your application periodically checks the remote receiver for availability:

   if( receiverIsAvailable()){
    ...
   }

...when the receiver is available, dequeue messages from tempQueue and send to remoteQueue ...

Queue tempQueue = (Queue) ctx.lookup("tempQueue");
QueueSession queueLocalSession = 
  queueConn.createQueueSession(false,
     Session.CLIENT_ACKNOWLEDGE);  
QueueReceiver queueReceiver = queueLocalSession.createReceiver(tempQueue);
TextMessage localMessage = (TextMessage) queueReceiver.receive();

//send to remote queue
Queue remoteQueue = (Queue) ctx.lookup("remoteQueue");
QueueSender queueSender = queueRemoteSession.createSender(remoteQueue);
Message newMessage = queueRemoteSession.createTextMessage(
  localMessage.getText());
queueSender.send( newMessage);

//now acknowledge the message since we safely sent to remoteQueue
localMessage.acknowledge(); 

I like this approach because it's fully transactional; if anything goes wrong, you don't lose messages provided you use PERSISTENT mode. Also, when pulling message from tempQueue , you must use a synchronous receiver (as above), you can't use onMessage() since it processes messages from the local queue immediately.

Option 2 (Simpler, Less Safe)

You can also use in-memory queue (not JMS ) for storing the message content locally:

ArrayBlockingQueue queue = new ArrayBlockingQueue<String>();
queue.add(messageContents1);
queue.add(messageContents2);
...

Your application checks for resource availability on the receiving side, if it's available, just dequeue and send the real JMS messages with no delay:

if( receiverIsAvailable()){
   while(!queue.isEmpty()){
      Message message = session.createTextMessage();
      message.setText(queue.take());
      queueSender.send(message);
   }
}

The problem with this approach is that messages stored in queue reside in memory; if the sender crashes, you'll lose those message.

Hope it helps!

Normally to delay receiving of the messages until the resources are ready, the connection.start() method is not invoked. Here is the logic:

  1. The receiver starts and makes a connection and sets up all JMS resources.
  2. The connection.start() is not invoked.
  3. Wait for other resources to initialize
  4. Start the JMs connection using connection.start()

You can even pause the messages to be received by the message listener using this method. This technique is very common in GUI tools that use JMS.

Assuming your using Websphere MQ, I don't thinks it's supported.

JMS 2.0 does have support for delayed delivery[1] of messages, but without more information it's tough to answer.

[1] https://java.net/projects/jms-spec/pages/JMS20FinalRelease#What_s_new_in_JMS_2.0 ?

You can have your receiver block if the external resource is not ready. Since the receiver is "busy" no more messages will be pulled off of the queue while it is blocked.

Have you looked at the time-to-deliver setting for JMS objects configured in the WebLogic server?

Oracle WebLogic docs

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM