22.10. Configure a Generic JMS Resource Adapter for Use with a Third-party JMS Provider
JBoss EAP 6 can be configured to work with third-party JMS providers, however not all JMS providers produce a JMS JCA resource adapter for integration with Java application platforms. This procedure covers the steps required to configure the generic JMS resource adapter included in JBoss EAP 6 to connect to a JMS provider. In this procedure, Tibco EMS 6.3 is used as an example JMS provider, however other JMS providers may need a different configuration.
Important
Prerequisites
- JMS provider server is already configured and ready for use. Any binaries required for the provider's JMS implementation will be needed.
- You will also need to know the values of the following JMS provider properties to be able to lookup its JMS resources (connection factories, queues and topics).
- java.naming.factory.initial
- java.naming.provider.url
- java.naming.factory.url.pkgs
In the example XML used in this procedure, these parameters are written asPROVIDER_FACTORY_INITIAL
,PROVIDER_URL
, andPROVIDER_CONNECTION_FACTORY
respectively. Replace these placeholders with the JMS provider values for your environment.
Procedure 22.10. Configure a Generic JMS Resource Adapter for Use with a Third-party JMS Provider
Create a JBoss Module for the JMS provider
Create a JBoss module that contains all the libraries required to connect and communicate with the JMS provider. This module will be namedorg.jboss.genericjms.provider
.- Create the following directory structure:
EAP_HOME/modules/system/layers/base/org/jboss/genericjms/provider/main
- Copy the binaries required for the provider's JMS implementation to
EAP_HOME/modules/system/layers/base/org/jboss/genericjms/provider/main
.Note
For Tibco EMS, the binaries required aretibjms.jar
andtibcrypt.jar
from the Tibco installation'slib
directory. - Create a
module.xml
file inEAP_HOME/modules/system/layers/base/org/jboss/genericjms/provider/main
as below, listing the JAR files from the previous steps as resources:<module xmlns="urn:jboss:module:1.1" name="org.jboss.genericjms.provider"> <resources> <!-- all jars required by the JMS provider, in this case Tibco --> <resource-root path="tibjms.jar"/> <resource-root path="tibcrypt.jar"/> </resources> <dependencies> <module name="javax.api"/> <module name="javax.jms.api"/> </dependencies> </module>
Configure a JNDI external context to the JMS provider
The JMS resources (connection factories and destinations) are looked up in the JMS provider. We will add an external context in the JBoss EAP 6 instance so that any local lookup for this resource will automatically look up the resource on the remote JMS provider.Note
In this procedure,EAP_HOME/standalone/configuration/standalone-full.xml
is used as the JBoss EAP 6 configuration file.InEAP_HOME/standalone/configuration/standalone-full.xml
, under<subsystem xmlns="urn:jboss:domain:naming:1.4">
, add:<bindings> <external-context name="java:global/remoteJMS/" module="org.jboss.genericjms.provider" class="javax.naming.InitialContext"> <environment> <property name="java.naming.factory.initial" value="${PROVIDER_FACTORY_INITIAL}"/> <property name="java.naming.provider.url" value="${PROVIDER_URL}"/> <property name="java.naming.factory.url.pkgs" value="${PROVIDER_URL_PKGS}"/> </environment> </external-context> </bindings>
These three properties' values must be replaced by the correct value to connect to the remote JMS provider. Take care when replacing the placeholder text to keep the${}
intact.Enable Lookup by String
There are some JMS provider (such as Tibco EMS) that do not support the JNDIlookup(Name)
method. In these cases, add theorg.jboss.as.naming.lookup.by.string
property with a valuetrue
to workaround this issue.Example 22.2. Enable Lookup by String with Tibco EMS
A complete definition for anexternal-context
to Tibco EMS would be as follows.<bindings> <external-context name="java:global/remoteJMS/" module="org.jboss.genericjms.provider" class="javax.naming.InitialContext"> <environment> <property name="java.naming.factory.initial" value="com.tibco.tibjms.naming.TibjmsInitialContextFactory"/> <property name="java.naming.provider.url" value="TIBCO_EMS_SERVER_HOST_NAME:PORT"/> <property name="java.naming.factory.url.pkgs" value="com.tibco.tibjms.naming"/> <property name="org.jboss.as.naming.lookup.by.string" value="true"/> </environment> </external-context> </bindings>
With this external context, any JNDI lookup to a resource starting withjava:global/remoteJMS/
will be done on the remote JMS provider (after removing this prefix). As an example, if a Message-Driven Bean perform a JNDI lookup forjava:global/remoteJMS/Queue1
, the external context will connect to the remote JMS provider and perform a lookup for theQueue1
resource.Configure the Generic JMS Resource Adapter
InEAP_HOME/standalone/configuration/standalone-full.xml
, add the generic resource adapter configuration to<subsystem xmlns="urn:jboss:domain:resource-adapters:1.1">
.Example 22.3. Tibco EMS Resource Adapter Configuration
A complete resource adapter definition for Tibco EMS would be as follows.<resource-adapter id="org.jboss.genericjms"> <module slot="main" id="org.jboss.genericjms"/> <transaction-support>NoTransaction</transaction-support> <connection-definitions> <connection-definition class-name="org.jboss.resource.adapter.jms.JmsManagedConnectionFactory" jndi-name="java:/jms/XAQCF" pool-name="XAQCF"> <config-property name="ConnectionFactory"> XAQCF </config-property> <config-property name="JndiParameters"> java.naming.factory.initial=com.tibco.tibjms.naming.TibjmsInitialContextFactory;java.naming.provider.url=TIBCO_EMS_SERVER_HOST_NAME:PORT </config-property> <security> <application/> </security> </connection-definition> </connection-definitions> </resource-adapter>
Configure the default message-driven bean pool with the generic resource adapter.
InEAP_HOME/standalone/configuration/standalone-full.xml
, in<subsystem xmlns="urn:jboss:domain:ejb3:1.5">
, update the<mdb>
configuration with:<mdb> <resource-adapter-ref resource-adapter-name="org.jboss.genericjms"/> <bean-instance-pool-ref pool-name="mdb-strict-max-pool"/> </mdb>
The generic JMS resource adapter is now configured and ready for use. When creating a new Message-driven Bean, use code similar below to use the resource adapter.
Example 22.4. Use the Generic Resource Adapter
@MessageDriven(name = "HelloWorldQueueMDB", activationConfig = { // The generic JMS resource adapter requires the JNDI bindings // for the actual remote connection factory and destination @ActivationConfigProperty(propertyName = "connectionFactory", propertyValue = "java:global/remoteJMS/XAQCF"), @ActivationConfigProperty(propertyName = "destination", propertyValue = "java:global/remoteJMS/Queue1"), @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"), @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge") }) public class HelloWorldQueueMDB implements MessageListener { public void onMessage(Message message) { // called every time a message is received from the `Queue1` queue on the JMS provider. } }
Warning
NullPointerException
(NPE) error. The NPE error occurs because the generic JMS resource adapter attempts processing of parameters, when the Java EE specification states that they are not to be processed.
connection.createSession(true, Session.SESSION_TRANSACTED);
Example 22.5. Use the Pooled Connection
@Resource(lookup = "java:/jms/XAQCF") private ConnectionFactory cf;
Example 22.6. Perform a Lookup
@Resource(lookup = "java:global/remoteJMS") private Context context; ... Queue queue = (Queue) context.lookup("Queue1")