Pages

Showing posts with label jms. Show all posts
Showing posts with label jms. Show all posts

Wednesday, June 13, 2012

WebLogic JMS / AQ bridge with JBoss AS 7

There are different ways to exchange JMS messages between WebLogic and JBoss Application Server 7. In this blogpost I will explain how you can retrieve JMS messages from JBoss ( with the help of a WebLogic Foreign Server ) and how to push messages to JBoss AS ( with the help of a WebLogic JMS Bridge). This even works with AQ.

For JBoss AS 7 I will use the JMS ( HornetQ ) / JBoss configuration which I already explained in this blogpost. On the WebLogic side I will use WebLogic 11gR1 PS5 or version 10.3.6.

Before we start we need to add the jboss / hornetq jars to the lib folder of your domain. Use jboss-client.jar from the bin/client jboss folder and we need to download the lates HornetQ libraries ( hornetq-2.2.14.Final) . Use the hornetq-jms-client.jar from the HornetQ lib folder.

The best way to retrieve JMS messages from JBoss AS 7 is using a WebLogic Foreign Server. In the current version of JBoss 7.1.1 it is not possible to setup bridging in the console or in one of the instances xml's.

Create a Foreign Server in a JMS module and use default targetting or target this to a WebLogic server

JNDI Initial Contect Factory is org.jboss.naming.remote.client.InitialContextFactory
JNDI Connection URL is remote://yourJbossServer:4447
Provide the remote password
In the JNDI properties add the remote username  java.naming.security.principal=xxxxx


Provide the Remote JNDI name of the Queue.


Provide the remote JNDI name of the JBoss Connection Factory -> jms/RemoteConnectionFactory


Now you deploy a MDB or a OSB process which listens on the local JNDI CF and Queue.


Second part is setting up a JMS bridge between WebLogic and JBoss. This way local messages in a local JMS or AQ Queue can be pushed to JBoss AS.

First we need to deploy two resource adapters jms-notran-adp and jms-xa-adp these rar files are located at the wlserver_10.3\server\lib. Deploy them as application and target them to the right weblogic servers.

Add a JMS Bridge Destination ( JBoss AS), this configuration is almost the same as the JBoss Foreign Server configuration.
Only choose eis/jms/WLSConnectionFactoryJNDIXA as Adapter JNDI Name.


The JMS Bridge Source ( WebLogic side )


Add a Bridge where we select the Destination and Source. Important, use Atmost-once for Quality of Service. Exactly once won't work.

Enable the started checkbox.


Add some messages to the WebLogic Queue and see if it delivered to JBoss.

Last part is to use Oracle Database AQ as source for this JMS bridge. For all the information, how to setup AQ on WebLogic see this excellent Oracle Documentation.

Create a Foreign Server, target this to a WebLogic server and use oracle.jms.AQjmsInitialContextFactory as JNDI Initial Context Factory also add a JNDI property with the JDBC datasource as value.


Add the AQ Queue name with its local WebLogic JNDI name.


Also define the Connection Factory.

And here the matching JMS bridge source which will work on the AQ Foreign server.


Happy messaging.

Friday, June 8, 2012

Remote JMS with JBoss AS 7.1 / HornetQ JMS

When you want to connect to a Queue or Topic on JBoss Application Server 7.1.1 with a remote jms client you can follow the next steps.

First step is to add messaging configuration to the JBoss configuration xml. In this case I will use the standalone configuration.

Open standalone.xml located at jboss-as-7.1.1.Final\standalone\configuration

Add org.jboss.as.messaging to the extensions

<?xml version='1.0' encoding='UTF-8'?>
<server xmlns="urn:jboss:domain:1.2">
    <extensions>
        <extension module="org.jboss.as.messaging"/>
        <extension module="org.jboss.as.clustering.infinispan"/>


