Monday, August 29, 2016

Oracle AQ with WSO2 ESB 4.8.1 / 4.9.0

Environment
Oracle 11g R2 Expression
WSO2 ESB 4.8.1 and 4.9.0
Apache Directory Studio Version: 2.0.0.v20150606-M9
Oracle Installation and Configuration.


If you need to install oracle in ubuntu 15.04 you can follow the steps in this blog and I was able to successfully install oracle instance in my ubuntu environment.


  1. First, we need to create an Oracle user which having privileges to create queue and  queue tables.

    The following privileges are required. (You may need to provide additional privileges). You can execute following commands in command line or create a user using the SQL Developer client.

    #sqlplus sys/admin@orcl as sysdba;
    #create user jmsuser identified by jmsuser account unlock;
    #grant create session,dba to jmsuser;
    #grant connect, resource to jmsuser;
    #grant aq_administrator_role to jmsuser  identified by  jmsuser;
    #grant execute on dbms_aq to  jmsuser;
    #grant execute on dbms_aqadm to jmsuser;
    #exec dbms_aqadm.grant_system_privilege('ENQUEUE_ANY','jmsuser');
    #exec dbms_aqadm.grant_system_privilege('DEQUEUE_ANY','jmsuser');
    #grant execute on sys.aq$_jms_text_message to jmsuser;


JAVA client to create a queue.

I have attached simple JAVA client to do the following tasks, (Please download the JAVA client from here)

1) Create a queue with the queue table,
2) Enqueue messages
3) Dequeue messages

For this client you may need to add the following jars comes with the Oracle installation. (Also, you can download them from here.)

