Skip to content

Instantly share code, notes, and snippets.

@remibantos
Last active August 24, 2022 07:03
Show Gist options
  • Save remibantos/33c366803f189db9b225 to your computer and use it in GitHub Desktop.
Save remibantos/33c366803f189db9b225 to your computer and use it in GitHub Desktop.
Message Driven Beans with Wildfly and Websphere MQ

Message Driven Beans with Wildfly and Websphere MQ

Introduction

This page describes MDB (Message Driven Bean) configuration with Wildfly (> version 8 implementing Java EE 7/8) and Websphere MQ messaging broker.

Websphere MQ Resource Adapter

Description

Websphere MQ provides a resource adapter which is able to interact with latest and even legacy Websphere MQ versions. (See this link for WMQ v8.0 Resource Adapter compatibility details)
It implements Java Connector Architecture (JCA) Java EE specification, allowing to interact with it from a Java EE application server.
Finally it allows Java EE 7 applications using JMS 2.0 specification to interact with legacy WMQ JMS 1.1 providers in an implicit way.

MDB setup

MDB code sample

Bellow is a sample of MDB

package org.rembx.sample.jee;

import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.ejb.MessageDrivenContext;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;

/**
 * User: bantos
 */

@MessageDriven(activationConfig = {
        @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
        @ActivationConfigProperty(propertyName = "useJNDI", propertyValue = "true"),
        @ActivationConfigProperty(propertyName = "destination", propertyValue = "java:/jboss/test"),
        @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge")})
public class TestMDB implements MessageListener {

    @Override
    public void onMessage(Message message) {

        if (message instanceof TextMessage) {
            try {
                System.out.println(((TextMessage) message).getText());
            } catch (JMSException e) {
                // propagate for transaction rollback
                throw new IllegalArgumentException(e);
            }
        }

    }
}

Note that ActivationSpec annotations used here do not depend on environment. (See following section)

MDB destination configuration

WebsphereMQ resource adapter does not allow to use standalone.xml admin-objects for destination configuration (admin-objects can only be used by messages producers).
Thus we need to configure the whole destination parameters such as JMS provider host, port, (...), in MDB configuration.
Configuring such parameters with MDB ActivationSpec annotations would not help to maintain contextual configuration (related to environment).

jboss-ejb3.xml deployment descriptor (in WEB-INF directory of webapp,

This custom deployment descriptor (See this link for details) allows to declare and maintain properly contextual MDB configuration related to destination by using system properties.

<?xml version="1.0" encoding="UTF-8"?>
<jboss:ejb-jar xmlns:jboss="http://www.jboss.com/xml/ns/javaee"
               xmlns="http://java.sun.com/xml/ns/javaee"
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xsi:schemaLocation="http://www.jboss.com/xml/ns/javaee http://www.jboss.org/j2ee/schema/jboss-ejb3-2_0.xsd
                  http://java.sun.com/xml/ns/javaee http://www.jboss.org/j2ee/schema/jboss-ejb3-spec-2_0.xsd"
               xmlns:mdb="urn:resource-adapter-binding" version="3.1" impl-version="2.0">

    <jboss:enterprise-beans>
        <message-driven>
            <ejb-name>TestMDB</ejb-name>
            <ejb-class>org.rembx.sample.jee.TestMDB</ejb-class>
            <transaction-type>Container</transaction-type>
            <message-destination-type>javax.jms.Queue</message-destination-type>
            <activation-config>
                <activation-config-property>
                    <activation-config-property-name>channel</activation-config-property-name>
                    <activation-config-property-value>${websphere.channel}</activation-config-property-value>
                </activation-config-property>
                <activation-config-property>
                    <activation-config-property-name>queueManager</activation-config-property-name>
                    <activation-config-property-value>${websphere.queueManager}</activation-config-property-value>
                </activation-config-property>
                <activation-config-property>
                    <activation-config-property-name>transportType</activation-config-property-name>
                    <activation-config-property-value>${websphere.transportType}</activation-config-property-value>
                </activation-config-property>
                <activation-config-property>
                    <activation-config-property-name>hostName</activation-config-property-name>
                    <activation-config-property-value>${websphere.hostName}</activation-config-property-value>
                </activation-config-property>
                <activation-config-property>
                    <activation-config-property-name>port</activation-config-property-name>
                    <activation-config-property-value>${websphere.port}</activation-config-property-value>
                </activation-config-property>
            </activation-config>
        </message-driven>
    </jboss:enterprise-beans>
    <assembly-descriptor>
        <mdb:resource-adapter-binding>
            <ejb-name>TestMDB</ejb-name>
            <mdb:resource-adapter-name>${websphere.resource.adapter}</mdb:resource-adapter-name>
        </mdb:resource-adapter-binding>
    </assembly-descriptor>
</jboss:ejb-jar>

standalone.xml

The following resource-adapters subsystem configuration has to be added

        <subsystem xmlns="urn:jboss:domain:resource-adapters:2.0">
            <resource-adapters>
                <resource-adapter id="wmq.jmsra.rar">
                    <archive>
                        wmq.jmsra.rar
                    </archive>
                    <transaction-support>NoTransaction</transaction-support>
                    <connection-definitions>
                        <connection-definition class-name="com.ibm.mq.connector.outbound.ManagedConnectionFactoryImpl" jndi-name="java:/jboss/MyConnectionFactory" use-java-context="true" pool-name="mqconn">
                            <config-property name="hostName">
                                ${websphere.hostName:localhost}
                            </config-property>
                            <config-property name="password">
                                ${websphere.password:mqm}
                            </config-property>
                            <config-property name="queueManager">
                                ${websphere.queueManager:QUEUE.MANAGER}
                            </config-property>
                            <config-property name="port">
                                ${websphere.port:1414}
                            </config-property>
                            <config-property name="channel">
                                ${websphere.channel:SYSTEM.AUTO.SVRCONN}
                            </config-property>
                            <config-property name="transportType">
                                ${websphere.transportType:CLIENT}
                            </config-property>
                            <config-property name="username">
                                ${websphere.username:mqm}
                            </config-property>
                            <security>
                                <application/>
                            </security>
                        </connection-definition>
                    </connection-definitions>
                    <admin-objects>
                        <admin-object class-name="com.ibm.mq.connector.outbound.MQQueueProxy" jndi-name="java:/jboss/test" use-java-context="true" pool-name="MQ.QUEUE.NAME">
                            <config-property name="baseQueueName">
                                ${websphere.queueName:Q_QUEUE}
                            </config-property>
                        </admin-object>
                    </admin-objects>
                </resource-adapter>
            </resource-adapters>
        </subsystem>

Then, destination contextual configuration is defined through syste-properties. (These properties are referenced by WMQ resource-adapter configuration (see above) and jboss-ejb3.xml MDB configuration)

<system-properties>
        <property name="websphere.hostName" value="< WMQ HOST >"/>
        <property name="websphere.port" value="< WMQ PORT >"/>
        <property name="websphere.channel" value="< WMQ CHANNEL >"/>
        <property name="websphere.transportType" value="< WMQ TRANSPORT TYPE >"/>
        <property name="websphere.queueManager" value="< WMQ HQUEUE MANAGER >"/>
        <property name="websphere.queueName" value="< WMQ QUEUE NAME >"/>
        <property name="websphere.resource.adapter" value="< WMQ RESOURCE ADAPTER ARCHIVE NAME (such as wmq.jmsra.rar) >"/>
</system-properties>

Messages push configuration

Sample of JMS messages producer

The following EJB pushes messages to configured test destination :

package org.rembx.sample.jee;

import javax.annotation.Resource;
import javax.ejb.Stateless;
import javax.jms.*;
import java.util.UUID;

@Stateless
public class ResourceSample {

    @Resource(mappedName = "java:/jboss/MyConnectionFactory")
    ConnectionFactory factory;

    @Resource(mappedName = "java:/jboss/test")
    Queue queue;

    public void pushMessage() throws JMSException {
        try (JMSContext context = connectionFactory.createContext()) {
            context.createProducer().send(queue, "Hello World !");
        }
    }
}

Links

@sidhuurs
Copy link

sidhuurs commented Jul 16, 2017

Thanks for great article. Couple of questions.... is it not possible to add ConnectionFcatory jndi to MDB through annotation ? do we need to deploy wmq.jmsra.rar into wildfly as a module ? is not required at to add resource adopter to MDB as a resource through annotation?

@foukad
Copy link

foukad commented Oct 5, 2021

Bonjour Rémi,
merci pur cet article très intéressants. Je voudrais savoir comment je peut activer le SSL avec mon MDB (sslCipherSuite)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment