1

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.

Community
  • 1
  • 1
Roboprog
  • 3,054
  • 2
  • 28
  • 27
  • As for your update (edit July 26), this is what I'd liked to point out with my 2nd quote: You have to synchronize every method except for `close`. So while you save 10ms (by not creating a separate session) initiallly, you have to spend time on each synchronized method invocation later. If you do not already have that synchronization, you have to refactor your code anyway (and this is possibly error-prone). Possibly that's the reason for the recommendation not to do it this way. – Beryllium Jul 27 '13 at 11:46

1 Answers1

1

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.]

Beryllium
  • 12,808
  • 10
  • 56
  • 86
  • Thanks for the answer. FWIW, creating a session + required consumer from the session takes about 250 ms, at least to do once within the environment I happen to be using at the moment. I would not consider that too lightweight :-) – Roboprog Jul 26 '13 at 15:14
  • @Roboprog I agree, I wouldn't call that lightweight either. Does it always take that time? In other words, if you create another session from the same `QueueConnection`, does it still take that long? Which JMS implemementation is it? – Beryllium Jul 26 '13 at 15:21
  • 1
    Had a chance to go back and embellish test scaffolding: subsequent session + message-consumer pairs take about 5 to 10 millis to make. If I said what hardware and message vendor it was, somebody would probably sue me for bad, unauthorized benchmarking :-) – Roboprog Jul 27 '13 at 03:10
  • @Roboprog OK, 10ms is still something to consider, but it's much better. – Beryllium Jul 27 '13 at 11:41
  • Thanks. The simplest thing is going to be to make a session for each thread with the same lifetime as the thread. – Roboprog Aug 22 '13 at 18:59