Add the HornetQ messaging configuration, make sure it is the first xml entry after profile.


    <profile>
        <subsystem xmlns="urn:jboss:domain:messaging:1.1">
            <hornetq-server>
                <persistence-enabled>true</persistence-enabled>
                <journal-file-size>102400</journal-file-size>
                <journal-min-files>2</journal-min-files>

                <connectors>
                    <netty-connector name="netty" socket-binding="messaging"/>
                    <netty-connector name="netty-throughput" socket-binding="messaging-throughput">
                        <param key="batch-delay" value="50"/>
                    </netty-connector>
                    <in-vm-connector name="in-vm" server-id="0"/>
                </connectors>

                <acceptors>
                    <netty-acceptor name="netty" socket-binding="messaging"/>
                    <netty-acceptor name="netty-throughput" socket-binding="messaging-throughput">
                        <param key="batch-delay" value="50"/>
                        <param key="direct-deliver" value="false"/>
                    </netty-acceptor>
                    <in-vm-acceptor name="in-vm" server-id="0"/>
                </acceptors>

                <broadcast-groups>
                    <broadcast-group name="bg-group1">
                        <group-address>231.7.7.7</group-address>
                        <group-port>9876</group-port>
                        <broadcast-period>5000</broadcast-period>
                        <connector-ref>
                            netty
                        </connector-ref>
                    </broadcast-group>
                </broadcast-groups>

                <discovery-groups>
                    <discovery-group name="dg-group1">
                        <group-address>231.7.7.7</group-address>
                        <group-port>9876</group-port>
                        <refresh-timeout>10000</refresh-timeout>
                    </discovery-group>
                </discovery-groups>

                <cluster-connections>
                    <cluster-connection name="my-cluster">
                        <address>jms</address>
                        <connector-ref>netty</connector-ref>
                        <discovery-group-ref discovery-group-name="dg-group1"/>
                    </cluster-connection>
                </cluster-connections>

                <security-settings>
                    <security-setting match="#">
                        <permission type="send" roles="guest"/>
                        <permission type="consume" roles="guest"/>
                        <permission type="createNonDurableQueue" roles="guest"/>
                        <permission type="deleteNonDurableQueue" roles="guest"/>
                    </security-setting>
                </security-settings>

                <address-settings>
                    <address-setting match="#">
                        <dead-letter-address>jms.queue.DLQ</dead-letter-address>
                        <expiry-address>jms.queue.ExpiryQueue</expiry-address>
                        <redelivery-delay>0</redelivery-delay>
                        <max-size-bytes>10485760</max-size-bytes>
                        <address-full-policy>BLOCK</address-full-policy>
                        <message-counter-history-day-limit>10</message-counter-history-day-limit>
                        <redistribution-delay>1000</redistribution-delay>
                    </address-setting>
                </address-settings>

                <jms-connection-factories>
                    <connection-factory name="InVmConnectionFactory">
                        <connectors>
                            <connector-ref connector-name="in-vm"/>
                        </connectors>
                        <entries>
                            <entry name="java:/ConnectionFactory"/>
                        </entries>
                    </connection-factory>
                    <connection-factory name="RemoteConnectionFactory">
                        <connectors>
                            <connector-ref connector-name="netty"/>
                        </connectors>
                        <entries>
                            <entry name="RemoteConnectionFactory"/>
                            <entry name="java:jboss/exported/jms/RemoteConnectionFactory"/>
                        </entries>
                    </connection-factory>
                    <pooled-connection-factory name="hornetq-ra">
                        <transaction mode="xa"/>
                        <connectors>
                            <connector-ref connector-name="in-vm"/>
                        </connectors>
                        <entries>
                            <entry name="java:/JmsXA"/>
                        </entries>
                    </pooled-connection-factory>
                </jms-connection-factories>

                <jms-destinations>
                    <jms-queue name="testQueue">
                        <entry name="queue/test"/>
                        <entry name="java:jboss/exported/jms/queue/test"/>
                    </jms-queue>
                </jms-destinations>
            </hornetq-server>
        </subsystem>
        <subsystem xmlns="urn:jboss:domain:logging:1.1">

We will use 

RemoteConnectionFactory as JMS ConnectionFactory with "java:jboss/exported/jms/RemoteConnectionFactory" as JNDI name. Use jms/RemoteConnectionFactory as CF reference in your java client.

queue/test as Queue with as jndi name "java:jboss/exported/jms/queue/test".  Use  jms/queue/test as Queue reference.

For remote it should start with java:jboss/exported/ else these object won't be exposed and then you can't lookup the CF or Queue.

Also for remote we need to create a application user. Go to the bin folder and start add-user.sh
Create a user jms with a password and add this user to the guest role. Guest role has permission for remote and jms. 

Start JBoss with the standalone configuration.


For our java test clients we need to have a jboss and a HornetQ jar file.
First copy jboss-client.jar from the bin/client jboss folder and we need to download the lates HornetQ libraries ( hornetq-2.2.14.Final) . Copy hornetq-jms-client.jar from the HornetQ lib folder.

First the Jms Send Client


Jms Receive Client



In this example I use the same username , password for createQueueConnection
 QueueConnection qcon = qconFactory.createQueueConnection("jms","jboss1");

If you don't do this you will get this error Unable to validate user: null

INFO: JBoss Remoting version 3.2.3.GA
Exception in thread "main" javax.jms.JMSSecurityException: Unable to validate user: null
at org.hornetq.core.protocol.core.impl.ChannelImpl.sendBlocking(ChannelImpl.java:312)
Caused by: HornetQException[errorCode=105 message=Unable to validate user: null]

To solve this you can also disable messaging security
    <profile>
        <subsystem xmlns="urn:jboss:domain:messaging:1.1">
            <hornetq-server>
                <persistence-enabled>true</persistence-enabled>
                <journal-file-size>102400</journal-file-size>
                <journal-min-files>2</journal-min-files>
                <security-enabled>false</security-enabled> 

Now you can also use QueueConnection qcon = qconFactory.createQueueConnection();

That's all

Thursday, November 20, 2008

Using AQ in WebLogic 10.3

For a project we want to use a Message Driven Bean in WebLogic 10.3 which listens to an Oracle AQ queue. You can use a JMS bridge which uses jndi and OID to retrieve the connection and queue. This didn't work for me because the OID username and password must be same as the Database user of the queue. But there is another way to make this happen. Robert Patrick made a great howto. I decide to do same what Robert did I do it from JDeveloper 11G.
In this blog we will create a startup class for WebLogic which can connect to the AQ queues and topics.
First I made a new jdeveloper 11G application with 3 projects.
The first is wls10.3. This project generates a startup class jar ( I imported the wls10 and jms1.1 code from Robert) In this project there is also a password file generator for the database user / password. WLS uses this password file to connect to the Oracle database .
The MDB project is my Message Driven Bean which will enqueue the AQ messages.
The last project is JmsClient which can dequeue or enqueue new messages to AQ through WLS. Not directly to the database.


