How to Configure and use Active MQ JCA 1.5 Resource Adapter with OC4J 10g (10.1.3)?

First Created: 09-15-2006
Author:  
Sandeep Bangera


Introduction

This demo application showcases  configuring and deploying the Active MQ  JCA 1.5 resource adapter to OC4J 10g  10.1.3.  The resource adapter allows ActiveMQ to be used  from OC4J. 

The demo application shows how you can perform:
Outbound Communication:  Configuring a Stateless Session Bean to  send messages to a queue defined in ActiveMQ
Inbound Communication:  Configuring a Message Driven Bean to receive messages from ActiveMQ

Prerequisites

What you need to know

Software Requirements

Notations

Building the Application

The Javadoc for this application is located in the %HOWTO_HOME%/doc/javadoc/ directory.
The configuration files are located in the %HOWTO_HOME%/etc directory, including deployment descriptor files such as application.xml.


Overview

Howto Architecture

The above diagram shows the message flow in the howto example. A standlaone JMS client generates a JMS TextMessage and places it on the queue queue.inbound. These inbound messages are consumed by MDB which then invokes the Stateless EJB. The Stateless EJB takes the input from the MDB and publishes a simple response message to the queue.outbound queue.


Updating ActiveMQ rar to be OC4J deployable .

ActiveMQ rar cannont be deployed as is to OC4J. The following minor modifications need to be made:
Note: These steps are already done in the current howto for ActiveMQ 4.0.1 release. If you are using a more recent release of ActiveMQ then you may need to do the above steps to use the latest ActiveMQ RAR.

       <oracle:publishSharedLibrary
                  deployerUri="deployer:oc4j:${oc4j.host}:${oc4j.admin.port}"
                  userId="${oc4j.admin.user}"
                  password="${oc4j.admin.password}"
                  libraryName="${shared.library.name}"
                  libraryVersion="4.0.1"
                  logFile="${log.dir}/publish-library.log">
                  <oracle:uploadCodeSource path="${activemq.home}/${activemq.core.jar}" />
                  <!-- You may need to add these files to the shared library if you are interested
                        in ActiveMQ persistence features.
                        In adddition you will need to modify broker-config.xml in ra.jar to use spring properties -->

                  <!--
                     <oracle:uploadCodeSource path="${activemq.home}/lib/optional/spring-1.2.6.jar" />
                     <oracle:uploadCodeSource path="${activemq.home}/lib/optional/xbean-spring-2.2.jar" />
                  -->
           </oracle:publishSharedLibrary>
      <imported-shared-libraries>
         <import-shared-library name="activemq.rar" max-version="4.0.1"/>
      </imported-shared-libraries>


Inbound Communication - Configuring MDB to receive messages from ActiveMQ

Message Driven Bean

For the ActiveMQMessageDrivenEJBBeanIn the ejb-jar.xml deployment descriptor is declared as follows:

    <message-driven>
      <description>Message Driven Bean</description>
      <display-name>ActiveMQMessageDrivenEJB</display-name>
      <ejb-name>ActiveMQMessageDrivenEJB</ejb-name>
      <ejb-class>com.oracle.howto.activemq.ActiveMQMessageDrivenEJBBean</ejb-class>
      <messaging-type>javax.jms.MessageListener</messaging-type>
      <transaction-type>Container</transaction-type>
      <activation-config>
            <activation-config-property>
               <activation-config-property-name>destination</activation-config-property-name>
               <activation-config-property-value>queue.inbound</activation-config-property-value>
            </activation-config-property>
            <activation-config-property>
               <activation-config-property-name>destinationType</activation-config-property-name>
               <activation-config-property-value>javax.jms.Queue</activation-config-property-value>
            </activation-config-property>
            <activation-config-property>
               <activation-config-property-name>acknowledgeMode</activation-config-property-name>
               <activation-config-property-value>Auto-acknowledge</activation-config-property-value>
            </activation-config-property>
            <activation-config-property>
               <activation-config-property-name>messageSelector</activation-config-property-name>
               <activation-config-property-value/>
            </activation-config-property>
      </activation-config>
    </message-driven>

