Exposing/Accessing JBoss JNDI Objects/Datasources From an External JVM

Problem:

You have some program that needs to access some data sources that are managed by JBoss and accessed via JNDI, but when you start that program, it can’t find that JNDI reference or you get a javax.naming.NoInitialContextException with the message “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”

Example:

Our company uses ATG Portal for our end customer. The ATG Portal + our additions (web aps – WAR’s) to the portal get assembled into an EAR file. The EAR file then is deployed onto JBoss, which contains the Tomcat engine to serve up web apps.

You can easily turn at data source into an ATG Component via their JTDataSource pattern by havning your component have a properties file that says…

$class=atg.nucleus.JNDIReference
JNDIName=java:WhateverDsJndiName

Now that means that ATG will query JBoss’s JNDI container to get connections from the JBoss connection pool manager for your datasource. Well how are these defined? Via JBoss *-ds.xml files!

You just make a MyNewWhatever-ds.xml (“-ds.xml” is important…) that looks like this…

NOTE: Your <jndi-name> must match the name after the colon for JNDIName property for your component. The “java:” part of the JNDIName refers to the scope context for that object. “Java” scoped JNDI components can NOT be seen outside the JVM!!!

Well ATG has a nice little tool to help you load data into your Repository (or just sanity check your repositories) called startSQLRepository. Unfortunately, this script brings up a dumbed down version of the ATG Platform without JBoss, which brings up the repositories, which hits the NewWhateverDsJTDatasource, which queries the JNDI for a connection/transaction manager……

ALARM!!! ERROR!!! EXPLOSIONS!!! It fails with the javax.naming.NoInitialContextException!!!

JBoss is our connection manager and JNDI container but startSQLRepository doesn’t use JBoss!!!

Oh no we’re screwed!!! Actually we’re not… read on…

Solution:

Well after much reading on JBoss and Redhat’s sites on JBoss JNDI naming service, I found that it’s not that hard to connect to JBoss’s JNDI from an external JVM.

There are 2 main ways you can connect to JBoss’s JNDI Context (see above as well)

  1. JNP (Java Network Programming)
  2. HTTP(S)

The JNDI can now be externalized via these two interfaces. Using JNP, we can create a socket connection to JBoss via the default 1099 port

Luckily JBoss has jar’ed up every-freaking-thing-you-need-in-the-world into a single client jar that your clients must have in their classpath:

# Located in the $JBOSS_HOME/client directory

jbossall-client.jar

You should also include any JDBC drivers for the databases you are connecting to in the client classpath as well.

Next, you pass 3 arguments to the client JVM…

  • For JNP Connection…
    • -Djava.naming.factory.initial=org.jboss.naming.NamingContextFactory
    • -Djava.naming.provider.url=jnp://server:1099
    • -Djava.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
  • For HTTP(S) Connection…
    • -Djava.naming.factory.initial=org.jboss.naming.HttpNamingContextFactory
    • -Djava.naming.provider.url=http://server:8080/invoker/JNDIFactory
    • -Djava.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces

NOTE: If you are doing this over SSL (HTTPS), be ready to deal with Secured Socket handshaking and certificates/etc.

NOTE: Make sure you check your user security information and ports/servlets in the http-invoker.sar. You may have to add extra parameters to pass principal (username & password) information onto the inoker servlet.

And we are done right? We run our client and…

ALARM!!! ERROR!!! EXPLOSIONS!!! It fails with the javax.naming.NameNotFoundException

What happened?!?! We forgot that data source in JBoss get added to the “java” naming context instead of the global context, and any “java” context object can’t be seen outside of the JVM.

So we need to “tell” the data source (via the -ds.xml file) that it shouldn’t use the java context by default, so just add <use-java-context>false</use-java-context> to your ds file and now your JNDI name will be added to the global context!!

And then they lived happily ever after…

The End

16 thoughts on “Exposing/Accessing JBoss JNDI Objects/Datasources From an External JVM

  1. Excellent article. Thanks. I have a question though – how can we add about the java:/TransactionManager to the global JNDI namespace?

  2. Good question. I didn’t know. I did some research around…

    The couple paragraphs at http://docs.jboss.org/jbossas/jboss4guide/r4/html/ch4.chapt.html#d0e9851 (section 4.2) talk about the TransactionPropogationContext (importer and exporter) that it’s a field in the org.jboss.ejb.plugins.jrmp.client.RemoteMethodInvocation class.

    I also saw this interesting point on an older javadoc API for TransactionManager (http://docs.huihoo.com/javadoc/jboss/3.2.7/j2ee/javax/transaction/TransactionManager.html)

    “User applications should not use this interface directly, but use UserTransaction insted if they need to do their own transaction management.”

    Don’t know if that helps. Good luck!

  3. Many many thanks your post clarified my understanding related to remotely exposining JNDI resources.

    keep up the good work
    merci!!

  4. Excellent article, wish I’d found it sooner!! We are using this technique to access an Oracle data source while running batch java (which is naturally outside the container). The problem we are having is that we have an XMLType field in the database, so we need the actual OracleConnection object in order to create a CLOB or XMLType to store in there. If running inside the container from MDB or web, no problems. However, if running in batch we can’t get the Oracle data types. The JNDI lookup works just fine, we get a java.sql.Connection. The problem is we can’t cast that to any Oracle data type. Inspecting the data source object in debug mode, we find that it evaluates to $Proxy1. Any thoughts on that? Thanks!

  5. Hi Jason, you can’t get a specific Oracle object because you are running in a different JVM; that’s why you only get a proxy.

    The good news is you don’t need it if you are using an oracle jdbc driver 10.2 or newer. To work with clobs/blobs, use:

    ResultSet rs = …
    byte[] myBlob = rs.getBytes(1);
    String myClob = rs.getString(2);

    or:

    Statement s = …
    byte[] myBlob = …
    s.setBytes(1, myBlob);
    String myClob = “This is my huge clob.”);
    s.setString(2, myClob);

    hope it helps,
    Vladimir

  6. Great post but what about having 2 datasources and use them at the same time? When I have two datasources I just can acceed the first one! I don’t know how to solve this…

  7. I guess I’m at a loss to understand the issue you are having… What specific situation are you referring to?

    On the outset, I would tell you to make sure that both of your datasource xml’s are using the global JNDI namespace. You should be able to connect to both…

  8. Hi!

    I solved my problem :)

    Let me explian you:
    I have two Datasources because I want to use two databases in the same class communicating one to each other.

    I solved the problem with a property in JBoss file: jbossts-properties.xml:

  9. this was VERY helpful – wanted to get this going for a while now and most documents i found never mentioned the attribute in the datasource config files. that was the piece i was missing!

    however, it does bring a conern to mind. now that this datasource is exposed, how can i restrict who can use it?

  10. i should have expanded… is HTTP communication the only way that you can secure access to the JNDI entry? JNP doesnt allow such a thing? it just feels like my datasources are living in the wild for anyone who could try to access (assuming firewalls allow ports to be used that is)

  11. Hats off to you .. Exact resolution of the problem and brilliant explanation.

    Thanks so much for sharing this information .

    Abdul Mohsin

  12. Excellent presentation, content, very creative diagrams.

    Out of may be several blogs oon jndi/jboss this blogs stands out !!

    Thanks for posting.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>