Pages

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.

17 comments:

  1. Hi,

    Nice article.

    Have you worked on AQ and securing JMS messages?

    Contact merageeth@gmail.com

    Thanks,

    ReplyDelete
  2. Hi, Yes I did. What do you want to know about this.

    ReplyDelete
  3. Hi Edwin,
    we have the following entry in LDAP for Oracle AQ queue configuration :
    dn: cn=messagequeue_aq, cn=OracleDBQueues, ou=queues, ou=tms, ou=services, o=nhs
    objectClass: top
    objectClass: javaContainer
    objectClass: javaObject
    objectClass: javaNamingReference
    objectClass: orclDBAQObject
    javaFactory: oracle.jms.AQjmsDestinationFactory
    javaClassName: oracle.jms.AQjmsDestination
    orclDBAQObjName: MESSAGE_QUEUE
    orclDBAQObjOwner: aqadm
    orclDBAQPointerAttr: QUEUE_MESSAGE_TABLE
    orclDBAQObjType: AQ$_JMS_BYTES_MESSAGE

    But when we try to send a message to the queue, the following error is thrown :
    javax.naming.NamingException: problem generating object using object factory [Root exception is java.lang.NullPointerException]; remaining name 'cn=messagequeue_aq, cn=OracleDBQueues, ou=queues, ou=tms, ou=services, o=nhs'
    at com.sun.jndi.ldap.LdapCtx.c_lookup(LdapCtx.java:1052)
    at com.sun.jndi.toolkit.ctx.ComponentContext.p_lookup(ComponentContext.java:526)
    at com.sun.jndi.toolkit.ctx.PartialCompositeContext.lookup(PartialCompositeContext.java:159)
    at com.sun.jndi.toolkit.ctx.PartialCompositeContext.lookup(PartialCompositeContext.java:148)
    at javax.naming.InitialContext.lookup(InitialContext.java:351)
    at src.java.servlet.Test.main(Test.java:58)
    Caused by: java.lang.NullPointerException
    at oracle.jms.AQjmsDestinationFactory.getObjectInstance(AQjmsDestinationFactory.java:120)
    at javax.naming.spi.DirectoryManager.getObjectInstance(DirectoryManager.java:176)
    at com.sun.jndi.ldap.LdapCtx.c_lookup(LdapCtx.java:1045)
    ... 5 more


    It seems the queue object is not getting created due to insufficient /invalid attribures.

    Can you please help?

    ReplyDelete
  4. Hi, can you post a picture of the ldap entry and the java code

    thanks

    ReplyDelete
  5. Hi Edwin,
    thanks a lot for the prompt reply.
    i am not able to post a picture.
    Can i have ur personal email id so that i can post it there

    ReplyDelete
  6. You can send it to biemond @ gmail . com

    ReplyDelete
  7. Hi,
    I got your oracle.schema and try to import that to ApcheDS in order to work with JNDI endabled OracleAQ

    Anyway ApacheDS says some errors with the schema
    After importing that to ApcheDS server , I'm not seeing the oracle specific objects..
    Any help regarding this would be appreciate..

    ReplyDelete
  8. Hi,

    this schema works for openldap, you should know how it works in ApacheDS.

    Probably it has a different schema definition format.

    thanks

    ReplyDelete
  9. Hi,
    Thanks for help..I managed with your schema in ApcheDS and successfully registered my connection factory.
    As pointed in this post[1], I have created a queue object under 'OracleDBQueues"..But when i do lookup it gives null
    //code
    Queue queue = (Queue) destctxQF.lookup("cn=ratha.test");

    Any idea, how can i overcome this?

    Thanks..
    -Ratha


    [1]http://biemond.blogspot.com/2008/10/lookup-oracle-database-queue-aq-with.html

    ReplyDelete
  10. Hi,
    Thanks for help..I managed with your schema in ApcheDS and successfully registered my connection factory.
    As pointed in this post[1], I have created a queue object under 'OracleDBQueues"..But when i do lookup it gives null
    //code
    Queue queue = (Queue) destctxQF.lookup("cn=ratha.test");

    Any idea, how can i overcome this?

    Thanks..
    -Ratha


    [1]http://biemond.blogspot.com/2008/10/lookup-oracle-database-queue-aq-with.html

    ReplyDelete
  11. This is my ldif definition for ratha.test queue;

    dn: cn=ratha.test,cn=OracleDBQueues,cn=ORCL,cn=OracleContext,ou=Services,o=s
    gi,c=us
    objectClass: javaContainer
    objectClass: orclDBAQObject
    objectClass: javaNamingReference
    objectClass: javaObject
    objectClass: top
    cn: ratha.test
    javaClassName: oracle.jms.AQjmsDestination
    orcldbaqobjtype: Queue
    javaFactory: oracle.jms.AQjmsDestinationFactory
    orcldbaqobjname: test
    orcldbaqobjowner: ratha
    orcldbaqpointerattr: cn=ratha.test_table,cn=OracleDBQueuesTables,cn=ORCL,cn=
    OracleContext,ou=Services,o=sgi,c=us

    ReplyDelete
  12. Hi,

    Did you do the following,

    Create a oracle database connection which contains username / password and jdbc url and in my case under cn=oracledbconnections,cn=ORCL, cn=OracleContext, ou=Services, o=sgi,c=us


    Then do a base dn which contains the db connections

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

    more specific

    DirContext destctxCF = (DirContext)dirContext.lookup("cn=oracledbconnections");

    Lookup the db connection and create CF
    queueConnectionFact = (QueueConnectionFactory)destctxCF.lookup("cn=SCOTT");

    Hope this helps.

    ReplyDelete
  13. Actually, I'm able to succefully invoke till this step;
    DirContext connctx = (DirContext) inictx.lookup("cn=oracledbconnections");
    after that i couldn't retrieve the queue object ..it throws NPE;

    javax.naming.NamingException: problem generating object using object factory [Root exception is java.lang.NullPointerException]; remaining name 'cn=ratha.test'
    at com.sun.jndi.ldap.LdapCtx.c_lookup(LdapCtx.java:1070)
    at com.sun.jndi.toolkit.ctx.ComponentContext.p_lookup(ComponentContext.java:526)
    at com.sun.jndi.toolkit.ctx.PartialCompositeContext.lookup(PartialCompositeContext.java:159)
    at com.sun.jndi.toolkit.ctx.PartialCompositeContext.lookup(PartialCompositeContext.java:148)
    at OracleAQJNDIClient.get_Factory_from_LDAP(OracleAQJNDIClient.java:107)
    at OracleAQJNDIClient.main(OracleAQJNDIClient.java:155)
    Caused by: java.lang.NullPointerException
    at oracle.jms.AQjmsDestinationFactory.getObjectInstance(AQjmsDestinationFactory.java:120)
    at javax.naming.spi.DirectoryManager.getObjectInstance(DirectoryManager.java:176)
    at com.sun.jndi.ldap.LdapCtx.c_lookup(LdapCtx.java:1063)

    Should i look into any other settings?

    Thanks
    -ratha

    ReplyDelete
  14. Actually, I'm able to succefully invoke till this step;
    DirContext connctx = (DirContext) inictx.lookup("cn=oracledbconnections");
    after that i couldn't retrieve the queue object ..it throws NPE;

    javax.naming.NamingException: problem generating object using object factory [Root exception is java.lang.NullPointerException]; remaining name 'cn=ratha.test'
    at com.sun.jndi.ldap.LdapCtx.c_lookup(LdapCtx.java:1070)
    at com.sun.jndi.toolkit.ctx.ComponentContext.p_lookup(ComponentContext.java:526)
    at com.sun.jndi.toolkit.ctx.PartialCompositeContext.lookup(PartialCompositeContext.java:159)
    at com.sun.jndi.toolkit.ctx.PartialCompositeContext.lookup(PartialCompositeContext.java:148)
    at OracleAQJNDIClient.get_Factory_from_LDAP(OracleAQJNDIClient.java:107)
    at OracleAQJNDIClient.main(OracleAQJNDIClient.java:155)
    Caused by: java.lang.NullPointerException
    at oracle.jms.AQjmsDestinationFactory.getObjectInstance(AQjmsDestinationFactory.java:120)
    at javax.naming.spi.DirectoryManager.getObjectInstance(DirectoryManager.java:176)
    at com.sun.jndi.ldap.LdapCtx.c_lookup(LdapCtx.java:1063)

    Should i look into any other settings?

    Thanks
    -ratha

    ReplyDelete
  15. Hi,

    Did you lookup this cn=OracleDBQueues,cn=ORCL,cn=OracleContext,ou=Services,o=sgi,c=us

    instead of cn=OracleDBQueues


    thanks

    ReplyDelete
  16. Hi,
    Thanks for the help..I managed it..
    After adding "orcldbaqgeneric: maxretries=3", i'm able to connect to my queue..Not sure how that solved the issue..(i don't have any network issue..)
    BTW, your posts are really helpful..

    Rgds,
    -Ratha

    ReplyDelete
  17. Hi,

    Good to know it worked , maybe it is a DNS Issue and want to do a reverse lookup or in the meanwhile want to validates the connection .

    Thanks

    ReplyDelete