For these projects I need the AQ and Weblogic 10.3 remote-client library.



Now we can create a new jar ( deploy project wls10.3 to jar ) called WLS103AQJMSStartupClass.jar



Let's create in the scott/tiger schema a jms queue table called TEST_TABLE and a queue TEST

begin

sys.dbms_aqadm.create_queue_table(

queue_table => 'TEST_TABLE',

queue_payload_type => 'SYS.AQ$_JMS_MESSAGE',

sort_list => 'PRIORITY',

compatible => '10.0.0',

primary_instance => 0,

secondary_instance => 0,

storage_clause => 'tablespace USERS pctfree 10 initrans 1 maxtrans 255 storage ( initial 64K minextents 1 maxextents unlimited )');

end;

/

begin

sys.dbms_aqadm.create_queue(

queue_name => 'TEST',

queue_table => 'TEST_TABLE',

queue_type => sys.dbms_aqadm.normal_queue,

max_retries => 5,

retry_delay => 0,

retention_time => 0);

end;

/


Make sure to start the queue


Next step is to generate the password files which holds the scott/tiger username password.
We do this by running the AQJMSPasswordUtility class. Delete the aqjms.dat and aqjms_user.properties files.


com.oracle.oems.weblogic.AQJMSPasswordUtility -username scott -password tiger


this will generate the password files agian


I use in this blog the Weblogic server of jdeveloper 11g. In this middleware home I create a new folder jms_lib ( D:\oracle\Middleware\jms_lib ) . In this folder I copied the following files WLS103AQJMSStartupClass.jar, aqapi.jar , aqjms.dat, aqjms_user.properties and aqjms.properties files.


Change the aqjms.properties file so it matches with your database and queue.


# Oracle database connection-related properties#


Server=XPCND7010XMP


Port=1521


DBInstance=orcl