aqapi.jar
jmscommon.jar
jta.jar
Ojdbc6.jar I have created queue "TEST" using "TEST_TABLE" in Oracle AQ. For that I used above JAVA client. Please refer the following code segment. And create a queue to proceed further in this tutorial. public static void main(String args[]) throws JMSException { // to create new queue please uncommented below commented line QueueConnection QCon = getConnection(); Session session = QCon.createQueueSession(false, Session.CLIENT_ACKNOWLEDGE); String userName = "jmsuser"; String queue = "TEST"; String qTable = "TEST_TABLE"; createQueue( session,userName, qTable , queue); sendMessage(userName, queue); browseMessage(userName, queue); // consumeMessage(userName, queue); }




LDAP Server Installation and Configuration

To enable Java Naming and Directory Interface (JNDI) lookup in OJMS, you need to register the database with an LDAP server. JMS administrator can register ConnectionFactory objects in a LDAP server.

Here, ApacheDS is used as the sample LDAP server. (You can use whatever LDAP server you like). You must have following structure of Oracle Streams AQ entries in the LDAP server.



ApacheDS installation and Configurations

Download, install and start the Apache Directory Studio™ (v2.0.0)
Go to 'File' menu and click 'New'. Select 'ApcheDS' server. Go to 'next' page.
Provide a unique name to identify your LDAP server instance. (eg: Apacheds) Click 'Finish'. You will see your newly created server at servers panel.
Double click on a server instance (ie:Apacheds's) link.You will see a window which lists all options to configure the server.
At the 'General' tab, you can provide the port numbers for different protocols. Here leave the default port numbers as it is.

LDAP =10389
LDAPS=10636


Go to 'servers' panel and click the 'start' button. (Green icon with white color triangle)

Now, the server is started. Need to create a connection to that server.

Go to 'LDAP' menu and select 'New Connection'. Provide;

Connection name - oracleAQ

Hostname - localhost

Port no -10389 (This is the port number 'apacheds' server instance running)


Click 'Next'.

Authentication Method - "Simple Authentication"

Bind DN - "uid=admin,ou=system" (this is the one by default available partition and the user)

Bind password - 'secret' (default  password)

If you provide all the above parameters correctly, your connection will start successfully.


You can see the available partitions at LDAP browser.That is it for ApacheDS installation and configuration.

Partitions for OracleAQ entries directory structure

To create a new partition, which is going to be used to keep Oracle Streams AQ entries in the LDAP server, I have used an oracle. schema (available as an attachment) file, which contains all ObjectClasses definitions needed by AQ. For your easy I have attached ldif file file and you can directly import this to the schemas. Please download the oraclenew.ldif file from here.







Right click on the ou=schema => Import => LDIF Import and select the attached oracleNew.ldif file. If this step is successfully done,“oracle specific object classes” can be used.



Let  create a new partition to keep OracleAQ entries.



Double click on server link. You will see the config.ldif graphical view. From that select 'Partitions' tab.

Under partitions section you will see default two partitions are listed out.

System
Example

Click on the 'Add' button. You will see a new partition will be created. Provide an ID and suffix. Click on 'Save' button @ toolbar.

ID='Services'
suffix='ou=Services, o=sgi,c=us'


Now you have created a new partition called "Services". But you can not view that at LDAP browser. To view in browser, need to restart the LDAP server.

You will see the newly created entry in LDAP browser

To connect to this newly created partition, you have to create an uid. (I have attached structure.ldif to create uid and other entries so you can directly import it without creating manually.)

Right Click on administrative context-->new entry-->select ObjectClass as 'inetOrgPerson'.
Select base DN as dn='ou=Services, o=sgi,c=us'
uid='krishan'
Provide password for the uid ='secret' (just provide the default password)
Make sure that you have provided attributes to the user like below.

Now user is created. Let us try to create entries for AQ.

According to OracleAQ entries structure, the second level would be,cn=OracleContext, which is the root of the Oracle RDBMS schema.

Right click->New entry-->Select 'use existing entry as template'

Provide 'ou=Services, o=sgi,c=us'.

Click 'Next' and select following 'javacontainer' as ObjectClass. Provide 'cn=oraclecontext'.

Likewise, we need to create other entries also.

I have attached the structure.ldif file so you can  just import this in the administrative context (Right click on ou=Services, o=sgi,c=us' partition and select LDIF Import and select provided file). Anyway, you may need to edit attribute values according to your configurations.




Finally, your LDAP browser will look like this;

AQ entries in LDAP server are successfully created now. The above mentioned settings are totally related to OracleAQ and the JNDI lookup for OracleJMS. Now we will look at the ESB side configurations for OracleAQ.
ESB Transport Configuration

To support JMS transport we have to enable 'jms' transport at axis2 configuration. Find the axis2.xml and edit as following; (you must be careful when you provide the base DN and connection parameters)

Axis2 Transport level configuration

To enable JMS transport, you need to un comment the 'JMS' transport sender and receiver in order to send and receive messages to/from OracleAQ. Here LDAP server is used as the data source, which can be accessible via JNDI API.

Edit axis2 configuration as follows;

Add the transport listener configuration.
<!-- ================================================= -->
 <!--             Transport Ins (Listeners)             -->
<!-- ================================================= -->
 <transportReceiver name="local" class="org.wso2.carbon.core.transports.local.CarbonLocalTransportReceiver"/>  
 <transportReceiver name="jms" class="org.apache.axis2.transport.jms.JMSListener">  
  <parameter name="myQueueConnectionFactory" locked="false">  
   <parameter name="java.naming.factory.initial" locked="false">com.sun.jndi.ldap.LdapCtxFactory</parameter>  
   <parameter name="java.naming.provider.url" locked="false">ldap://localhost:10389</parameter>  
   <parameter name="server_dn" locked="false">cn=XE,cn=OracleContext,ou=Services, o=sgi,c=us</parameter>  
   <parameter name="java.naming.security.principal" locked="false">uid=krishan,ou=Services, o=sgi,c=us</parameter>  
   <parameter name="java.naming.security.credentials" locked="false">secret</parameter>  
   <parameter name="java.naming.security.authentication" locked="false">simple</parameter>  
   <parameter name="transport.jms.UserName" locked="false">jmsuser</parameter>  
   <parameter name="transport.jms.Password" locked="false">jmsuser</parameter>                 
   <parameter name="transport.jms.ConnectionFactoryJNDIName" locked="false">cn=JMSUSER,cn=oracledbconnections,cn=XE,cn=OracleContext,ou=Services, o=sgi,c=us</parameter>  
   <parameter name="transport.jms.ConnectionFactoryType" locked="false">queue</parameter>  
  </parameter>  
  <parameter name="default" locked="false">  
   <parameter name="java.naming.factory.initial" locked="false">com.sun.jndi.ldap.LdapCtxFactory</parameter>  
   <parameter name="java.naming.provider.url" locked="false">ldap://localhost:10389</parameter>  
   <parameter name="server_dn" locked="false">cn=XE,cn=OracleContext,ou=Services, o=sgi,c=us</parameter>  
   <parameter name="java.naming.security.principal" locked="false">uid=krishan,ou=Services, o=sgi,c=us</parameter>  
   <parameter name="java.naming.security.credentials" locked="false">secret</parameter>  
   <parameter name="java.naming.security.authentication" locked="false">simple</parameter>  
   <parameter name="transport.jms.UserName" locked="false">jmsuser</parameter>  
   <parameter name="transport.jms.Password" locked="false">jmsuser</parameter>  
   <parameter name="transport.jms.ConnectionFactoryJNDIName" locked="false">cn=JMSUSER,cn=oracledbconnections,cn=XE,cn=OracleContext,ou=Services, o=sgi,c=us</parameter>  
   <parameter name="transport.jms.ConnectionFactoryType" locked="false">queue</parameter>  
  </parameter>   
 </transportReceiver>  
Also, enable transport sender
   <!-- ================================================= -->

   <!--             Transport Outs (Senders)              -->

   <!-- ================================================= -->
 <transportSender name="jms" class="org.apache.axis2.transport.jms.JMSSender"/>  

Note:

Above configurations are based on the ApcheDS configuration we made above. You might need to change parameter values according to your LDAP server configurations.

You should keep following jars in your "ESB_HOME\repository\components\lib" folder.

aqapi.jar
jmscommon.jar
jta.jar
Ojdbc6.jar

If you successfully configure above step, server will start to listen to the queue, which we have created already. Also, you will see the following log on startup console of the server

INFO - JMSListener Started to listen on destination : cn=JMSUSER.TEST,cn=OracleDBQueues,cn=XE,cn=OracleContext,ou=Services, o=sgi,c=us of type queue for service queueListner
JMS Listener Proxy Configuration

You can deploy followed proxy service to listen to JMS queue and consume messages from there.
 <?xml version="1.0" encoding="UTF-8"?>  
 <proxy xmlns="http://ws.apache.org/ns/synapse"  
     name="queueListner"  
     transports="jms"  
     statistics="disable"  
     trace="disable"  
     startOnLoad="true">  
   <target>  
    <inSequence>  
      <log level="full"/>  
      <drop/>  
    </inSequence>  
   </target>  
   <parameter name="transport.jms.ContentType">  
    <rules>  
      <jmsProperty>ContentType</jmsProperty>  
      <default>text/plain</default>  
    </rules>  
   </parameter>  
   <parameter name="transport.jms.Destination">cn=JMSUSER.TEST,cn=OracleDBQueues,cn=XE,cn=OracleContext,ou=Services, o=sgi,c=us</parameter>  
   <description/>  
 </proxy>                       

You can use, provided JAVA client application to enqueue messages to the queue.

JMS Producer Proxy Configuration

 <?xml version="1.0" encoding="UTF-8"?>  
 <proxy xmlns="http://ws.apache.org/ns/synapse"  
     name="messageProducer"  
     transports="https http"  
     startOnLoad="true"  
     trace="disable">  
   <description/>  
   <target>  
    <inSequence>  
      <property name="OUT_ONLY" value="true"/>  
      <log level="full">  
       <property name="INSEQ" value="*****"/>  
      </log>  
      <send>  
       <endpoint>  
         <address uri="jms:/cn=JMSUSER.TEST,cn=OracleDBQueues,cn=XE,cn=OracleContext,ou=Services, o=sgi,c=us?java.naming.factory.initial=com.sun.jndi.ldap.LdapCtxFactory&amp;transport.jms.ConnectionFactoryJNDIName=cn=JMSUSER,cn=oracledbconnections,cn=XE,cn=OracleContext,ou=Services, o=sgi,c=us&amp;java.naming.provider.url=ldap://localhost:10389/&amp; transport.jms.DestinationType=queue&amp; server_dn=cn=XE,cn=OracleContext,ou=Services, o=sgi,c=us&amp; java.naming.security.principal=uid=krishan,ou=Services, o=sgi,c=us&amp; java.naming.security.credentials=secret&amp; java.naming.security.authentication=simple&amp; transport.jms.UserName=jmsuser&amp; transport.jms.Password=jmsuser"/>  
       </endpoint>  
      </send>  
    </inSequence>  
   </target>  
 </proxy>  

1 comment :

  1. Do you know if is possible to use XMLType using jms jndi lookup? Using SYS.AQ$_JMS_TEXT_MESSAGE, works like a charm, but I have queues that DataBase create XML using XMLType, and I can't change type of that queues, is that possible?

    Thank you, nice documentation, clear and precise.

    ReplyDelete