This question mainly focuses on Websphere Application Server (WAS) when using Websphere MQ (WMQ), as this is what I am most familiar with. However, I think that everything I am talking about more generally applies to all Java EE application servers, as I adhere to standard Java interfaces. I would prefer an explanation related to standards, but I would still be delighted with the answer specific to WAS / WMQ.
JMS 1.1 defines the mechanism by which JMS interacts with the application server. The rough process is that a ConnectionConsumer is created at some point to monitor the queue or topic. When a message appears, the JMS implementation receives a ServerSession object from ServerSessionPool, loads the message into the session associated with ServerSession, and then calls start () on the ServerSession object. ServerSession is then responsible for scheduling a message for processing the MDB in the application server thread. The MDB receives the message as part of its onMessage () method and can perform any necessary processing.
This is all good until the MDB decides that he wants to send another message in response to the one he received. To do this, the MDB must search or enter a ConnectionFactory object, receive a connection, then a session, then MessageProducer, and then finally send a message. All this seems rather wasteful. As part of delivering messages to MDB, a Connection and Session object has already been created. If the MDB could somehow access this session, it could avoid the need to do all this extra work and avoid creating all these extra connections. This extra work as a cost - just to send a response message to a request message, the MDB must use two connections and two sessions (one each to receive the message and send the response). When using global transactions, I believe that this forces the application server to process the transaction as a two-phase transaction (at least some, if not all, application servers can optimize a global transaction that includes only one resource, treating it as a single-phase commit). The execution of a two-phase transaction transaction significantly increases the overhead of processing the message, and also introduces all kinds of new complexity (questionable transactions are one of the largest).
JMS 1.1 specifications: "Since many listeners will need to use the services of their session, the listener is likely to require that their session be passed to him as a constructor parameter," which seems to indicate that it will be perfectly acceptable for the MDB to use the session who sent the original message to send a response. However, I do not know of any mechanism for retrieving this Session object from the MDB in a standard way. I also do not know any mechanism for obtaining it in a non-standard way. I can't even find a question or blog post about this anywhere.
So the question is: why is this so? The JMS API is rather confusing, but I donβt see anything in it, which makes it difficult for the MDB to use the session that gave it the original message to send a response if it could access it. Is there a reason MDB will not be able to use this Session object? Is there a standards-compliant way to access a session? Is there a way that does not meet the standards? Are JMS server applications / implementations smart for optimizing a global transaction, including operations on two connections in the same JMS queue manager, in a single-phase transaction (my research and understanding of the standards seem to indicate that this is not possible)?