These are important settings ( I will use AQJMS_QueueConnectionFactory as my jndi connection factory lookup, I have a queue and I don't use XA )


XAQueueConnectionFactoryJNDIName=AQJMS_XAQueueConnectionFactory


QueueConnectionFactoryJNDIName=AQJMS_QueueConnectionFactory


XATopicConnectionFactoryJNDIName=AQJMS_XATopicConnectionFactory


TopicConnectionFactoryJNDIName=AQJMS_TopicConnectionFactory


Change QueueName1 to TEST ( the name of the Queue in the scott schema)


QueueName1=TEST


#QueueName2=JMSDEMO_QUEUE2


#TopicName1=JMSDEMO_TOPIC1


Give the queue name a jndi name so we can use this name in the JNDI lookup of the queue


QueueJNDIName1=ORAQ_TEST


#QueueJNDIName2=ORAQ_JMSDEMO_QUEUE2


#TopicJNDIName1=ORAQ_JMSDEMO_TOPIC1


We are ready with changing this file. Now we can configure Weblogic so it uses the startup class.


first open the setDomainEnv.cmd file located in D:\oracle\Middleware\jdeveloper\system\system11.1.1.0.31.51.56\DefaultDomain\bin


Add -Doracle.jms.useEmulatedXA=false -Doracle.jms.useNativeXA=true to the JAVA_PROPERTIES variable


and Add D:\oracle\Middleware\jms_lib\WLS103AQJMSStartupClass.jar;D:\oracle\Middleware\jms_lib\aqapi.jar to the PRE_CLASSPATH variable


Start the WebLogic Server where we will create a new Startup Class




Use as "AQJMSPropertiesFile=aqjms.properties, AQJMSPasswordFile=aqjms_user.properties, AQJMSSecretFile=aqjms.dat, AQJMSConfigDirectory=D:/oracle/Middleware/jms_lib" as arguments.

Or you can change the config.xml and add the startupclass to this xml

<startup-class>
<name>AQStartUpClass</name>
<target>DefaultServer</target>
<deployment-order>1000</deployment-order>
<class-name>com.oracle.oems.weblogic.AQJMSStartupClass</class-name>
<arguments>AQJMSPropertiesFile=aqjms.properties,AQJMSPasswordFile=aqjms_user.properties,AQJMSSecretFile=aqjms.dat,AQJMSConfigDirectory=D:/oracle/Middleware/jms_lib</arguments>
<failure-is-fatal>true</failure-is-fatal>
<load-before-app-deployments>true</load-before-app-deployments>
<load-before-app-activation>true</load-before-app-activation>
</startup-class>

Restart Weblogic and deploy the Message Driven Bean to WLS or use the dequeue / enqueue class to connect to weblogic / aq.
Here is some code from the dequeue java class which can connect to weblogic.

String queueName = "ORAQ_TEST";
String queueConnectionFactoryName = "AQJMS_QueueConnectionFactory";

Context ctx;

try {
Properties parm = new Properties();
parm.setProperty("java.naming.factory.initial","weblogic.jndi.WLInitialContextFactory");
parm.setProperty("java.naming.provider.url","t3://localhost:7101");
parm.setProperty("java.naming.security.principal","weblogic");
parm.setProperty("java.naming.security.credentials","weblogic");

ctx = new InitialContext(parm);

QueueConnectionFactory connectionFactory =
(QueueConnectionFactory)ctx.lookup(queueConnectionFactoryName);

connection = connectionFactory.createQueueConnection();
connection.start();
session = connection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
queue = (Queue)ctx.lookup(queueName);
receiver = session.createReceiver(queue);

try {
javax.jms.TextMessage textMessage = (javax.jms.TextMessage)receiver.receive();
System.out.println("Receiving message [" + textMessage.getJMSMessageID() + "] enqueued at " + new Timestamp(textMessage.getJMSTimestamp()).toString());
String xmlText = textMessage.getText();
System.out.println(xmlText);
} catch (JMSException jmse) {
jmse.printStackTrace();
}

receiver.close();
session.close();
connection.close();


} catch (JMSException je) {
throw new RuntimeException("Fout opgetreden bij het starten ",je);
} catch (Throwable t) {
throw new RuntimeException("Fout opgetreden bij het starten ",t);


Download the 11g example project here

Friday, October 10, 2008

JMS in JDeveloper 11g and WebLogic 10.3

JMS is a bit different in JDeveloper 11G and WebLogic 10.3 then when you use OC4J 10.1.3. This blog will show you how you can create a Queue and Connection Factory in WebLogic and use this in one of your JDeveloper 11g projects.
First you have to add two libraries to the project, The first is the AQJMS library ( even when we don't use AQ ) and the second library is the WebLogic 10.3 thin Client

Start the weblogic server. Menu Run , Start Server Instance


The url is http://localhost:7101/console. Username weblogic password weblogic.


Default the weblogic server has an empty configuration. We need to create a new jms server with a database of file persistance. We need this for the queue or topic persistence

create a new jms system module. In this module we will create a new connection factory and queue
Select the just created jms module and create a new connection factory first.



Create a new queue

Make sure that the queue uses the jms server. See the targets this can't be empty

And here is the java code to test the connection factory and the queue

The difference with oc4j is that you use other jndi properties. This are the right properties for WebLogic 10.3 in JDeveloper 11g

java.naming.factory.initial weblogic.jndi.WLInitialContextFactory
java.naming.provider.url t3://localhost:7101
java.naming.security.principal weblogic
java.naming.security.credentials weblogic




package nl.ordina.jms;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.Timestamp;
import java.util.Properties;
import javax.jms.JMSException;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueReceiver;
import javax.jms.QueueSender;
import javax.jms.QueueSession;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.naming.Context;
import javax.naming.InitialContext;

public class WeblogicClient {

private QueueConnection connection = null;
private QueueSession session = null;
private QueueSender sender = null;
private QueueReceiver receiver = null;
private Queue queue = null;
private long waitTime = 0;


public WeblogicClient() {
setUp();
put();
get();
tearDown();
}

public static void main(String[] args) {
WeblogicClient weblogicClient = new WeblogicClient();
}

public void tearDown() {
try {
sender.close();
receiver.close();
session.close();
connection.close();

} catch (JMSException je) {
je.printStackTrace();
} finally {
}
}

public void get(){
try {
javax.jms.TextMessage textMessage = (javax.jms.TextMessage)receiver.receive();
System.out.println("Receiving message [" + textMessage.getJMSMessageID() + "] enqueued at " + new Timestamp(textMessage.getJMSTimestamp()).toString());
String xmlText = textMessage.getText();
System.out.println(xmlText);
} catch (JMSException jmse) {
jmse.printStackTrace();
}
}

public void put(){
String messageId = null;
String xmlData = "";
FileInputStream fis;
try {
fis = new FileInputStream("D:\\projecten\\mhs_esb\\delfor.xml");
int x= fis.available();
byte b[]= new byte[x];
fis.read(b);
xmlData = new String(b);
} catch (FileNotFoundException e) {
// TODO
} catch (IOException e) {
// TODO
}
try {
TextMessage message = session.createTextMessage(xmlData);
sender.send(message);
} catch (JMSException jmse) {
jmse.printStackTrace();
}
}

protected void setUp() {

String queueName = "jms/QTest";
String queueConnectionFactoryName = "jms/CFTest";
Context ctx;

try {
Properties parm = new Properties();
parm.setProperty("java.naming.factory.initial","weblogic.jndi.WLInitialContextFactory");
parm.setProperty("java.naming.provider.url","t3://localhost:7101");
parm.setProperty("java.naming.security.principal","weblogic");
parm.setProperty("java.naming.security.credentials","weblogic");

ctx = new InitialContext(parm);

QueueConnectionFactory connectionFactory =
(QueueConnectionFactory)ctx.lookup(queueConnectionFactoryName);

connection = connectionFactory.createQueueConnection();
connection.start();
session = connection.createQueueSession(false, Session.CLIENT_ACKNOWLEDGE);
queue = (Queue)ctx.lookup(queueName);
sender = session.createSender(queue);
receiver = session.createReceiver(queue);


} catch (JMSException je) {
throw new RuntimeException("Fout opgetreden bij het starten ",je);
} catch (Throwable t) {
throw new RuntimeException("Fout opgetreden bij het starten ",t);

}
}

}


Friday, October 3, 2008

Lookup Oracle database queue (AQ) with jndi and LDAP

In my previous blog entry I explained how you can register tnsnames entries and database connections in OpenLDAP, this blog entry goes a little further. This blog explains how you can register Oracle database queues (AQ) in ldap and use them with JNDI. I don't use OID because the product takes too many resources. I just want to lookup some queues. So I downloaded openldap and create the oracle ldap schema and add this to openldap. Now I can register oracle object in LDAP and use it in java.

Here you see how my LDAP tree looks like. Click here to get the LDIF file
SCOTT.TEST is a queue called test in the scott oracle schema. SCOTT.TEST_TABLE is the queue table of the test queue.
The LDAP attributes of the queue entry and this queue has a pointer to the queue table (first attribute)
The queue table attributes

The database connection registration which you can use for the connection factory
Here is the plsql code to create the queue and queue table

begin
sys.dbms_aqadm.create_queue_table(
queue_table => 'TEST_TABLE',
queue_payload_type => 'SYS.AQ$_JMS_MESSAGE',
sort_list => 'PRIORITY',
compatible => '10.0.0',
primary_instance => 0,
secondary_instance => 0,
storage_clause => 'tablespace USERS pctfree 10 initrans 1 maxtrans 255 storage ( initial 64K minextents 1 maxextents unlimited )');
end;
/
begin
sys.dbms_aqadm.create_queue(
queue_name => 'TEST',
queue_table => 'TEST_TABLE',
queue_type => sys.dbms_aqadm.normal_queue,
max_retries => 5,
retry_delay => 0,
retention_time => 0);
end;
/

The java code where we do a lookup of the database connection to create the connection factory and do a lookup to create a queue.

package jms2;

import java.util.Hashtable;
import javax.jms.JMSException;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueReceiver;
import javax.jms.QueueSender;
import javax.jms.QueueSession;

import javax.jms.TextMessage;

import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;

//import oracle.jms.AQjmsOracleDebug;


public class jmsclient2 {

Hashtable env = null;
boolean envSet = false;
private QueueConnection connection = null;
private QueueSession session = null;
private QueueSender sender = null;
private QueueReceiver receiver = null;
private QueueConnectionFactory queueConnectionFact = null;;
private Queue queue = null;;


public void testRegistration() {
// AQjmsOracleDebug.setLogStream(out);
// AQjmsOracleDebug.setTraceLevel(AQjmsOracleDebug.AQ_ORA_TR6);
// AQjmsOracleDebug.setDebug(true);

env = new Hashtable(5, 0.75f);
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL , "ldap://localhost:389");
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL , "o=sgi,c=us");
env.put(Context.SECURITY_CREDENTIALS , "secret");

DirContext dirContext = null;
try {
dirContext = new InitialDirContext(env);

dirContext=(DirContext)dirContext.lookup("cn=ORCL, cn=OracleContext, ou=Services, o=sgi,c=us");
DirContext destctxCF = (DirContext)dirContext.lookup("cn=oracledbconnections");
DirContext destctxQF = (DirContext)dirContext.lookup("cn=OracleDBQueues");

queueConnectionFact = (QueueConnectionFactory)destctxCF.lookup("cn=SCOTT");
queue = (Queue) destctxQF.lookup("cn=SCOTT.TEST");

connection = queueConnectionFact.createQueueConnection();
session = connection.createQueueSession(true, QueueSession.AUTO_ACKNOWLEDGE);
connection.start();

sender = session.createSender(queue);
String xmlData = "1111";
TextMessage message = session.createTextMessage(xmlData);
sender.send(message);

receiver = session.createReceiver(queue);
TextMessage textMessage = (javax.jms.TextMessage)receiver.receive();
String xmlText = textMessage.getText();
System.out.println(xmlText);


} catch (NamingException ne) {
ne.printStackTrace();
} catch (JMSException jmse) {
jmse.printStackTrace();
}
}

public static void main (String[] args) {
jmsclient2 client = new jmsclient2();
client.testRegistration();

}
}


That's all.

Sunday, May 25, 2008

Using OpenLDAP for net8 and AQ connection factory

In this blog I will show you can use OpenLDAP to lookup your Oracle Net (tnsnames) connections or AQ connection factories. Now you don't need to have an Oracle Internet Directory (OID) installed. The first step is to download openldap. Install this and download my oracle.schema and put this in the schema folder of openldap. This file has to be included in the slapd.conf.
Edit slapd.conf and add
"include schema/java.schema"
"include schema/oracle.schema" .
Make sure anonymous can read the tnsnames entries.
access to dn="" by * read
access to *
by self write
by users read
by anonymous read
We have to configure the ldap for Oracle by making an OracleContext and oracledbconnections entry.

I do this with ldapbrowser. You can download it here. For this free java application I made some templates which you can use.



Do the same for oracledbconnections ( this is for the AQ entries) Now use the queue template in ldapbrowser.

To make a tnsnames entry I select the OracleContext ldap entry and I use the orclNetService template to create a new Oracle connection.

We are ready to use it, we only has to create ldap.ora in the network\admin folder. The ldap.ora looks like this.
DIRECTORY_SERVERS= (localhost:389:636)

DEFAULT_ADMIN_CONTEXT = "o=sgi,c=us"

DIRECTORY_SERVER_TYPE = OID

We start sqlplus and use the ldap name as tnsnames entry. I can also start net manager and go the Directory menuitem to see our ldap entry

The second part shows you can lookup an AQ connection factory with JNDI and ldap. first let's register a new connection in the ldap server. For this I only need the following jars files. jndi-1.2.1.jar,jta-1.0.1.jar, jms-1.1.jar,aqapi.jar and the jdbc jar of oracle



package jms2;

import java.util.Hashtable;
import java.util.Properties;
import javax.jms.JMSException;
import javax.naming.Context;
import oracle.jms.AQjmsFactory;

public class register_jms_to_oid {
public register_jms_to_oid() {
Hashtable env = new Hashtable(5, 0.75f);
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://localhost:389");
env.put("server_dn", "o=sgi,c=us");
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, "o=sgi,c=us");
env.put(Context.SECURITY_CREDENTIALS, "secret");
String url = "jdbc:oracle:thin:@XPCND7010XMP:1521:orcl";
Properties properties = new Properties();
properties.setProperty("user","scott");
properties.setProperty("password","tiger");
try {
AQjmsFactory.registerConnectionFactory(env, "scott3", url ,properties, "queue");
} catch ( JMSException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
register_jms_to_oid register_jms_to_oid = new register_jms_to_oid();
}
}

Now we can lookup this entry with standard jms calls.

package jms2;

import java.util.Hashtable;
import javax.jms.JMSException;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueSender;
import javax.jms.QueueSession;
import javax.jms.TextMessage;
import javax.jms.QueueConnectionFactory;
import javax.naming.Context;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.NamingException;

public class lookup_jndi_queue {

private QueueConnection connection = null;
private QueueSession session = null;
private QueueSender sender = null;

public lookup_jndi_queue() {

Hashtable env = new Hashtable(5, 0.75f);
DirContext ctx;
QueueConnectionFactory queueConnectionFact;
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://localhost:389");
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, "o=sgi,c=us");
env.put(Context.SECURITY_CREDENTIALS, "secret");

try {
ctx = new InitialDirContext(env);
ctx = (DirContext)ctx.lookup("cn=connections, o=sgi,c=us");
Object reference = ctx.lookup("cn=scott");
queueConnectionFact = (QueueConnectionFactory)reference;
try {
connection = queueConnectionFact.createQueueConnection();
session = connection.createQueueSession(true, QueueSession.CLIENT_ACKNOWLEDGE);
connection.start();
QueueSession session = connection.createQueueSession(true, QueueSession.AUTO_ACKNOWLEDGE);
Queue queue = session.createQueue("JMS_IN");
sender = session.createSender(queue);
String xmlData = "1111";
TextMessage message = session.createTextMessage(xmlData);
sender.send(message);
session.commit();
} catch (JMSException e) {
// TODO
e.printStackTrace();
}
} catch (NamingException ee) {
// TODO
ee.printStackTrace();
}
}

public static void main(String[] args) {
lookup_jndi_queue lookup_jndi_queue = new lookup_jndi_queue();
}
}


