The sun-jms-adapter supports any JMS Provider of which the connection factories can be looked up in JNDI, but also provides specialized support for the following JMS Providers:
JMS Provider | ConnectionURL |
---|---|
STCMS | stcms://, stcmss:// |
OpenMQ / JMQ / Sun Java System Message Queue | mq://, mqtcp://, mqssl://, httpjms://, httpsjms:// |
JMS Grid | stream://, tcp://, ssl://, http:// |
WebSphere MQ/MQ Series | wmq:// |
WebLogic JMS | t3:// |
JBoss JMS | jboss:// |
STCMS 4.5.3 / SRE | stms453:// |
Generic JNDI | jndi:// |
See below for more information
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 | connection URL. Takes precedence over the value specified in the generic section of ra.xml. This can be of the form of lookup://name. See below. |
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 | (deprecated; use JMSJCA.producerpooling instead) A 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 | (deprecated; use JMSJCA.idletimeout instead) 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".
In the activation spec, the ConnectionURL can take the form of lookup://jndiname where jndiname should represent a JMSJCA connection pool bound in JNDI. The advantage of this construct is that all connectivity parameters no longer need to be present in the activation spec, but can be delegated to a globally shared connection pool. The connection pool is typically configured in the application server, i.e. outside of the application, i.e. outside of the EAR file.
During activation, JMSJCA checks the ConnectionURL; if it starts with lookup:// it will try to use the remainder of that string to lookup an object in the default JNDI provider. The returned object must a connection factory that was created with JMSJCA; the activation and the connection pool also must use the same classloader. The configuration of both the connection pool (MCF) and its resource adapter (RA) will be inspected. Next, the following properties will be changed in the activation spec:
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. Hence, createConnection(), createQueueConnection(), and createTopicConnection() can be used as follows:
createConnection("u", "p"); createConnection("protocol://host:port?option=value", null); createConnection("protocol://host:port?option=value&username=u&password=p", null); createConnection("protocol://host:port?option=value&username=u", "p");As shown, 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:
The following first two statements are equivalent and will all create a connection to the STCMS server on BLUE at port 18008 using the username "X" and the password "Y". In the third statement, the username is obtained through the normal presedence rules, i.e. from the connection factory level specification or the connector.
ConnectionFactory.createConnection("stcms://blue:18008?username=X", "Y") ConnectionFactory.createConnection("stcms://blue:18008?username=X&password=Y", null) ConnectionFactory.createConnection("stcms://blue:18008, null)
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://.
The destination obtained through Session.createQueueue() or Session.createTopic() also uses this approach: if the destination name supplied to these methods starts with lookup://, the destination is looked up in the container's JNDI instead of calling Session.createQueue() or Session.createTopic() on the underlying JMS provider. If the looked up destination is an administrative object, this destination is converted into a JMS provider specific destination using an approach specific for that provider.
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").
Destination q = session.createQueue("lookup://jms/destinations/orders");This will result in a lookup in the container's jndi of the object with the jndi-name jms/destinations/orders. The resulting object is an administrative object containing the name q1234. The adapter will call session.createQueue("q1234") on the STCMS JMS client, and return the resulting object.
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.* |
JMSJCA.nocfcache | out | Determines if connection factories are cached. Default: true, but may depend on particular connector (e.g. WL). Can be set to false for those cases where connection factories constitute live connections. In case of connection failures, these connection factories should not be cached but recreated. |
JMSJCA.messagewrapping | in | Always create a message wrapper around a message when it gets delivered to the MDB which allows the application code to associate state with the message in case the message gets redelivered. See Message Wrapping. Possible values: 0=auto, 1=always. Default: 1. |
JMSJCA.selector | in | Specifies a default selector for all activations. See Selectors. Default: "" |
JMSJCA.ForceBMT | in | When set to true, it will ignore the application server's directive to enlist receiving the message part of the transaction that spans the Message Driven Bean, and will ensure that receiving the message happens in a separate transaction. In other words: it ignores the CMT directive and will behave as if the application server had indicated BMT. Default: false. |
JMSJCA.idletimeout | out | 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. |
ProducerPooling | out | A 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. Default: false, but for some JMS providers this is turned on by default (e.g. STCMS453). |
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:
Property | Meaning |
---|---|
JMS_Sun_JMSJCA_RedeliveryCount | number of times the message was seen with the redelivered flag set by JMSJCA. Will accurately reflect the total number of redelivery attempts only if there's one instance of the inbound adapter, and the inbound adapter was not redeployed. |
JMS_Sun_JMSJCA_OriginalDestinationName | name of the destination as specified in the activation spec |
JMS_Sun_JMSJCA_OriginalDestinationType | either "javax.jms.Queue" or "javax.jms.Topic" |
JMS_Sun_JMSJCA_SubscriberName | as specified in the activation spec |
JMS_Sun_JMSJCA_ContextName | as specified in the activation spec |
JMS_Sun_JMSJCA_OriginalJMSMessageID | original msgid as obtained through getJMSMessageID() of the original message |
JMS_Sun_JMSJCA_OriginalJMSCorrelationID | original JMS Correlation ID as obtained through getJMSCorrelationID() of the original message |
JMS_Sun_JMSJCA_OriginalClientID | The ClientID as specified in the activation spec |
JMS_Sun_JMSJCA_ExceptionClass | The classname of the exception that was caught by the RA. This is typically a wrapper exception created by the container. |
JMS_Sun_JMSJCA_ExceptionMessage | The exception message of the exception that was caught by the RA. |
JMS_Sun_JMSJCA_ExceptionStackTrace | The exception stacktrace of the exception that was caught by the RA. |
JMS_Sun_JMSJCA_UserRollbackData.* | Values specified on the message while being processed in the MDB by the application code. See Message Wrapper. |
3:25; 5:50; 10:100; 20:1000; 50:5000
Arbitrary state can be associated with a message through the JMS_Sun_JMSJCA_UserRollbackData.* properties. For example, when an MDB calls message.setStringProperty("JMS_Sun_JMSJCA_UserRollbackData.failuremode", "permanent") and rolls back the transaction, the next time that the message gets delivered, a call to message.getStringProperty("JMS_Sun_JMSJCA_UserRollbackData.failuremode") will yield "permanent".
Note that this kind of state is not persisted and that its scope is limited to only the MDBs of the activation in which the state was set.
Through functionality exposed in message wrapper, the MDB can also query the number of times the message was seen before by the activation that the MDB is part of. This is done through the JMS_Sun_JMSJCA_RedeliveryCount object property which returnes a java.lang.Integer.
An MDB can find out what the redelivery handling is for the activation that it is part of: getStringProperty("JMS_Sun_JMSJCA_RedeliveryHandling") returns the redelivery string that applies to that message. The MDB can even change the redelivery handling for each particular message using setStringProperty("JMS_Sun_JMSJCA_RedeliveryHandling", h) where h is the redelivery handling string. This string should be of the same format as redelivery handling strings specified in the activation spec.
An MDB can even stop message delivery altogether by calling setStringProperty("JMS_Sun_JMSJCA_StopMessageDelivery", reason) where reason is a string that will be printed in the log as the reason why message delivery was stopped. Of course message delivery can only be resumed by an external action such as the call on the activation MBean, disabling/enabling or undeploying/redeploying the application.
The message wrapper implements one of the six javax.jms message types. The interface type will be the same as the wrapped message implements. Messages cannot be wrapped if a JMS provider delivers messages that implement more than one of the derived interfaces (TextMessage, BytesMessage, MapMessage, ObjectMessage, StreamMessage). If the JMS provider delivers a proprietary message that implements only javax.jms.Message, the wrapper will only expose the javax.jms.Message interface.
The message wrapper exposes new functionality through the methods that are declared in the javax.jms.Message type, especially the properties methods. A summary of all functionality is listed in the following table. Details on each item can be found in the corresponding sections.
Parameter | Type | method | See section on | Meaning |
---|---|---|---|---|
- | - | acknowledge() | HUA mode | To indicate that processing of the message has finished |
JMSJCA.setRollbackOnly | java.lang.Boolean | setObjectProperty() | HUA mode | To rollback the transaction |
JMSJCA.batchIndex | java.lang.Integer | getObjectProperty() | Batch | Indicates the number of messages that preceded this message |
JMSJCA.batchSize | java.lang.Integer | getObjectProperty() | Batch | Indicates the size of the batch, the same value as in the activation spec |
JMS_Sun_JMSJCA_UserRollbackData.* | java.lang.String | setStringProperty(), getStringProperty() | Redelivery | Gives access to arbitrary data that an application can associate with a message. |
JMS_Sun_JMSJCA_RedeliveryCount | java.lang.Integer | getObjectProperty() | Redelivery | The number of times the message was seen before. A value of zero indicates that the message wasn't seen before. |
JMS_Sun_JMSJCA_RedeliveryHandling | java.lang.String | getStringProperty() setStringProperty() | Redelivery | The current redelivery handling setting for this message; sets the redelivery handling for this message |
JMS_Sun_JMSJCA_StopMessageDelivery | java.lang.String | setStringProperty() | Redelivery | Stops message delivery. The second parameter passed to setStringProperty will be printed in the log as the reason for stopping message delivery. Once message delivery is stopped, it can only be resumed by another invocation on the MBean. |
JMS_Sun_JMSJCA_MBeanServer | java.lang.Object | getObjectProperty() | - | Returns the MBeanServer used to register the Activation MBean |
JMS_Sun_JMSJCA_MBeanName | java.lang.String | getStringProperty() | - | Returns the MBean name used to register the Activation MBean |
Note that the extra properties on the message wrapper do not follow the JMS specification:
Substitution parameters are of the form ${Parameter} . Substitution can be disabled by escaping the $-sign with an extra $-sign. For instance, while s = '${subscribername}' may resolve to s = 'x47' if the subscriber name in the activation spec was x47. On the other hand, the string s = '$${subscribername}' will always resolve to s = '${subscribername}' .
Selectors can also refer to parameters in the activation spec: the ${subscribername} refers to the the subscriptionName parameter in the activation spec.
Here is a list of all sustitution parameters:
Parameter | Usage | Description |
---|---|---|
${subscribername} | Anywhere | Will be replaced with the subscriptionName parameter in the activation spec |
${selector} | Override | Will be replaced with the selector parameter in the activation spec |
${andselector} | Override | Evaluates to and (${selector}) if the selector in the activation spec is non-empty string, or evaluates to an empty string "" if the selector spec is an empty string |
${selectorand} | Override | Evaluates to (${selector}) and if the selector in the activation spec is a non-empty string, or evaluates to an empty string "" if the selector in the activation spec is an empty string. |
Parameters that are not in this list will be resolved as System parameters using System.getProperty().
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); } }
There are three approaches to this problem:
For those JMS servers for which the first approach does not work, jmsjca provides the third approach.
jmsjca://distribution=1&subscribername=s[&queue=q][&mbeanname=m][&batchsize=b]
Parameter | Required | Meaning | Default |
---|---|---|---|
distribution | yes | turns on distributed durable subscribers. Valid values: 0=off, 1=distributed durable subscriber | 0 |
subscribername | yes | the name of the durable subscriber | |
queue | no | name of the queue to send the messages to | LOADBALQ_topicname_subscribername |
mbeanname | no | name of the MBean associated with the topic-to-queue delivery object | specified MBean name + "-LOADBALQ" |
batchsize | no | number of messages read in one batch from the topic and written to the queue | 10 |
Genericjmsra's queues and topics contain the name of a destination object bound in JNDI. JMSJCA will take this name, prefix it with jndi:// and create its own administrative object for it. This approach will work if the JNDI adapter is used, and if this adapter is pointing to the the same JNDI store as Genenericjmsra.
stcms://server:portwhen using SSL, specify
stcmss://server:port
The ConnectionURL can optionally contain a query string. This can be used to specify parameters for the STCMS connection factory or the JMSJCA adapter. For example, to turn make the client validate the SSL certificate that it receives from the server, one can specify server authentication as follows: stcmss://?com.stc.jms.ssl.authenticationmode=Authenticate.
stcms://?JMSJCA.concurrencymode=sync
Another example:
stcms://server:18007?JMSJCA.concurrencymode=sync
Run in cc-mode will cause deadlock in the case of any MDB rolling back. This can be fixed either in the client side or the server side. A better solution will be addessed later.
Workaround #1:use sync mode instead of CC mode. This implies that there is no concurrent processing for topics. This mode can be specified in the deployment descriptor or in the URL. See the JMSJCA release notes.
Workaround #2: restart the SJSMQ broker if this situation occurs
Workaround: upgrade to 3.7UR1 or higher.
Name | Meaning |
---|---|
JMSJCA.QueueCF | JNDI name of queue connection factory (javax.jms.QueueConnectionFactory) |
JMSJCA.TopicCF | JNDI name of topic connection factory (javax.jms.TopicConnectionFactory) |
JMSJCA.UnifiedCF | JNDI name of connection factory (javax.jms.ConnectionFactory) |
If the property java.naming.factory.initial is specified, the InitialContext is created using the complete set of properties specified in the URL and or the options field. If the property java.naming.factory.initial is not specified, the InitialContext is created using its default constructor.
java.naming.factory.initial=com.stc.jms.jndispi.InitialContextFactory java.naming.provider.url=stcms://localhost:18007 java.naming.security.principal=Administrator java.naming.security.credentials=STC JMSJCA.TopicCF=connectionfactories/xatopicconnectionfactory JMSJCA.QueueCF=connectionfactories/xaqueueconnectionfactory JMSJCA.UnifiedCF=connectionfactories/xaconnectionfactory com.stc.jms.autocommitxa=true com.stc.jms.jndispi.disconnected=true
These properties can be specified in the Options field or be encoded in the ConnectionURL. Note that if the Options field needs to be limited to one single line, e.g. because of limitation in administrative consoles, the JMSJCA.sep option can be used. Example:
JMSJCA.sep=,java.naming.factory.initial=com.stc.jms.jndispi.InitialContextFactory,java.naming.provider.url=stcms://localhost:18007,java.naming.security. principal=Administrator,java.naming.security.credentials=STC,JMSJCA.TopicCF=connectionfactories/xatopicconnectionfactory,JMSJCA.QueueCF= connectionfactories/xaqueueconnectionfactory,JMSJCA.UnifiedCF=connectionfactories/xaconnectionfactory,com.stc.jms.autocommitxa=true,com.stc.jms. jndispi.disconnected=true
The same thing will happen if the destination is specified as lookup://q and q is an administrative object with name jndi://queues/Queue1.