GenerationJava.com's Simple-JNDI

Simple-JNDI is intended to solve two problems. The first is that of finding a container independent way of opening a database connection, the second is to find a good way of specifying application configurations.

In a J2EE container, you can use JNDI as a java.sql.Connection factory. This code however is not usable outside of a J2EE container as you cannot guarentee you have a JNDI implementation available, and to be honest, you don't want to start some other server to make your simple script run. Simple-JNDI is not a server, it is merely an API, however it looks exactly the same as the JNDI client code used in a J2EE container.

Applications need configuration. A servlets container uses the web.xml files to configure, while a J2EE container uses a different system, for example, JBoss has a jboss.jcml configuration file which sets a system up via JMX managed beans. An application could however use Simple-JNDI for parameter values.

Using Simple-JNDI

Using Simple-JNDI is the same as using JNDI itself. So this is not covered here.

Installing Simple-JNDI

Installing Simple-JNDI is as simple as adding the simple-jndi jar, jdbc 2.0 jar and the commons-lang jar to your classpath.

Setting up Simple-JNDI

This is where all the work goes in a Simple-JNDI implementation. Firstly you need a jndi.properties file, which somehow needs to go into your classpath. This jndi.properties needs two values:

java.naming.factory.initial=com.generationjava.jndi.PropertiesFactory com.generationjava.jndi.root=/home/hen/gj/simple-jndi/config/

The first property is a part of the jndi specification, java.naming.factory.initial. This should be set equal to com.generationjava.jndi.PropertiesFactory.

The second property is simple-jndi specific, com.generationjava.jndi.root is set to a directory containing all the jndi values for this application.

Simple-JNDI's values

Simple-JNDI stores values in multiple .properties files and are looked up using a dotted name convention. There is also a special flag to specify whether a .properties file is a DataSource or not. Following are some examples.

Examples

Imagine a file-structure looking like,

config/

config/debug.properties

config/ProductionDS.properties

config/application1/default.properties

config/application1/ds.properties

config/application1/users.properties

in which the files look like;

default.properties
name=Prototype url=http://www.generationjava.com/
debug.properties
state=ERROR
ProductionDS.properties
com.generationjava.jndi.datasource=true

driver=org.gjt.mm.mysql.Driver

url=jdbc:mysql://localhost/testdb

user=testuser

password=testing
application1/default.properties
name=My Application

version=v3.4
application1/ds.properties
com.generationjava.jndi.datasource=true

TestDS.driver=org.gjt.mm.mysql.Driver

TestDS.url=jdbc:mysql://localhost/testdb

TestDS.user=testuser

TestDS.password=testing
application1/users.properties
admin=fred

customer=jim
The following pieces of Java are all legal ways in which to get values from Simple-JNDI. They assume they are preceded with a line of 'InitialContext ctxt = new InitialContext();'.
  • Object value = ctxt.lookup("debug.state")
  • Object value = ctxt.lookup("name")
  • Object value = ctxt.lookup("url")
  • Object value = ctxt.lookup("ProductionDS")
  • Object value = ctxt.lookup("application1.name")
  • Object value = ctxt.lookup("application1.TestDS")
  • Object value = ctxt.lookup("application1.users.admin")
Note that the ProductionDS and TestDS return types are objects of type javax.sql.DataSource.

FAQ

I get a ClassCastException with java.util.Properties.
Most likely you are trying to get a DataSource but you have forgotten to include com.generationjava.jndi.datasource=true.
I get an SQLException of 'No suitable driver'.
Your driver's jar is not in the classpath.
I get InvalidNameException of [key] not found.
You have not specified the com.generationjava.jndi.root correctly in your jndi.properties.
ClassNotFoundException: com.generationjava.jndi.PropertiesFactory.
You don't have the simple-jndi jar in the classpath.

Todo

  • Types. com.foo.Value can have a partner key of com.foo.Value.type which specifies the type of object to use for the key.
  • Implement binding so that values may be stored in the system, making it Read/Write.
  • Implementing the list methods so you can see the values in a particular directory/properties file.
  • Searches. Consider implementing DirContext.
  • Switch to using Names in the system, with the String argument being turned to a Name based on delimiters specified in the jndi.properties.