You can also use the ldapbrowser template. The entry look this in ldap.

Monday, March 24, 2008

Flex jms client with OC4J Queue ( blazeds)

In this blog I will show what you have to do to send and receive jms text messages in flex. For this I use the embedded container of jdeveloper 10.1.3.3 with the blazeds libraries and the blazeds configuration xml files( this is very easy, how to do this see this blog). I also use the j2ee container of jdeveloper 10.1.3.3 so I can use the jms queues and do the rmi jndi lookup. First we create a queue in the oc4j container. I will do it manually by editing the jms.xml in the j2ee\home\config folder. Here we add a queue and a queue connection factory.
<queue name="MyJMSQueue" location="jms/MyJMSQueue">
<queue-connection-factory location="jms/MyJMSQCF"/>
Now you can start the j2ee server and use this java code to test the queue. You have to add a lot of oc4j libraries (located in j2ee\home\ ) to get rmi jndi lookup standalone working.

package jms2;

import java.sql.Timestamp;
import java.util.Properties;
import javax.jms.JMSException;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueReceiver;
import javax.jms.QueueSender;
import javax.jms.QueueSession;
import javax.jms.Session;
import javax.jms.TextMessage;

import javax.naming.Context;
import javax.naming.InitialContext;


public class jmsclientoc4j {

private QueueConnection connection = null;
private QueueSession session = null;
private QueueSender sender = null;
private QueueReceiver receiver = null;
private Queue queue = null;
private long waitTime = 0;

public jmsclientoc4j() {

}

public static void main(String[] args) {
new jmsclientoc4j().execute();
}

public void tearDown() {
try {
sender.close();
receiver.close();
session.close();
connection.close();

} catch (JMSException je) {
je.printStackTrace();
} finally {
}
}


public void execute() {
setUp();
put();
get();
tearDown();
}


public void get(){

try {
javax.jms.TextMessage textMessage = (javax.jms.TextMessage)receiver.receive();
System.out.println("Receiving message [" + textMessage.getJMSMessageID() + "] enqueued at " + new Timestamp(textMessage.getJMSTimestamp()).toString());
String xmlText = textMessage.getText();
System.out.println(xmlText);
} catch (JMSException jmse) {
jmse.printStackTrace();
}
}

public void put(){

String messageId = null;
String xmlData = "1111";
try {
TextMessage message = session.createTextMessage(xmlData);
sender.send(message);
} catch (JMSException jmse) {
jmse.printStackTrace();
}
}

protected void setUp() {

// Haal instellingen voor de verbinding op
String queueName = "jms/MyJMSQueue";
String queueConnectionFactoryName = "jms/MyJMSQCF";
Context ctx;

try {
Properties parm = new Properties();
parm.setProperty("java.naming.factory.initial","com.evermind.server.rmi.RMIInitialContextFactory");
parm.setProperty("java.naming.provider.url","ormi://localhost:23791/");
parm.setProperty("java.naming.security.principal","oc4jadmin");
parm.setProperty("java.naming.security.credentials","welcome");

ctx = new InitialContext(parm);

QueueConnectionFactory connectionFactory =
(QueueConnectionFactory)ctx.lookup(queueConnectionFactoryName);

connection = connectionFactory.createQueueConnection();
connection.start();
session = connection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
queue = (Queue)ctx.lookup(queueName);
sender = session.createSender(queue);
receiver = session.createReceiver(queue);


} catch (JMSException je) {
throw new RuntimeException("Fout opgetreden bij het starten ",
je);
} catch (Throwable t) {
throw new RuntimeException("Fout opgetreden bij het starten ",
t);

}
}
}

