Bind JNDI datasource in tomcat?

2019-02-23 00:29发布

问题:

Is it possible to bind programatically a DataSource to Tomcat's 6 JNDI?

I want to create a DataSource on the fly and then make it available through JNDI ( to ColdFusion for instance ).

This is what I have:

public void bindToConext(DataSource dataSource) throws NamingException, SQLException {
    Context initContext = new InitialContext();
    Context envContext  = (Context)initContext.lookup("java:/comp/env");
    envContext.bind("jdbc/mydatasource", dataSource);
}

But I'm getting this exception:

javax.naming.OperationNotSupportedException: Context is read only

Is there a work around?

回答1:

Well it was not possible because tomcat's context becomes read-only after startup.

So what we did was to use SimpleJNDI which is a in memory context ( more like a glorified HashMap ) and that worked for us.

It needs a jndi.properties file that has to be in the classpath and where you define the directory where to look for resources and the initial context factory

java.naming.factory.initial=org.osjava.sj.SimpleContextFactory
org.osjava.sj.root=some/relative/path
org.osjava.jndi.delimiter=/
org.osjava.sj.jndi.shared=true

To make the binding with ColdFusion first we create the data source programatically and then bind it to the context:

DataSource ds = ...
Context c = new InitialContext();
c.bind( "jdbc/my/blah/"+var , ds );
...

Then using CF admin api we create a CF datasource of type JNDI just using the jndiname



回答2:

Tomcat's working context is java:comp/env. This context is read-only. But you can create your own contexts, using Tomcat's JNDI Implementation, as long as you keep yourself out of "java:comp/env".

Context ctx = new InitialContext()
ctx.createSubcontext("any_name").createSubcontext("any_sub_name");
ctx.bind("any_name/any_sub_name/myDataSource", myDataSource);

By default Tomcat's contexts are shared, so the DataSource is retrievable from anywhere in your app this way:

Context ctx = new InitialContext()
DataSource ds = (DataSource)ctx.lookup("any_name/any_sub_name/myDataSource");