Search code examples
jmsibm-mqxmsjms-session

How to use multiple sessions per connection in a multi-threaded application?


Suppose I have one connection c and many session objects s1, s2 .. sn, each working in different threads t1, t2 ... tn.

                                      c
                                      |
                -------------------------------------------------
                |          |          |                         |
             (t1,s1)    (t2,s2)    (t3,s3)      ......       (tn,sn)

Now suppose one of the thread t3 wants to send a message to a particular queue q3 and then listen to the reply asynchronously. So it does the following:

 1:   c.stop();

 2:   auto producer = s3.createProducer(s3.createQueue(q3));
 3:   auto text = s3.createTextMessage(message);
 4:   auto replyQueue = s3.createTemporaryQueue();
 5:   text.setJMSReplyTo(replyQueue);
 6:   producer.send(text);

 7:   auto consumer = s3.createConsumer(replyQueue);
 8:   consumer.setMessageListener(myListener);

 9:   c.start();

The reason why I called c.stop() in the beginning and then c.start() in the end, because I'm not sure if any of the other threads has called start on the connection (making all the sessions asynchronous — is that right?) and as per the documentation:

"If synchronous calls, such as creation of a consumer or producer, must be made on an asynchronous session, the Connection.Stop must be called. A session can be resumed by calling the Connection.Start method to start delivery of messages."

So calling stop in the beginning of the steps and then start in the end seems reasonable and thus the code seems correct (at least to me). However, when I thought about it more, I think the code is buggy, as it doesn't make sure no other threads call start before t3 finishes all the steps.

So my questions are:

  • Do I need to use mutex to ensure it? Or the XMS handles it automatically (which means my reasoning is wrong)?
  • How to design my application so that I dont have to call stop and start everytime I want to send a messages and listen reply asynchronously?
  • As per the quoted text above, I cannot call createProducer() and createConsumer() if the connection is in asynchronous mode. What are other methods I cannot call? The documentation doesn't categorise the methods in this way:

Also, the documentation doesn't say clearly what makes a session asynchronous. It says this:

"A session is not made asynchronous by assigning a message listener to a consumer. A session becomes asynchronous only when the Connection.Start method is called."

I see two problems here:

  • Calling c.start() makes all sessions asynchronous, not just one.
  • If I call c.start() but doesn't assign any message listener to a consumer, are the session(s) still asynchronous?

It seems I've lots of questions, so it'd be great if anyone could provide me with links to the parts or sections of the documentation which explains XMS objects with such minute details.

This says,

"According to the specification, calling stop(), close() on a Connection, setMessageListener() on a Session etc. must wait till all message processing finishes, that is till all onMessage() calls which have already been entered exit. So if anyone attempts to do that operation inside onMessage() there will be a deadlock by design."

But I'm not sure if that information is authentic, as I didn't find this info on IBM documentation.


Solution

  • I prefer the KIS rule. Why don't you use 1 connection per thread? Hence, the code would not have to worry about conflicts between threads.