Friday, March 12, 2010

JMS Security, Concurrency and Triggers

This is the 2nd in a series of posts around JMS 1.1, focusing on things that can guide design decisions when putting a JMS application together. In this writeup, I'll discuss security, concurrency and the use of triggers.


JMS 1.1, section 2.7: JMS does not provide features for controlling or configuring message integrity or message privacy. It is expected that many JMS providers will provide such features. It is also expected that configuration of these services will be handled by provider specific administration tools. Clients will get the proper security configuration as part of the administered objects they use.

Decision: does the application need authentication, confidentiality, etc.?

Idioms: Any client authentication is handled by the Connection object. A JMSSecurityException is thrown when authentication credentials are rejected by the provider, or whenever any security restriction prevents a method from completing.

Caveat: Any security measures applied will not be portable across JMS providers. Remember that authentication and confidentiality exercises are relatively heavyweight; combined with the heavy lifting of setting up network connectivity, this motivates minimizing the number of connections in use (and, for that matter, of using connection caches).


Of the six top-level JMS objects, only Destination, ConnectionFactory and Connection are intended for multi-threaded access.  The Session, MessageProducer and MessageConsumer are intended for single-thread use only. See the JMS 1.1 spec, section 2.8 for an in-depth rationale around this restriction - bottom line, this makes it easier for the typical JMS client, with concurrency possible if needed by using multiple sessions.

JMS providers must prevent concurrent access to a given client's state that could result in messages being lost or processed redundantly - whether that's done by an exception being thrown, or blocking the offending client, or otherwise.

Idioms: Note that this doesn't mean multiple threads can't use a given Session object - it just means the developer must ensure the access is not concurrent. Using one thread only is the simplest way to ensure this; otherwise, explicit synchronization is called for. The standard approach to setting up asynchronous delivery is using a single thread for setup while the Connection is stopped, then use that same thread to start the Connection. Concurrent access to a session's producers and consumers is also not allowed. If a client uses one thread to produce messages and other threads to consume them, use of a separate session for the producing thread is called for. Once a connection has been started, do not use any Session method except close; using a separate thread of control to close a Session is allowed. This restriction applies in particular to setting up multiple message listeners - all of these must be established before the connection is started.

Caveat: While a client may have multiple sessions, JMS does not define the behavior around concurrent QueueReceivers for the same Queue; relying on a given provider's support for this is not portable. Note that the Session serializes execution of asynchronous deliveries, using a single thread to run all MessageListeners.  One consequence of this is that a session with asyncronous listeners cannot be used to also receive messages synchronously.

Recommendation: Consider the effect of the session's serial execution on your target throughput. For higher throughput via concurrency, use multiple sessions. However, note that it is not considered reliable to use a single consumer with application-level multi-threading logic to concurrently process messages from a topic (due to lack of adequate transaction facility in JMS). JMS does, however, provide a special facility for creating MessageConsumers that can consume messages concurrently, via application server support; see section 8 in the spec. The application developer presents a single-threaded program if using this facility.


A trigger is e.g. a threshold of waiting messages, a length of time that has gone by, a time of day, etc., which is used to wake up a client so it will process any waiting messages. Keep in mind that any such mechanism, if available in the provider you use, is not specified by the JMS spec, and as such is not portable.

Caveat: any trigger mechanisms will not be portable across JMS providers.

In the next several posts in this series, I'll discuss things like request/reply, message ID, timestamp, message expiration and message priority.

No comments:

Post a Comment