The activation-config-property is used to  link MDB to JCA.  The destination property value is only ActiveMQ specific and is the physical name of the queue on  which the MDB listens to.

Connector

The two activation configuration defined above link to the following elements in  ra.xml

        <inbound-resourceadapter>
            <messageadapter>
                <messagelistener>
                    <messagelistener-type>javax.jms.MessageListener</messagelistener-type>
                    <activationspec>
                        <activationspec-class>org.apache.activemq.ra.ActiveMQActivationSpec</activationspec-class>
                       
                        <required-config-property>
                            <config-property-name>destination</config-property-name>
                        </required-config-property>
                        <required-config-property>
                            <config-property-name>destinationType</config-property-name>
                        </required-config-property>
                       
                    </activationspec>
                </messagelistener>
            </messageadapter>
        </inbound-resourceadapter>

Additional  Glue Steps

Update orion-ejb-jar.xml with the actual dest location JNDI info.  This connects the inbound JMS Destination to the MDB
        <message-driven-deployment name="ActiveMQMessageDrivenEJB" resource-adapter="activemq-rar"
                    connection-factory-location="activeMQ/QueueConnectionFactory" destination-location="activeMQJMS/MyQ">

        </message-driven-deployment>

Update the transaction info for onMessage to be required in ejb.-jar.xml
      <container-transaction>
         <method>
            <ejb-name>ActiveMQMessageDrivenEJB</ejb-name>
            <method-name>onMessage</method-name>
            <method-params>
               <method-param>javax.jms.Message</method-param>
            </method-params>
         </method>
         <trans-attribute>Required</trans-attribute>
      </container-transaction>


Outbound Communication - Configuring a Session Bean  to send messages to ActiveMQ

Stateless Session Bean

         <resource-ref>
        <res-ref-name>jms/QCF</res-ref-name>
        <res-type>javax.jms.QueueConnectionFactory</res-type>
        <res-auth>Container</res-auth>
        <res-sharing-scope>Unshareable</res-sharing-scope>
      </resource-ref>
      <resource-env-ref>
        <resource-env-ref-name>jms/QUEUE</resource-env-ref-name>
        <resource-env-ref-type>javax.jms.Queue</resource-env-ref-type>
      </resource-env-ref>

The jms/QCF is the JNDI name the ActiveMQEJBBean will use to lookup a javax.jms.QueueConnectionFactory. We will configure it to point to an ActiveMQ QueueConnectionFactory.


        <session-deployment name="ActiveMQEJB">
            <resource-ref-mapping     name="jms/QCF"  location="activeMQ/QueueConnectionFactory" />     
            <resource-env-ref-mapping name="jms/QUEUE" location="activeMQJMS/MyQ" />
        </session-deployment>

The Connector

The resource-ref defined above will be linked to the following element in ra.xml
        <outbound-resourceadapter>
            <connection-definition>
                <managedconnectionfactory-class>org.apache.activemq.ra.ActiveMQManagedConnectionFactory</managedconnectionfactory-class>
                <connectionfactory-interface>javax.jms.ConnectionFactory</connectionfactory-interface>
                <connectionfactory-impl-class>org.apache.activemq.ra.ActiveMQConnectionFactory</connectionfactory-impl-class>
                <connection-interface>javax.jms.Connection</connection-interface>
                <connection-impl-class>org.apache.activemq.ra.ManagedConnectionProxy</connection-impl-class>
            </connection-definition>

        <adminobject>
            <adminobject-interface>javax.jms.Queue</adminobject-interface>
            <adminobject-class>org.apache.activemq.command.ActiveMQQueue</adminobject-class>
            <config-property>
                <config-property-name>PhysicalName</config-property-name>
                <config-property-type>java.lang.String</config-property-type>
            </config-property>
        </adminobject>

