Search code examples
javamultithreadingjmscommitjms-session

JMS: Is it OK to read via MessageConsumer.receive() on one thread, then call Session.commit() from another thread?


The spec for JMS sessions warns that Session objects/instances must only be used on the thread in which they are created when there are MessageListener instances registered to a Session. However, it doesn't say anything about being thread-un-safe, or perhaps more accurately, "thread-bound", when using MessageConsumer objects (only).

http://docs.oracle.com/javaee/1.3/api/javax/jms/Session.html

(by "thread-bound", I mean that the object must only be used, ever, on a specific thread, not just that it's unsafe to use it on multiple threads without synchronization or other coordination)

The answer to this question also suggests that Sessions are thread-bound: Relationship between JMS connections, sessions, and producers/consumers

However, there may or may not be some assumptions the author is making, and the question is also more about writing messages than about reading them.

Does anybody know if you can read a message in a Session on one thread, and then have another thread deal with the message and do a commit/rollback for the message (with the session) on that other thread? Only commit (or rollback) would be called against the Session from within the processing thread -- no other calls would be made to the Connection / Session / MessageConsumer / Message chain. Also, the Session would not be used to read again until after the commit/rollback occurred.

The following S/O questions seem closely related, but do no satisfactorily address what I am proposing:

How to continuously read JMS Messages in a thread and achnowledge them based on their JMSMessageID in another thread?

Reason for a JMS Session object to be used in a single threaded context

While I would like to use a Session on multiple threads, there will never be overlapping message requests/transactions.

I'm trying to avoid further refactoring of existing code, so I'm considering doing something a little odd, rather than having a Session on each worker thread.

      • edit (July 26) - - -

This question, Using a JMS Session from different threads, seems to suggest that it is OK to do synchronized operations with a session on different threads, but I am uncertain which version of the spec is referenced.


Solution

  • Maybe you have found a way in the specification.

    A quote from the doc of Sessionhttp://docs.oracle.com/javaee/1.3/api/javax/jms/Session.html

    A Session object is a single-threaded context for producing and consuming messages. Although it may allocate provider resources outside the Java virtual machine (JVM), it is considered a lightweight JMS object.

    So it's single-threaded; and it's not expensive to create one.

    And you have to pay attention to

    The close method is the only session method that can be called while some other session method is being executed in another thread.

    So you have to make sure that read and commit do not overlap, for example.

    From a technical point of view I would refactor it; the code will be easier to read/maintain. Resource handling (open/close) would be in one thread (one method) only. This would simplify exception handling as well.

    [From a legal point of view: You admit that you are doing something "odd" - against the recommendation. I would not deliver such a piece of software.]