Can I get the original JMS session in MDB?

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)?

+4
source share
1 answer

Are JMS server applications / implementations smart for optimizing a global transaction that includes operations on two connections on the same JMS queue manager in a single-phase commit transaction (my research and understanding of the standards seems to be impossible)?

My understanding is this: JMS is a special JCA connector. Typically, a connector has an internal pool of managed connections that correspond to physical connections. A managed connection can only be involved in one transaction at a time (but transactions can be paused and resumed, so they are a bit complicated). What beans get are connection handles. If a bean receives multiple connection descriptors from a given transaction, then the same managed connection is supported on the handles, which means that it should not include a distributed transaction.

Of course, this depends on the implementation of the connector and the application server. You can try this by setting up the JMS resource as non-XA (there should be an option where you can enable / disable XA support ) and see if you can receive the message in MDB and send another message to the queue. It works, which means that distributed transactions are not involved.

Note. The general optimization is β€œ Optimization of the latest resources ”, which allows one of the participants in a distributed transaction to actually be a local participant, using it as the last resource. This last member never knows that it belongs to a distributed transaction.

0
source

All Articles