Here are the blazeds configurations files, these files are located in public_html/WEB-INF/flex/. For jms we need services-config.xml for the channel defitions. You can define two jms channels one for streaming, this mean blazeds is continually connected to the queue, the other polls the queue every few seconds.
The second blazeds configuration xml is the messaging-config.xml file. In this file we define the jms adapter.
here is the service-config.xml

Here is messaging-config.xml with the jms configuration

Now we are raedy with the java side now we can go to the flex builder. first we create the flex project. Follow the pictures belows



The jms producer and consumer mxml looks like this. Here we can send text messages to the queue and the consumer automatically receive these messages and displays it on the screen.

Here is the result.

Saturday, February 23, 2008

JNDI connections lookup with RMI and LDAP

In java you can lookup connections and datasources with JNDI. The Oracle java libraries enables you to do this against the OC4J Container with rmi or against the OID server with ldap ( probably this will work with other ldap servers too). The first part of this blog is about the ldap jndi lookup and second part is about the rmi lookup.
I use the ldap server of Oracle Identity Management 10g (10.1.4.0.1) to register the connection, which you can download at otn. First we have to rename the object OracleDBConnection and its cn attribute to lowercase. Now we can register the connection with java. We have to set server_dn so java can find the oracledbconnection object. In all the Oracle examples they use searchbase but this is not going to work then you get the following error message cn=oracledbconnections,null.

