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.