Glue Code

The following snippet  links the Outbound queue .  The following snippet is in oc4j-connectors.xml 

    <connector name="activemq-rar" path="activemq-ra.rar" >
        <adminobject-config location="activeMQJMS/MyQ">
            <adminobject-class>org.apache.activemq.command.ActiveMQQueue</adminobject-class>
            <config-property name="PhysicalName" value="queue.outbound"/>
        </adminobject-config>
        <adminobject-config location="activeMQJMS/MyT">
            <adminobject-class>org.apache.activemq.command.ActiveMQTopic</adminobject-class>
            <config-property name="PhysicalName" value="topic.outbound"/>
        </adminobject-config>
    </connector>

The connection factory is linked in oc4j-ra.xml

    <connector-factory location="activeMQ/QueueConnectionFactory" connector-name="activemq-rar">
        <connection-pooling use="none">
        </connection-pooling>
        <security-config use="none">
        </security-config>
        <connectionfactory-interface>javax.jms.QueueConnectionFactory</connectionfactory-interface>
    </connector-factory>

Running the Application

The following instructions are for running this demonstration on a standalone instance of Oracle Containers for J2EE 10g (10.1.3).

Examining the Sample File Directories

Configuring the Environment

Please check to make sure that the following properties are configured correctly in the howto.properties file located in the root of the sample's distribution (NOTE:  Some of these properties will default to the values of corresponding environment variables as noted below.  If you have these variables setup in your environment you may not have to alter the values in the file).  If necessary, modify these variable to the proper values for you environment:
          ActiveMQ Specific properties  
In addition, please make sure that the ant command associated with the OC4J ant distribution is in your execution path (%OC4J_HOME%/ant/bin).

Starting the OC4J Instance

Open a new console window. Start an OC4J 10.1.3 instance as follows:

Note that the oc4j command expects the JAVA_HOME environment variable to point to a full JDK installation.

Starting the ActiveMQ Instance

Open a new console window. Start an ActiveMQ 10.1.3 instance as follows:

Note that the activemq command expects the JAVA_HOME environment variable to point to a full JDK installation.

You need to install ActiveMQ 4by downloading the binaries from here.


Generating, Compiling , Deploying and Running the Application

Open a new console window. set the env variables ORACLE_HOME, ACTIVEMQ_HOME, JAVA_HOME as explained  here. To run the application, type the following command from the %HOWTO_HOME% directory:

You should now have the newly created active-mq.ear in your %HOWTO_HOME%/lib directory.

This command would attempt to deploy the application if the build is successful. It will first test whether OC4J is running. After deploying it will also run the test .The test will execute the JMS client which will  post a message to the ActiveMQ inbound queue on which the MDB is listening via the ActiveMQ Resource Adapter

You should see this message on the console where you typed  ant.
" Sent message: Hello world to ActiveMQ inbound queue!"

Return to the console where you started OC4J and you will see output generated by the MDB and Stateless EJB.

"Inside MDB, received from inbound queue: Hello world to ActiveMQ inbound queue!
Message Received from MDB inside Session Bean: Hello world to ActiveMQ inbound queue!
Sending Message from Stateless EJB to ActiveMQ outbound queue: Hello world to ActiveMQ inbound queue!"

To verify if the message posted by Stateless EJB to the ActiveMQ outbound queue "queue.outbound"  was correctly received by ActiveMQ we will use  jconsole ( JMX Browser available by default with JDK15.

Jconsole Connect Image

AtiveMQ MBean



ActiveMQ browse



Note that you can also deploy the application separately . Ensure the %ORACLE_HOME% environment variable is defined, and from the %HOWTO_HOME% directory, type the command:

If you are interested in only running the client. Please type the command:


Simplified Steps:

You would basically need 4 console windows to run this test

Summary

In this document, you should have: