Pages

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

11 comments:

  1. Hi,

    could you proviede JDeveloper workspace with this example?

    Kuba

    ReplyDelete
  2. Hi Kuba,

    I updatet the blog with a link to the example project

    ReplyDelete
  3. Hi,

    I am working on JMS Queues using JDeveloper and OC4J. I am getting following runtime exception:

    JNDI API lookup failed: javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file: java.naming.factory.initial

    javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file: java.naming.factory.initial

    at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:645)

    at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:247)

    at javax.naming.InitialContext.getURLOrDefaultInitCtx(InitialContext.java:284)

    at javax.naming.InitialContext.lookup(InitialContext.java:351)

    at SimpleProducer_java.main(SimpleProducer_java.java:131)





    at the following line of code:



    ConnectionFactory connectionFactory = null;

    Destination dest = null;



    try {

    connectionFactory = (ConnectionFactory) jndiContext.lookup("jms/QueueConnectionFactory");

    dest = (Destination) jndiContext.lookup(destName);

    } catch (Exception e) {

    System.out.println("JNDI API lookup failed: " + e.toString());

    e.printStackTrace();

    System.exit(1);

    }





    I think it is failing now on looking up jms/QueueConnectionFactory. In which file I have to put up the entry of jms/QueueConnectionFactory for looking up?

    Can you guide me how to lookup this jms/QueueConnectionFactory? Or can you give me your email address so that i can send my code to check?

    Thanks.

    Farrukh Mahmood
    fmahmood@gmail.com

    ReplyDelete
  4. Hi,

    the jms config is located in j2ee/home/config/jms.xml

    what is your context parameter ( jndi)

    my mail address = biemond at gmail dot com

    thanks

    ReplyDelete
  5. Hi,

    Can you give me an idea of how to invoke a proxy service using java in OSB. Means my java program should invoke the proxy service.

    Thanks,

    ReplyDelete
  6. Hi

    I think you want to start this proxy with rmi t3 protocol or else if your proxy has a wsdl interface then you can generate a ws proxy client.

    thanks Edwin

    ReplyDelete
  7. My scenario is to call the proxy service from the java class. And I had tried to call the proxy service from bpel by making the proxy service as WSDL. But I am not getting any idea of the configurations of the java class to call that proxy WSDL.Could you help me on this issue.

    ReplyDelete
  8. Hi,

    here is some documentation how to use osb and bpel.

    I tried once to call the osb proxy with rmi / t3 this is not possible yet but you can do it with bpel ( ormi) and call from bpel the osb proxy.

    or create a wsdl and use ws in the proxy service and publish this and then use jdev to generate a ws proxy on this url and call the proxy service from java

    or put a jms message on queue and listen for the results.

    let me know what works for you.

    ReplyDelete
  9. here is the url http://download.oracle.com/docs/cd/E13159_01/osb/docs10gr3/bpelpmtransport/transport.html

    ReplyDelete
  10. Actually I have tried the first option calling OSb from a BPEL process. But my case is to write the java code which will execute the proxy service in OSB.

    Could you please explain me a lille bit on the second scenario which you are explaning here."create a wsdl and use ws in the proxy service and publish this and then use jdev to generate a ws proxy on this url and call the proxy service from java".

    I think my scenario may be similar to calling a BPEL process from java.

    ReplyDelete
  11. Hi,

    Watch today or tommorrow my blog for a osb to bpel and back description. I got it working.

    you can not call an osb service with rmi but we can always use soap.

    So create a wsdl ( sync or async ) with the operations you want , create a proxy service and use this wsdl. use http as transport and define your endpoint and define your flow where you can call a business service.
    when you deploy this and it is working then you can use jdev and create a new project with a ws proxy client , In this wizard you can add the wsdl url and jdev generates java code and some proxy classes.

    that's all

    thanks edwin

    ReplyDelete