Hashtable env = new Hashtable(5, 0.75f);
// env.put(Context.INITIAL_CONTEXT_FACTORY, AQjmsConstants.INIT_CTX_FACTORY);
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://win2003_2:389");
env.put("server_dn", "cn=IDENT, cn=OracleContext");
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, "cn=orcladmin");
env.put(Context.SECURITY_CREDENTIALS, "Welcome01");

String url = "jdbc:oracle:thin:@XPCND7010XMP:1521:orcl";
Properties properties = new Properties();
properties.setProperty("user","scott");
properties.setProperty("password","tiger");

try {
AQjmsFactory.registerConnectionFactory(env, "scott", url ,properties, "queue");

} catch ( JMSException e) {
e.printStackTrace();
}

This is how it looks in ldap.



Now we can try to lookup the scott connection and create a queueconnection so we can dequeue the scott.JMS_IN queue

Hashtable env = new Hashtable(5, 0.75f);
DirContext ctx;
QueueConnectionFactory queueConnectionFact;

env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://win2003_2:389");
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, "cn=orcladmin");
env.put(Context.SECURITY_CREDENTIALS, "Welcome01");

try {
ctx = new InitialDirContext(env);
ctx = (DirContext)ctx.lookup("cn=oracledbconnections,cn=IDENT,cn=OracleContext");
queueConnectionFact = (QueueConnectionFactory)ctx.lookup("cn=scott");
// Start QueueConnection
try {
connection = queueConnectionFact.createQueueConnection();

session = connection.createQueueSession(true, QueueSession.CLIENT_ACKNOWLEDGE);
connection.start();
queue = ((AQjmsSession)session).getQueue("scott", "JMS_IN");
sender = ((AQjmsSession)session).createSender(queue);

String xmlData = "1111";
TextMessage message = session.createTextMessage(xmlData);
sender.send(message);
session.commit();
} catch (JMSException e) {
// TODO
e.printStackTrace();
}
} catch (NamingException ee) {
// TODO
ee.printStackTrace();
}


We can also lookup the jdbc/scott datasource with JNDI and rmi. First we have to create a datasource in the oc4j container. You can do this with the em webapp or go the datasources.xml in the config folder. You need a lot of oc4j container libraries to get this working. ( oc4jclient.jar , oc4j-internal.jar, connector.jar, bcel.jar, pcl.jar, jazn.jar and adminclient.jar )

