Properties
The following list gives the name of each standard property of Message
.JMS reserves the "JMSX" property name for these and future JMS-defined properties.
Using Properties
Property values are set prior to sending a message. When a client receives a message, its properties are in read-only mode. If a client attempts to set properties at this point, a MessageNotWriteableException is thrown.
Message Body
There are five forms of message body, and each form is defined by an interface that extends Message
. These interfaces are:
StreamMessage
: Contains a stream of Java primitive values that are filled and read sequentially using standard stream operations.
MapMessage
: Contains a set of name-value pairs; the names are of type string
and the values are Java primitives.
TextMessage
: Contains a String
.
ObjectMessage
: Contains a Serializable
Java object; JDK 1.2 collection classes can be used.
BytesMessage
: Contains a stream of uninterpreted bytes; allows encoding a body to match an existing message format.
Each provider supplies classes specific to its product that implement these interfaces. It is important to note that the JMS specification mandates that providers must be prepared to accept and handle a Message
object that is not an instance of one of its own Message
classes.
Transaction
A JMS transaction groups a set of produced messages and a set of consumed messages into an atomic unit of work. If an error occurs during a transaction, the production and consumption of messages that occurred before the error can be "undone."
Session
objects control transactions, and a Session
can be denoted as transacted when it is created. A transacted Session
always has a current transaction, that is, there is no begin()
; commit()
and rollback()
end one transaction and automatically begin another.
Distributed transactions can be supported by the Java Transaction API (JTA) XAResource
API, though this is optional for providers.
Message Selection
JMS provides a mechanism, called a message selector, for a JMS program to filter and categorize the messages it receives.
The message selector is a String
that contains an expression whose syntax is based on a subset of SQL92. The message selector is evaluated when an attempt is made to receive a message, and only messages that match the selection criteria of the selector are made available to the program.
Selection is based on matches to header fields and properties; body values cannot be used for selection.
Acknowledgment
Acknowledgment is the mechanism whereby a provider is informed that a message has been successfully received.
If the Session
receiving the message is transacted, acknowledgment is handled automatically. If the Session
is not transacted, then the type of acknowledgment is determined when the Session
is created.
There are three types of acknowledgment:
Session.DUPS_OK_ACKNOWLEDGE
: Lazy acknowledgment of message delivery; reduces overhead by minimizing work done to prevent duplicates; should be used only if duplicate messages are expected and can be handled.
Session.AUTO_ACKNOWLEDGE
: Message delivery is automatically acknowledged upon completion of the method that receives the message.
Session.CLIENT_ACKNOWLEDGE
: Message delivery is explicitly acknowledged by calling the acknowledge()
method on the Message
.
A session’s recover method is used to stop a session and restart it with its first unacknowledged message. In effect, the session’s series of delivered messages is reset to the point after its last acknowledged message. The messages it now delivers may be different from those that were originally delivered due to message expiration and the arrival of higher-priority messages.
A session must set the redelivered flag of messages it redelivers due to a
recovery.
It is up to a JMS application to deal with this ambiguity. In some cases, this may cause a client to produce functionally duplicate messages. A message that is redelivered due to session recovery is not considered a duplicate message.
Duplicate Delivery of Messages
A JMS provider must never deliver a second copy of an acknowledged message. When a client uses the AUTO_ACKNOWLEDGE mode, it is not in direct control of message acknowledgment. Since such clients cannot know for certain if a particular message has been acknowledged, they must be prepared for redelivery of the last consumed message. This can be caused by the client
completing its work just prior to a failure that prevents the message acknowledgment from occurring. Only a session’s last consumed message is subject to this ambiguity. The JMSRedelivered message header field will be set for a message redelivered under these circumstances.
Duplicate Production of Messages
JMS providers must never produce duplicate messages. This means that a client that produces a message can rely on its JMS provider to insure that consumers of the message will receive it only once. No client error can cause a provider to duplicate a message. If a failure occurs between the time a client commits its work on a Session and the commit method returns, the client cannot determine if the transaction was committed or rolled back. The same ambiguity exists when a failure occurs between the non-transactional send of a PERSISTENT message and the return
from the sending method.
Synchronous Delivery
A client can request the next message from a MessageConsumer using one of its receive methods. There are several variations of receive that allow a client to poll or wait for the next message.
Asynchronous Delivery
A client can register an object that implements the JMS MessageListener interface with a MessageConsumer. As messages arrive for the consumer, the provider delivers them by calling the listener’s onMessage method. It is possible for a listener to throw a RuntimeException.
Message Delivery Mode
JMS supports two modes of message delivery.
• The NON_PERSISTENT mode is the lowest-overhead delivery mode because it does not require that the message be logged to stable storage. A JMS provider failure can cause a NON_PERSISTENT message to be lost.
• The PERSISTENT mode instructs the JMS provider to take extra care to insure the message is not lost in transit due to a JMS provider failure. A JMS provider must deliver a NON_PERSISTENT message at-most-once. This means that it may lose the message, but it must not deliver it twice.
A JMS provider must deliver a PERSISTENT message once-and-only-once. This means a JMS provider failure must not cause it to be lost, and it must not deliver it twice.
PERSISTENT (once-and-only-once) and NON_PERSISTENT (at-most-once) message delivery are a way for a JMS client to select between delivery techniques that may lose a messages if a JMS provider dies and those which take extra effort to insure that messages can survive such a failure.
There is typically a performance/reliability trade-off implied by this choice. When a
client selects the NON_PERSISTENT delivery mode, it is indicating that it values performance over reliability; a selection of PERSISTENT reverses the requested trade-off. The use of PERSISTENT messages does not guarantee that all messages are always delivered to every eligible consumer.