Programming with IBM MQ classes for JMS with an OSGi JVM server
To use JMS in your CICS® Java application to exchange messages with IBM® MQ, you use a JMS connection factory.
for a tutorial that shows how to develop this type of application, see CICS Developer Center: Using MQ JMS in a CICS OSGi JVM server.
JMS programming considerations (OSGi JVM server)
- Use of any of the XA connection factories, for example com.ibm.mq.jms.MQXAConnectionFactory, is not supported.
- Messages sent and received by the IBM® MQ classes for JMS in a JVM server environment are always associated with the CICS® unit of work (UOW) that is active on the current thread. That UOW can only be completed by calling the commit or rollback methods on the com.ibm.cics.server.Task object, or by the CICS task ending normally in which case the UOW is implicitly committed. (There is one exception to this, described in the next item in this list.) The values of the transacted and acknowledgeMode arguments are ignored when calling any of the Connection.createSession, or
ConnectionFactory.createContext methods. Additionally, the following methods are
not supported and calling them results in an IllegalStateException in the session
case:
- javax.jms.Session.commit()
- javax.jms.Session.recover()
- javax.jms.Session.rollback()
- javax.jms.JMSContext.commit()
- javax.jms.JMSContext.recover()
- javax.jms.JMSContext.rollback()
- The exception to the transactionality described above is this: if a session or JMS context is
created using one of the following mechanisms:
- Connection.createSession(false, Session.AUTO_ACKNOWLEDGE)
- Connection.createSession(Session.AUTO_ACKNOWLEDGE)
- ConnectionFactory.createContext(JMSContext.AUTO_ACKNOWLEDGE)
- Any messages that are sent are transferred outside of the CICS UOW. That is, they are available on the target destination immediately, or when the provided delivery delay interval has completed.
- Any non-persistent messages are received outside of the CICS UOW, unless the syncPointAllGets property is specified on the connection factory that created the session or JMS context.
- Persistent messages are always received inside the CICS UOW.
- JMS provides support for a number of different listener interfaces such as javax.jms.MessageListener, javax.jms.ExceptionListener and, if using JMS 2, the javax.jms.CompletionListener. All of these interfaces result in MQ JMS using multiple threads which is not supported in a CICS environment. Attempting to register one of these listeners results in either a JMSException or a JMSRuntimeException.
- MQ JMS builds on the native support for IBM MQ in CICS so it makes use of the existing IBM MQ security support which is described in Security considerations for using IBM MQ with CICS . As a result, any attempt to create either a connection or JMS context object while specifying a user id or password results in either a JMSException or JMSRuntimeException.
- A CICS MQCONN resource must be defined. The name of the queue manager, or queue sharing group, to which MQ JMS connects is taken from this MQCONN definition. Attempting to programmatically specify a queue manager, or queue sharing group has no effect.
- The following approaches can be used to create and configure the IBM MQ implementations of connection
factories and destinations:
- Using JNDI to retrieve administered objects
- Using the IBM JMS extensions
- Using the IBM MQ JMS extensions
Most users of JMS use a JNDI repository to locate a pre-configured set of connection factories and destinations. CICS does not provide a JNDI implementation, and the use of LDAP is not possible in an OSGi environment.
For details of the available options, and an example of how to register an initial context factory and the IBM MQ object factories with OSGi using the start method of a bundle adapter, see Creating and configuring connection factories and destinations.
The connection between CICS and a IBM MQ queue manager is policed using the user ID of the CICS address space. Resource access to a queue is authorized by the transaction user ID. Specifying a user ID and password with a connection factory is therefore not supported.
- Any applications that make use of MQ JMS in CICS should make sure that all JMS resources are recreated from an MQConnectionFactory each time the application is run. I.e. application code should not store instances of sessions, message consumers, or any other MQ JMS objects in static variables so that they can be shared between runs of the application. This restriction exists because the CICS-MQ adapter tidies up any resources such as queue input handles when r the transaction that created them completes. Trying to use one of these resources in another run of the same, or any other, transaction results in JMS exceptions.
- From a JMS specification perspective, the IBM MQ classes for JMS treat a JVM server as a Java™ EE compliant application server, that always has a JTA transaction in progress. For example, you can never call javax.jms.Session.commit() in CICS, because the JMS specification states that you cannot call it in a JEE EJB, or Web container, while a JTA transaction is in progress. This results in restrictions to the JMS API in CICS.
- javax.jms.Connection.createConnectionConsumer(javax.jms.Destination, String, javax.jms.ServerSessionPool, int) always throws a JMSException
- javax.jms.Connection.createDurableConnectionConsumer(javax.jms.Topic, String, String, javax.jms.ServerSessionPool, int) always throws a JMSException.
- All three variants of javax.jms.Connection.createSession always throw a JMSException if the connection already has an existing session active.
- javax.jms.Connection.createSharedConnectionConsumer(javax.jms.Topic, String, String, javax.jms.ServerSessionPool, int) always throws a JMSException.
- javax.jms.Connection.createSharedDurableConnectionConsumer(javax.jms.Topic, String, String, javax.jms.ServerSessionPool, int) always throws a JMSException.
- javax.jms.Connection.setClientID() always throws a JMSException.
- javax.jms.Connection.setExceptionListener(javax.jms.ExceptionListener) always throws a JMSException.
- javax.jms.Connection.stop() always throws a JMSException.
- javax.jms.MessageConsumer.setMessageListener(javax.jms.MessageListener) always throws a JMSException.
- javax.jms.MessageConsumer.getMessageListener() always throws a JMSException.
- javax.jms.MessageProducer.send(javax.jms.Destination, javax.jms.Message,javax.jms.CompletionListener) always throws a JMSException.
- javax.jms.MessageProducer.send(javax.jms.Destination, javax.jms.Message, int, int, long, javax.jms.CompletionListener) always throws a JMSException.
- javax.jms.MessageProducer.send(javax.jms.Message, int, int, long, javax.jms.CompletionListener) always throws a JMSException.
- javax.jms.MessageProducer.send(javax.jms.Message,javax.jms.CompletionListener) always throws a JMSException.
- javax.jms.Session.run() always throws a JMSRuntimeException.
- javax.jms.Session.setMessageListener(javax.jms.MessageListener) always throws a JMSException.
- javax.jms.Session.getMessageListener() always throws a JMSException.
-
- javax.jms.JMSContext.createContext(int) always throws a JMSRuntimeException.
- javax.jms.JMSContext.setClientID(String) always throws a JMSRuntimeException.
- javax.jms.JMSContext.setExceptionListener(javax.jms.ExceptionListener) always throws a JMSRuntimeException.
- javax.jms.JMSContext.stop() always throws a JMSRuntimeException.
- javax.jms.JMSProducer.setAsync(javax.jms.CompletionListener) always throws a JMSRuntimeException.
- javax.jms.JMSConsumer.getMessageListener() always throws a JMSRuntimeException.
- javax.jms.JMSConsumer.setMessageListener(javax.jms.MessageListener) always throws a JMSRuntimeException.