Context ctx;
try {
Properties parm = new Properties();
parm.setProperty("java.naming.factory.initial","com.evermind.server.rmi.RMIInitialContextFactory");
parm.setProperty("java.naming.provider.url","ormi://localhost:23791/");
parm.setProperty("java.naming.security.principal","oc4jadmin");
parm.setProperty("java.naming.security.credentials","welcome");

ctx = new InitialContext(parm);
DataSource ds = (DataSource)ctx.lookup("jdbc/scott");
//Bepaal dbUser:
Connection conn = ds.getConnection();
dbUser = conn.getMetaData().getUserName();
conn.close();
factory = AQjmsFactory.getQueueConnectionFactory(ds);
// Maak QueueConnection
connection = factory.createQueueConnection();
// Maak QueueSession
session = connection.createQueueSession(true, Session.CLIENT_ACKNOWLEDGE);
// Start QueueConnection
connection.start();
// Haal Queue op
queue = ((AQjmsSession)session).getQueue(dbUser, queueTable);
// Maak QueueSender
sender = ((AQjmsSession)session).createSender(queue);
} catch (NamingException e) {
throw new RuntimeException("Fout opgetreden bij het starten ",
e);
} catch (JMSException je) {
throw new RuntimeException("Fout opgetreden bij het starten ",
je);
} catch (Throwable t) {
throw new RuntimeException("Fout opgetreden bij het starten ",
t);
}

Now you can store your connection in the ldap or Application Server.

Here is the example project. My jdeveloper home is D:\oracle\jdevstudio10133. This is voor j2ee rmi libs

Thursday, January 24, 2008

Oracle JMS with ESB and BPEL

In the esb server for the customer we want to use queues between the message handling system and the backoffices databases. In the Oracle database you can do this with Oracle AQ or with Oracle jms. We want to use the jms queue because we don't know in the future we still want to use Oracle esb and then it is easier in an other program to connect to the Oracle jms implementation then to connect to Oracle AQ. So we don't have to change the queues. You can easily create a jms queue in the database
First we give the schema user scott permission to create a queue.
grant aq_user_role to scott;
grant execute on DBMS_AQADM to scott;
We can create the queue table

begin
sys.dbms_aqadm.create_queue_table(
queue_table => 'JMS_IN_TABLE',
queue_payload_type => 'SYS.AQ$_JMS_MESSAGE',
sort_list => 'PRIORITY, ENQ_TIME',
compatible => '10.0.0',
primary_instance => 0,
secondary_instance => 0,
storage_clause => 'tablespace users pctfree 10 initrans 1 maxtrans 255 storage ( initial 64K minextents 1 maxextents unlimited )');
end;
/

What important is that we use 'SYS.AQ$_JMS_MESSAGE' as payload type and the dequeue order is first priority and then the enqueue time.
Now we can create the queue

begin
sys.dbms_aqadm.create_queue(
queue_name => 'JMS_IN',
queue_table => 'JMS_IN_TABLE',
queue_type => sys.dbms_aqadm.normal_queue);
end;
/

If you want to dequeue and enqueue this queue we have to enable this first

begin
dbms_aqadm.start_queue( queue_name =>'JMS_IN' ,enqueue => true ,dequeue => true );
end;
/

With this plsql code we can add a message to the queue

declare
l_message clob := '';
v_enqueue_options dbms_aq.enqueue_options_t;
v_msg_props dbms_aq.message_properties_t;
v_msg_id RAW(16);
v_message SYS.AQ$_JMS_MESSAGE := SYS.AQ$_JMS_MESSAGE.construct(DBMS_AQ.JMS_TEXT_MESSAGE);
begin
l_message := '<data-message><runid>210</runid></data-message>';
v_message.set_text(xmltype(l_message).getstringval());

dbms_aq.enqueue(queue_name => 'JMS_IN'
,enqueue_options => v_enqueue_options
,message_properties => v_msg_props
,payload => v_message
,msgid => v_msg_id);
commit;
end;
/

Now we are ready to use this in the ESB. We can add a new JMS adapter in the composite view.
Choose database as oems jms provider

Create a new database connection to scott.

If you want to enqueue a message then choose produce and if you want to dequeue choose consumer

Give the resource provider a name ( we need this name later )and select the destination.

Now we add the resource provider in the application.xml in the config folder, use the same name as above

<resource-provider class="oracle.jms.OjmsContext" name="jms">
<description>oc4j-jms loop back resource provider</description>
<property name="url" value="jdbc:oracle:thin:scott/tiger@localhost:1521:orcl"/>
</resource-provider>

The last step is to configure the jms adapter. Go to the deployment folder then to the default and JmsAdapter folder. Here we edit the oc4j-ra.xml where we add a new connection
Location is the database connection name and change the user and password properties. We have to change the value of connectionFactoryLocation property. Between /resource and /QueueConnectionFactoryLocation we have to add the resource provider name.

<connection-factory connector-name="Jms Adapter" location="eis/Jms/scott">
<config-property name="connectionFactoryLocation" value="java:comp/resource/jms/QueueConnectionFactories/myQCF" encoded-credential="false"/>
<config-property name="factoryProperties" value="" encoded-credential="false"/>
<config-property name="acknowledgeMode" value="AUTO_ACKNOWLEDGE" encoded-credential="false"/>
<config-property name="isTopic" value="false" encoded-credential="false"/>
<config-property name="isTransacted" value="true" encoded-credential="false"/>
<config-property name="username" value="scott" encoded-credential="false"/>
<config-property name="password" value="tiger" encoded-credential="false"/>
</connection-factory>

Now we can use the jms queue in the esb.