A session is a single-threaded context for producing and consuming messages. You can create multiple message producers and consumers for a single session, but you are restricted to using them serially, in a single logical thread of control.
Table 2–3 shows the methods defined in the Session interface; they are discussed in the relevant sections below.
Table 2–3 Session Methods
Name |
Description |
---|---|
Create message producer |
|
Create message consumer |
|
Create durable subscriber for topic |
|
Delete durable subscription to topic |
|
Create null message |
|
Create text message |
|
Create stream message |
|
Create map message |
|
Create object message |
|
Create bytes message |
|
Create queue destination |
|
Create topic destination |
|
Create temporary queue |
|
Create temporary topic |
|
Create message browser |
|
Set distinguished message listener |
|
Get distinguished message listener |
|
Get session’s acknowledgment mode |
|
Is session transacted? |
|
Commit transaction |
|
Roll back transaction |
|
Recover unacknowledged messages |
|
Close session |
Every session exists within the context of a particular connection. The number of sessions you can create for a single connection is limited only by system resources. As described earlier (see Using Connections), you use the connection’s createSession method to create a session:
Session mySession = myConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
The first (boolean) argument specifies whether the session is transacted; see Transacted Sessions for further discussion. The second argument is an integer constant representing the session’s acknowledgment mode, as described in the next section.
A session’s acknowledgment mode determines the way your application handles the exchange of acknowledgment information when receiving messages from a broker. The JMS specification defines three possible acknowledgment modes:
In auto-acknowledge mode, the Message Queue client runtime immediately sends a client acknowledgment for each message it delivers to the message consumer; it then blocks waiting for a return broker acknowledgment confirming that the broker has received the client acknowledgment. This acknowledgment “handshake” between client and broker is handled automatically by the client runtime, with no need for explicit action on your part.
In client-acknowledge mode, your client application must explicitly acknowledge the receipt of all messages. This allows you to defer acknowledgment until after you have finished processing the message, ensuring that the broker will not delete it from persistent storage before processing is complete. You can either acknowledge each message individually or batch multiple messages and acknowledge them all at once; the client acknowledgment you send to the broker applies to all messages received since the previous acknowledgment. In either case, as in auto-acknowledge mode, the session thread blocks after sending the client acknowledgment, waiting for a broker acknowledgment in return to confirm that your client acknowledgment has been received.
In dups-OK-acknowledge mode, the session automatically sends a client acknowledgment each time it has received a fixed number of messages, or when a fixed time interval has elapsed since the last acknowledgment was sent. (This fixed batch size and timeout interval are currently 10 messages and 7 seconds, respectively, and are not configurable by the client.) Unlike the first two modes described above, the broker does not acknowledge receipt of the client acknowledgment, and the session thread does not block awaiting such return acknowledgment from the broker. This means that you have no way to confirm that your acknowledgment has been received; if it is lost in transmission, the broker may redeliver the same message more than once. However, because client acknowledgments are batched and the session thread does not block, applications that can tolerate multiple delivery of the same message can achieve higher throughput in this mode than in auto-acknowledge or client-acknowledge mode.
Message Queue extends the JMS specification by adding a fourth acknowledgment mode:
In no-acknowledge mode, your client application does not acknowledge receipt of messages, nor does the broker expect any such acknowledgment. There is thus no guarantee whatsoever that any message sent by the broker has been successfully received. This mode sacrifices all reliability for the sake of maximum throughput of message traffic.
The standard JMS Session interface, defined in package javax.jms, defines static constants for the first three acknowledgment modes (AUTO_ACKNOWLEDGE, CLIENT_ACKNOWLEDGE, and DUPS_OK_ACKNOWLEDGE), to be used as arguments to the connection’s createSession method. The constant representing the fourth mode (NO_ACKNOWLEDGE) is defined in the extended Message Queue version of the interface, in package com.sun.messaging.jms. The session method getAcknowledgeMode returns one of these constants:
int ackMode = mySession.getAcknowledgeMode(); switch (ackMode) { case Session.AUTO_ACKNOWLEDGE: /* Code here to handle auto-acknowledge mode */ break; case Session.CLIENT_ACKNOWLEDGE: /* Code here to handle client-acknowledge mode */ break; case Session.DUPS_OK_ACKNOWLEDGE: /* Code here to handle dups-OK-acknowledge mode */ break; case com.sun.messaging.jms.Session.NO_ACKNOWLEDGE: /* Code here to handle no-acknowledge mode */ break; }
All of the acknowledgment modes discussed above apply to message consumption. For message production, the broker’s acknowledgment behavior depends on the message’s delivery mode (persistent or nonpersistent; see Message Header). The broker acknowledges the receipt of persistent messages, but not of nonpersistent ones; this behavior is not configurable by the client.
In a transacted session (see next section), the acknowledgment mode is ignored and all acknowledgment processing is handled for you automatically by the Message Queue client runtime. In this case, the getAcknowledgeMode method returns the special constant Session.SESSION_TRANSACTED.
Transactions allow you to group together an entire series of incoming and outgoing messages and treat them as an atomic unit. The message broker tracks the state of the transaction’s individual messages, but does not complete their delivery until you commit the transaction. In the event of failure, you can roll back the transaction, canceling all of its messages and restarting the entire series from the beginning.
Transactions always take place within the context of a single session. To use them, you must create a transacted session by passing true as the first argument to a connection’s createSession method:
Session mySession = myConnection.createSession(true, Session.SESSION_TRANSACTED);
The session’s getTransacted method tests whether it is a transacted session:
if ( mySession.getTransacted() ) { /* Code here to handle transacted session */ } else { /* Code here to handle non-transacted session */ }
A transacted session always has exactly one open transaction, encompassing all messages sent or received since the session was created or the previous transaction was completed. Committing or rolling back a transaction ends that transaction and automatically begins another.
Because the scope of a transaction is limited to a single session, it is not possible to combine the production and consumption of a message into a single end-to-end transaction. That is, the delivery of a message from a message producer to a destination on the broker cannot be placed in the same transaction with its subsequent delivery from the destination to a consumer.
When all messages in a transaction have been successfully delivered, you call the session’s commit method to commit the transaction:
mySession.commit();
All of the session’s incoming messages are acknowledged and all of its outgoing messages are sent. The transaction is then considered complete and a new one is started.
When a send or receive operation fails, an exception is thrown. While it is possible to handle the exception by simply ignoring it or by retrying the operation, it is recommended that you roll back the transaction, using the session’s rollback method:
mySession.rollback();
All of the session’s incoming messages are recovered and redelivered, and its outgoing messages are destroyed and must be re-sent.