« OC4J: Interaction between 10.1.3.x & 10.1.2.0.2, Part 1 | Main | OC4J: Interaction between 10.1.3.x & 10.1.2.0.2, Part 2 »

OC4J: Configuring and Using AQ w/ Remote Clients

Caveat

For a better understanding of the details used herein please refer to the How-To on OTN.

Requirements

You need an Oracle Database that supports AQ configuration. Also OC4J/Oracle Application Server 10.1.3.3 or later is required. I've tested this with OC4J 10.1.3.3 standalone and SOA Suite 10.1.3.1 patched to 10.1.3.3. Tests with OC4J 10.1.3.2 showed some issues.

The Application

In JDeveloper create a new application called AQ. Don't create a new project (simply cancel that window). This application will eventually contain two projects for the AQ configuration and a remote client test project.

The Resource Adapter

Create a new empty project named AQRA for AQ Resource Adapter. In this project create two new deployment descriptors: ra.xml and oc4j-ra.xml. Finally create a RAR deployment profile named aqjms to package the resource adapter. We can use the deployment profile as it was created.

ra.xml

After JDeveloper has created the default file content for the ra.xml we replace the whole content with the one from the ra.xml that comes with the How-to (see References). You can either remove or keep the comments. Now comes the tricky part: We need to have good, easier to type names. Therfore we replace the OEMSJMSDReference with aqRP. Secondly the <adminobject>'s that have the jndiName Queues/MY_QUEUE or Topics/MY_TOPIC should be removed. The generic approach for accessing the queues is good enough for us.

oc4j-ra.xml

We do the same as with the ra.xml with the oc4j-ra.xml file, ie replacing the whole content of the file with the content of the sample oc4j-ra.xml from the How-to. The tricky part is the same here, we need to have good, easier to type names:
  • Replace connector-name="OEMSJMSDRAInstanceName" with connector-name="AQRA"
  • Likewise we change the location="OEMSJMSDRASubcontext to location="AQJMSSubcontext

Deployment Profile

We can use the RAR deployment profile as created by JDeveloper. Doing a Recompile All will move the deployment descriptors to classes directory and makes them visible for the profile.

The Enterprise Application

Once we have done the resource adapter, we need to package it properly as a Java EE Enterprise Application in an EAR file. For this we create a new empty project called EAR. In this project we need to create three OC4J-specific deployment descriptors: data-sources.xml, orion-application.xml, and oc4j-connectors.xml. Next, we create an EAR deployment profile called aqear for the final EAR creation.

data-sources.xml

The data-sources.xml contains just the configuration needed for the AQ data source. Nothing more. Here is the complete file:
<?xml version = '1.0' encoding = 'windows-1252'?>
<data-sources xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:noNamespaceSchemaLocation="http://xmlns.oracle.com/oracleas/schema/data-sources-10_1.xsd">
   <managed-data-source connection-pool-name="aqPool" jndi-name="jdbc/aqDS"
                        name="aqDS"/>
   <connection-pool name="aqPool">
      <connection-factory factory-class="oracle.jdbc.pool.OracleDataSource"
                          user="jmsuser" password="welcome1"
                          url="jdbc:oracle:thin:@//localhost:1521/XE">
         <proxy-interface sql-object="PreparedStatement"
                          interface="oracle.jdbc.OraclePreparedStatement"/>
         <proxy-interface sql-object="Connection"
                          interface="oracle.jdbc.internal.OracleConnection"/>
         <proxy-interface sql-object="CallableStatement"
                          interface="oracle.jdbc.OracleCallableStatement"/>
         <proxy-interface sql-object="Statement"
                          interface="oracle.jdbc.OracleStatement"/>
         <proxy-interface sql-object="ResultSet"
                          interface="oracle.jdbc.OracleResultSet"/>
      </connection-factory>
   </connection-pool>
</data-sources>

orion-application.xml

