The generic JMSJCA adapter is packaged and specialized for the following connectors:
In either case, to use of outbound connections, a mapping must be made in the deployment descriptor of the EJB or servlet that ties the JNDI names of the connection factories to names in the ENC (Environment Naming Context). The application code can then lookup the JMS connection factory and create outbound connections.
Example:
TopicConnection topicConn = null; try { TopicConnectionFactory factory = (TopicConnectionFactory) context.lookup("java:comp/env/jms/TCF"); topicConn = factory.createTopicConnection(); TopicSession topicSession = topicConn.createTopicSession(false, Session.AUTO_ACKNOWLEDGE); topic = (Topic) context.lookup("jms/topic1"); TopicPublisher publisher = topicSession.createPublisher(topic); TextMessage txtMsg = topicSession.createTextMessage("Hello world"); publisher.publish(txtMsg); } finally { if (topicConn != null) { topicConn.close(); } }
Note that because a JMS connection is a transactional resource:
Parameter name | Meaning |
---|---|
ConnectionURL | default value for connectionURL |
UserName | default username |
Password | default password |
MBeanObjectName | MBeanObjectName: name of the MBean that the adapter should create. The MBean will provide access to statistical info and a relay MBean for management of destinations in the JMS server. |
MBeanServerDomain | MBean server domain: JMX name for the MBeanServer to be used to register the RA MBean in. Not used if no MBean name is specified. When left blank or unspecified, the default MBeanServer will be used. |
Options | See below |
Parameter name | Meaning |
---|---|
ConnectionURL | connectionURL. Takes precedence over the value specified in the generic section of ra.xml. |
UserName | username. Takes precedence over the value specified in the generic section of ra.xml. |
Password | password. Takes precedence over the value specified in the generic section of ra.xml. |
ClientId | the client id, used in Connection.setClientID() |
ProducerPooling | boolean that indicates if producers are pooled by the connector. For some JMS providers JMS producers (topic-publishers and queue-senders) are expensive to create because it may involve creating a socket connection. When ProducerPooling is turned on, the socket resources of a producer will not be closed when the application closes the producer. Instead, the producer will be returned to a pool that is tied to the session. The next time the application uses a producer on the session, it will be reused from the pool. |
IdleTimeout | this parameter is used for connection validation. If a connection is not used successfully for a period longer than the IdleTimeout period, the connection is marked as invalid. "Successfully" is defined as a msg was sent or received without an exception from the underlying JMS implementation. |
Options | switches and options, see below |
Parameter name | required? | Meaning |
---|---|---|
ConnectionURL | not required | connectionURL. Takes precedence over the value specified in the generic section of ra.xml. |
UserName | not required | username. Takes precedence over the value specified in the generic section of ra.xml. |
Password | not required | password. Takes precedence over the value specified in the generic section of ra.xml. |
ClientId | not required | the client id passed to setClientID)(). Note that many JMS providers require a client id to be set in order to use durable topics. If this value is omitted or left blank, a client ID will be automatically generated based on the durable subscription name. |
destination | mandatory | name of the queue or topic that messages should be read from. To indicate that this is the name of an object that should be looked up in JNDI, prefix the name with lookup://. If this prefix is not found, the queue or topic will be created using the approach most suitable for the JMS server, typically by calling createQueue(name) or createTopic(name) See release notes of individual adapters for more information. |
destinationType | mandatory | should be either javax.jms.Queue or javax.jms.Topic |
subscriptionDurability | depends | applies only to topics. Should be set to either Durable or NonDurable |
subscriptionName | depends | in case the subscriptionDurability is set to Durable, this parameter must be specified and must indicate the name of the durable subscriber. |
ConcurrencyMode | not required | either serial, cc, or sync. See below. |
endpointPoolMaxSize | not required | In the case of concurrent processing, this value (integer) specifies the number of MDBs that can be used to process messages concurrently. This should match the value specied in the application server specific deployment descriptor that specifies the number of MDBs the bean pool. |
MBeanName | not required | MBeanObjectName: name of the MBean that the adapter should create. The MBean will provide access to statistical info and a relay MBean for management of destinations in the JMS server. |
selector | not required | specifies a JMS message selector (optional) |
Options | not required | switches and options, see below |
RedeliveryHandling | not required | see below. |
BatchSize | not required | see below. (Set to a number greater than 1 to turn on batching) |
HoldUntilAck | not required | see below. (Set to 1 to turn on this special mode) |
ContextName | not required | Before the inbound connector calls the onMessage() method on an MDB, it will first log a message to the Logger with name com.stc.EnterContext. This entry in the activation spec defines the contents of the message. After the onMessage() method has returned, the same message (i.e. the value of ContextName), will be logged to the com.stc.ExitContext logger. The parameter ContextName may be left blank or may be omitted; in that case the value of ContextName is not logged to com.stc.EnterContext and com.stc.ExitContext. The Java CAPS application server interprets the com.stc.EnterContext and com.stc.ExitContext specially, and will actually not log the message (i.e. the value of ContextName), but will prepend the value of ContextName to all log entries that are logged by the application in the MBD. |
protocol://server:port?key1=value1&key2=value2The query string is optional and contains both properties for the JMS server as well as for the connector. See also the section on Options below.
The ConnectionURL can be specified at the connector level (i.e. top of ra.xml), but also for each activation spec. This allows multiple MDBs to use the same connector, but connect to different JMS servers. The ConnectionURL can also be specified for each connection factory. This is useful for global connectors: to connect to multiple JMS servers, one can specify a different ConnectionURL for each connection factory. For embedded connectors this is slightly different: the connection factory is configured in the ra.xml, and the number of connection factories in ra.xml is limited to exactly one per connectionfactory-interface class. This class must be one of the three JMS factory classes. Hence, the number of connection factories is limited to three per connector. Hence, if no global connectors are used, a separate embedded connector has to be used for each distinct JMS server used in an EAR. An alternative construct to using one different embedded connector for each distinct JMS server is by using a special facility in JMSJCA in which the username is overloaded: see below "Overloaded username".
The precedence order for outbound connections is as follows: 1) createConnection(username, password), 2) at the connection factory level, and 3) at the connector level.
The precedence order for MDBs is as follows: 1) at the activation spec level, and 2) at the connector level.
A special feature of JMSJCA is that the ConnectionURL can also be specified in the application code when creating a connection through ConnectionFactory.createConnection(username, password) or one of the equivalents for queue and topic. If the username can be recognized as a ConnectionURL, e.g. if the username starts with stcms:// or stcmss:// for STCMS, the username is interpreted as a ConnectionURL rather than a username. The username can still be specified: the query parameters username and password will be read from the ConnectionURL. The password can also be specified in the password parameter to createConnection(username, password).
Example:
ConnectionFactory.createConnection("stcms://blue:18008?user=X", "Y") will create a connection to the STCMS server on BLUE at port 18008 using the username "X" and the password "Y". This is equivalent to ConnectionFactory.createConnection("stcms://blue:18008?user=X&password=Y", null). If the username is not specified, e.g. as in ConnectionFactory.createConnection("stcms://blue:18008, null), the username is obtained through the normal presedence rules, i.e. from the connection factory level specification or the connector.
Connections to JMS servers specified in the username parameter are pooled in the same pool as the "normal" connections in the connector pool.
Parameter value | Meaning |
---|---|
serial | Uses one asynchronous listener; the JMS thread is used to invoke the onMessage() method. |
cc | Provides for concurrent processing by using connection consumer mode. Messages are dispatched to the WorkManager. Messages may be processed out of order. |
sync | Provides for multiple synchronous receivers that call receive(TIMEOUT) in a loop. This mode is mandatory for some implementations that do not properly implement the connection consumer mode (CC), or do not allow the XA start() method to be called from within the onMessage() method. A consequence is that for Topics, there will be no concurrent processing in this mode. |
The default value for the ConcurrencyMode-parameter is serial.
The destination in an activation spec can also be specified as an administrative object. To indicate that the destination parameter in an activation spec denotes an object that should be looked up, prefix the name with lookup://.
Destination q = (Destination) new InitialContext().lookup("orders"); session.createProducer(q).send(session.createTextMessage("hello 1")); session.createProducer(q).send(session.createTextMessage("hello 2"));In the first send() method in this code fragment, the destination is looked up in the JNDI provider at server X using the lookup-name queues/q1234. Because destinations are cached in the adapter, in the second send() method, the cached destination object is used.
In this example, the activation spec has the destination attribute has the value lookup://orders, the destination object is looked up in a similar fashion in the JNDI provider at server X using the lookup-name queues/q1234. If on the other hand the destination attribute has the value orders, the destination object is obtained using createQueue("orders") or createTopic("orders").
Parameter name | in/out | Meaning |
---|---|---|
JMSJCA.NoXA | in/out | if set to true, this indicates that the resource adapter should not use XA. This can be used in case the JMS provider is not configured to use XA. This feature can also be used when the resource adapter is used outside of the application server. See the note on transaction control below. |
JMSJCA.LocatorClass | in/out | Specifies the Java class name of the class that will be used to access the transaction manager in the application server. The transaction manager is used in case of temporary destinations (in order to delete them when the connection closes) and when messages are moved to the dead letter queue. The default value will most likely suffice. |
JMSJCA.redeliveryredirect | in | If set to true, in the case of messages being sent to dead letter queue, messages will be redirected rather than copied. |
JMSJCA.redeliveryhandling | in | specifies the behavior of the dead letter queue. See below. |
JMSJCA.concurrencymode | in | allows the concurrency mode to be overridden. Values are sync, CC, or serial. This is useful in particular cases (e.g. FIFO modes in STCMS) where the default concurrency mode does not suffice. |
JMSJCA.ACC | out | if set to true this indicates that the resouce adapter should behave as if it is running inside a client container. This means that the resource adapter will not be under the control of a transaction manager. The default is false. This property can also be set as a system property. |
JMSJCA.IgnoreTx | out | if set to true, the resource adapter will ignore the isTransacted parameter to the method createSession(isTransacted, ackmode) and equivalent functions and always change this parameter to isTransacted=true and the ackmode parameter is set to TRANSACTED. The default value is the opposite of JMSJCA.ACC. This property can also be set as a system property. |
JMSJCA.BypassRA | out | if set to true, this indicates that factories should not delegate to the resource adapter, but will instead delegate to the "native" JMS connection factory directly. The default is false. This property can also be set as a system property. |
JMSJCA.Strict | out | if set to true, the adapter will behave as close to the J2EE spec as possible. This property can also be set as a system property. See notes of specific adapters. |
JMSJCA.sep | in/out | To allow multiple properties to be specified in one single line (useful for some administrative consoles that limit the user input to one line), this options allows for a character to be specified that will be used to delimit multiple options. Example: "JMSJCA.sep=,JMSJCA.NoXA=true,JMSJCA.ACC=true" specifies two options: JMSJCA.NoXA = true and JMSJCA.ACC = true. Note that the separator can be escaped with a backslash in case it needs to be used as part of an option-value. Example: "JMSJCA.sep=*JMSJCA.NoXA=true*queuepattern=Q.\*" yields two values: JMSJCA.NoXA=true and queuepattern=Q.* |
Options can be specified in:
Method | Meaning |
---|---|
getJMSServerMBean() | returns the ObjectName of the MBean that provides management capabilities of the contents of destinations in the JMS server. |
getJMSServerType() | returns the type of the JMS server, e.g. STCMS. |
Also, for each activation (i.e. MDB deployment), the JMSJCA connector can register an MBean. This MBean can be used to start/stop delivery of messages to the MDBs and can be used to extract performance data out of the connector. The name is specified in the MBeanName parameter of the activation spec.
Attribute | Meaning |
---|---|
ActivationSpec | A dump of the values in the activation spec |
NActiveEndpoints | Number of active MDBs, i.e. number of threads that are currently in onMessage() |
NConfiguredEndpoints | Number of MDBs specified in the activation spec |
NHighestActiveEndpoints | Highest number of active MDBs reached sofar |
NMessages | Total number of messages delivered, i.e. the number of times onMessage() was invoked |
NTotalEndpoints | Current number of MDBs in the pool |
Stats | snapshot of performance numbers |
Method | Meaning |
---|---|
getJMSServerMBean() | returns the ObjectName of the MBean that provides management capabilities of the contents of destinations in the JMS server. |
getJMSServerType() | returns the type of the JMS server, e.g. STCMS. |
getStatus | indicates if the connector is "Up" (i.e. connected to the JMS server, and potentially delivering messages to MDBs), "Down" (i.e. no connection exists to the JMS server), "Connecting" (i.e. the adapter is trying to establish a connection to the JMS server; the status of a connector immediately after activation is always "Connecting"), or "Disconnecting" (i.e. the connector is disconnecting from the JMS server and may be waiting for all threads to return from their onMessage() methods. |
getProperties | returns a String specifying configuration parameters. |
Connection c = fact.createConnection(); Session s = c.createSession(false, Session.AUTO_ACKNOWLEDGE);
Transacted mode: This is the default mode: a call to Connection.createSession(isTransacted, ackmode is defaulted to c.createSession(true, Session.SESSION_TRANSACTED). The XA emulation will propagate only the second phase of the transaction commit protocol to the session, i.e. commit and rollback are propagated to the transacted session; the first phase is ignored. This implies that transactional integrity is not guaranteed: if Session.commit() or Session.rollback() fail, the transaction may be left in an inconsistent state. Note that the application code can call Session.commit() or Session.rollback() directly; in that case the transaction managed by the container is bypassed completely, and the transaction may be inconsistent.
Non transacted mode: To use this mode, set JMSJCA.IgnoreTx=false(default is true), and call Connection.createSession(false, Session.AUTO_ACKNOWLEDGE) (the values CLIENT_ACKNOWLEDGE or DUPS_OK_ACKNOWLEDGE may also be used). The XA emulation will not propagate anything of the container managed transaction to the session. This means that the session is used completely outside of the transaction managed by the container. There is no transactional integrity.
The msgid cache is not persistent, nor is it shared between multiple activations. This means that if a message was seen 10 times with the redelivered flag set, and the project is undeployed, the redelivery count will be set to zero when the project is deployed again. Also, if there are multiple application servers reading from the same queue, a message may be redelivered 10 times to one application server, and 10 times to the other application server, and both activations will see a count of 10 instead of 20.
The msgid cache is limited to 5000 entries; when this limit is reached, the oldest msgids are flushed from the cache. "Oldest" means least recently seen.
format := entry[; entry]* entry := idx ":" action idx := number (denotes the n-th time a msg was seen) action := number (denotes delay in ms) | "delete" | "move"(args) move := "queue"|"topic" | "same" ":" destname destname := any string, may include "$" which will be replaced with the original destination name.Example:
5:1000; 10:5000; 50:move(queue:mydlq)This causes no delay up to the 5th delivery; a 1000 ms delay is invoked when the message is seen the 5th, 6th, 7th, 8th, and 9th time. A 5 second delay is invoked when the msg is invoked the 10th, 11th, ..., 49th time. When the msg is seen the 50th time the msg is moved to a queue with the name "mydlq".
If the messages were received from "Queue1" and if the string was specified as
5:1000; 10:5000; 50:move(queue:dlq$oops)the messages would be moved to the destination "dlqQueue1oops": the special character "$" denotes the original destination name. Instead of "queue" one can also specify "topic" or "same". The latter denotes a queue if the message was received from a queue, or can denote a topic if the message was received from a topic.
Another example:
5:1000; 10:5000This causes no delay up to the 5th delivery; a 1000 ms delay is invoked when the message is seen the 5th, 6th, 7th, 8th, and 9th time. A 5 second delay is invoked for each time the message is seen thereafter.
stcms://localhost:18007?JMSJCA.redeliveryhandling=5:1000; 10:5000
Moving messages is done by creating a new message of the same type unless the property JMSJCA.redeliveryRedirect is set to true in which case the messages are simply redirected. In the first case, the payload of the new message is set as follows:
3:25; 5:50; 10:100; 20:1000; 50:5000
The EndOfBatch message can be recognized using an Object message property with the name JMSJCA.EndOfBatch such that
message.getObjectProperty("JMSJCA.EndOfBatch")returns
Boolean.TRUE
Note that since all messages in a batch are delivered in one transaction, all messages in the batch are rolled back. Therefore, in typical applications, it would be preferable to move faulty messages to an error-queue rather than to throw an exception or mark the transaction for rollback. Note that the redelivery handling feature (see above) works the same on all messages and cannot make a distinction which message in a batch may be faulty.
Here is an example that illustrates its intended use:
// An imaginary way to post a request to a different thread private void postRequest(Message m, OnDoneHandler h) { // Do something } // An imaginary callback handler public interface OnDoneHandler { void onDone(boolean failed) throws Exception; }; // The onMessage method public void onMessage(final Message m) { postRequest(m, new onDoneHander() { public void onDone(boolean failed) { m.acknowledge(); } }); }
In this example the RA-thread will call onMessage(), and after it has returned from this method it will not commit/rollback the transaction nor will it return the session to the pool. Instead, these two activities are done when the other thread calls acknowledge().
message.setBooleanProperty("JMSJCA.setRollbackOnly", true); message.acknowledge();
public void onMessage(final Message message) { try { postRequest(message, new OnDoneHandler() { public void onDone(boolean failed) throws Exception { if (failed) { message.setBooleanProperty("JMSJCA.setRollbackOnly", true); } message.acknowledge(); } }); } catch (Exception e) { // Posting failed; rollback try { message.setBooleanProperty("JMSJCA.setRollbackOnly", true); message.acknowledge(); } catch (JMSException e1) { throw new RuntimeException(e1); } } }
Here is an example:
public void onMessage(final Message message) { try { if (message.getObjectProperty("JMSJCA.EndOfBatch") != null) { // End of batch message.acknowledge(); } else { // Message in middle of batch try { postRequest(message, new OnDoneHandler() { public void onDone(boolean failed) throws Exception { if (failed) { message.setBooleanProperty("JMSJCA.setRollbackOnly", true); } message.acknowledge(); } }); } catch (Exception e) { // Posting failed; rollback message.setBooleanProperty("JMSJCA.setRollbackOnly", true); message.acknowledge(); } } } catch (JMSException e) { throw new RuntimeException(e); } }