In the orion-application.xml we configure the link between the data source and the resource adapter, the <resource-provider> tag. Here is the complete file:
<?xml version = '1.0' encoding = 'windows-1252'?>
<orion-application xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                   xsi:noNamespaceSchemaLocation="http://xmlns.oracle.com/oracleas/schema/orion-application-10_0.xsd">
  <data-sources path="./data-sources.xml" />
  <connectors path="./oc4j-connectors.xml" />
  <resource-provider class="oracle.jms.OjmsContext" name="aqRP">
    <property name="datasource" value="jdbc/aqDS" />
  </resource-provider>
</orion-application>

oc4j-connectors.xml

The next file is the oc4j-connectors.xml. In this file we configure the link between the resource provider and the JNDI space. Here is the complete file:
<?xml version="1.0" encoding="windows-1252" ?>
<oc4j-connectors xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xsi:noNamespaceSchemaLocation="http://www.oracle.com/technology/oracleas/schema/oc4j-connectors-10_0.xsd"
                 schema-major-version="10" schema-minor-version="0">
<connector name="AQRA" path="aqjms.rar">
  <config-property name="lookupMethod" value="resourceProvider" />
  <config-property name="resourceProviderName" value="aqRP" />
  <adminobject-config location="aq/Queues">
   <adminobject-class>oracle.j2ee.ra.jms.generic.AdminObjectQueueImpl</adminobject-class>
   <config-property name="resourceProviderName" value="aqRP" />
  </adminobject-config>
  <adminobject-config location="aq/Topics">
  <adminobject-class>oracle.j2ee.ra.jms.generic.AdminObjectTopicImpl</adminobject-class>
   <config-property name="resourceProviderName" value="aqRP" />
  </adminobject-config>
</connector>
</oc4j-connectors>

EAR deployment profile

By default the EAR deployment profile includes the standard deployment descriptors. To add the oc4j-connectors.xml we need some extra steps. Double click on the deployment profile and create a new file group (I called it files). In the Filters sub item select only the oc4j-connectors.xml to be included. The rest will be included automagically.

Deployment Profile Screenshot for AQ:

The AQ Setup

To setup the AQ Queues and Topics you should use a SQL script. This comes in handy to redo it when needed (eg. when moving from Development to Production). Here is a simple script:
BEGIN
   DBMS_AQADM.CREATE_QUEUE_TABLE(
        queue_table => 'FromTable',
        queue_payload_type => 'SYS.AQ$_JMS_MESSAGE',
        sort_list => 'PRIORITY,ENQ_TIME',
        multiple_consumers => false,
        compatible => '9.2');
   DBMS_AQADM.CREATE_QUEUE(
      queue_name => 'FROM_QUEUE',
      queue_table => 'FromTable');
   DBMS_AQADM.START_QUEUE(
      queue_name => 'FROM_QUEUE');
   DBMS_AQADM.CREATE_QUEUE_TABLE(
      Queue_table => 'ToTable',
      Queue_payload_type => 'SYS.AQ$_JMS_MESSAGE',
      sort_list => 'PRIORITY,ENQ_TIME',
      multiple_consumers => false,
      compatible => '9.2');
   DBMS_AQADM.CREATE_QUEUE(
      Queue_name => 'TO_QUEUE',
      Queue_table => 'ToTable');
   DBMS_AQADM.START_QUEUE(
      queue_name => 'TO_QUEUE');
   DBMS_AQADM.CREATE_QUEUE_TABLE(
      Queue_table        => 'LOGQTABLE',
      Queue_payload_type => 'SYS.AQ$_JMS_MESSAGE',
      sort_list => 'PRIORITY,ENQ_TIME',
  multiple_consumers => false,
      compatible         => '9.2');
   DBMS_AQADM.CREATE_QUEUE(
      Queue_name  => 'logQ',
      Queue_table => 'LOGQTABLE',
      max_retries => '2');
   DBMS_AQADM.START_QUEUE(
      queue_name => 'logQ');
END;

The Remote Client

Finally, we create an empty project called client for the remote test client. As it is always useful to test your configuration, this one can always be used for configuration verification and sanity checks. It both sends and receives from the queues. For brevity I'll show the sending part only. The receiving part is left as an exercise to the reader.
    System.out.println("Testing queue using " + factoryName + ' ' + 
                       destinationName);
    Connection conn = null;
    Session sess = null;
    MessageProducer prod = null;
    boolean verbose = false;
    try {
      ConnectionFactory factory = (ConnectionFactory)ctx.lookup(factoryName);
      Destination destSend = (Destination)ctx.lookup(destinationName);
      conn = factory.createConnection();
      conn.start();
      sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
      prod = sess.createProducer(destSend);
      TextMessage payload = sess.createTextMessage();
      payload.setText(msg);
      payload.setJMSCorrelationID(new Long(System.currentTimeMillis()).toString());
      prod.send(payload);
      System.out.print("Send " + payload.getJMSCorrelationID());
      if (verbose) {
        System.out.print(' ' + payload.getText());
      }
      System.out.println();
    } finally {
      closeJMSResources(prod, sess, conn);
      prod = null;
      sess = null;
      conn = null;
    }
As good developer we use the jndi.properties file for configuring the JNDI connection and credentials setup.

Needed Libraries

The remote client needs a number of libraries to work properly. These are (within JDeveloper 10.1.3.3):
  • J2EE
  • Oracle 9 iAS
  • $OC4J_HOME/j2ee/home/lib/javax77.jar
  • $OC4J_HOME/j2ee/home/lib/jmxri.jar
  • $OC4J_HOME/j2ee/home/lib/connector.jar
  • $OC4J_HOME/j2ee/home/lib/adminclient.jar
  • $OC4J_HOME/j2ee/home/lib/bcel.jar
  • $OC4J_HOME/j2ee/home/jazncore.jar
  • Oracle JDBC

What JNDI names should I use then?

The JNDI names you should use are:
  • AQJMSsubcontext/My{CF,QCF,TCF,XACF,XAQCF,XATCF}
  • aq/Queues/Queues/<queue_name> or aq/Topics/Topics/<topic_name>

Global Setup

For a server global setup of the AQ resource adapter, you can deploy the RAR file directly from the aqjms deployment profile to OC4J. The only downside is that you have to do the configuration of the global configuration files application.xml, data-sources.xml, and oc4j-connectors.xml manually.

References

Comments (2)

Mark :

It is great blog. I wonder if I can have the complete set of files which contains the testing clients.

Thanks

Mark:

Olaf,

Thanks a again for your blog.
By following the step and step instructions above, I got everything work and the teating client (servlet) is able to send and receive messages from the AQ (Queue name: FROM_QUEUE) defined.

Now I am trying to test with using MDB 3.0. Somehow the message driven bean is never fired up. Do I need any additional configurations to make MDB work? If so, please give your suggestions. The testing MDB code is below, please let me know if I miss anything:

package mdb;

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

import oracle.j2ee.ejb.MessageDrivenDeployment;

@MessageDriven(
messageListenerInterface=MessageListener.class,
activationConfig = {
@ActivationConfigProperty(
propertyName="connectionFactoryJndiName", propertyValue="AQJMSSubcontext/MyQCF"),
@ActivationConfigProperty(
propertyName="destinationName", propertyValue="aq/Queues/Queues/FROM_QUEUE"),
@ActivationConfigProperty(
propertyName="destinationType", propertyValue="javax.jms.Queue"),
@ActivationConfigProperty(
propertyName="messageSelector", propertyValue="RECIPIENT = 'MDB'")
})

//@MessageDrivenDeployment(resourceAdapter = "AQRA")
public class QueueMDBBean implements MessageListener {
public void onMessage(Message msg) {
System.out.println("mdb is invoked." + msg);
}
}

Post a comment

(If you haven't left a comment here before, you may need to be approved by the site owner before your comment will appear. Until then, it won't appear on the entry. Thanks for waiting.)

About This Entry

This page contains a single entry from the blog posted on July 24, 2007 12:23 PM.

The previous post in this blog was OC4J: Interaction between 10.1.3.x & 10.1.2.0.2, Part 1.

The next post in this blog is OC4J: Interaction between 10.1.3.x & 10.1.2.0.2, Part 2.

Many more can be found on the main index page or by looking through the archives.

Top Tags

Powered by
Movable Type and Oracle