使用由Tomcat创建的另一个应用程序创建的JNDI数据源

时间:2009-12-21 14:54:12

标签: java tomcat jndi

我的应用程序中有一个包含dataSource属性的.properties文件。 我使用以下代码设置了对此dataSource的JNDI引用:

// first I create MyDataSource from the properties found in the .properties file
//then :

Context initContext = new InitialContext();
initContext.createSubcontext("jdbc");
initContext.createSubcontext("jdbc/oracle");
initContext.rebind(jdbc/oracle/myDataSource, MyDataSource);

如果我在此应用程序中使用查找,则会找到dataSource:

Context initContext = new InitialContext();
BasicDataSource dataSource = 
            (BasicDataSource) initContext.lookup("jdbc/oracle/myDataSource")
//everything works fine and I can use my dataSource to getConnection,
//requests, etc...

现在我想在另一个应用程序中使用此dataSource。但是,如果我执行相同的查找,我找不到myDataSource(而在tomcat中仍然存在以前的应用程序,并且在启动时通过侦听器完成jndi绑定)。

我如何在第二个应用程序中获取myDataSource,因为我不能在server.xml或context.xml文件中使用Tomcat的资源(出于不同的原因,我必须使用这个.properties文件)?

由于

5 个答案:

答案 0 :(得分:2)

“本地”JDNI目录在Tomcat中是只读的。不过,您可以在LifecycleListener中绑定“全局”JNDI资源,然后将它们“链接”到您的上下文(*):

您需要实现org.apache.catalina.LifecycleListener http://tomcat.apache.org/tomcat-6.0-doc/api/org/apache/catalina/LifecycleListener.html

然后将其注册到您的server.xml中(与其他侦听器一起):

<Listener className="yourlistener.YourLifecycleListener"/>

你的听众应该等待2个事件:

public void lifecycleEvent(final LifecycleEvent event) {

    if (Lifecycle.START_EVENT.equals(event.getType())) {
      // Create your datasource instance...
      Context initContext = new InitialContext();
              initContext.createSubcontext("jdbc");
              initContext.createSubcontext("jdbc/oracle");
              initContext.rebind("jdbc/oracle/myDataSource", myDataSource);
    } else if (Lifecycle.STOP_EVENT.equals(event.getType())) {
      // unbind...
    }
}

然后,您必须通过使用META-INF / context.xml中的ResourceLink元素将它们从“全局”JNDI目录“链接”到“本地”JNDI目录来传播资源访问:

<ResourceLink name="jdbc/oracle/myDataSource" global="jdbc/oracle/myDataSource"
    type="javax.sql.DataSource" />

到目前为止,这对我有用。

(*)有些注意事项:

使用生命周期监听器有一个优势。由于不保证上下文创建的顺序。优点是你的所有上下文都会看到这个对象被创建。

如果您需要在生命周期监听器创建时更加动态地创建和配置数据源创建,请注意您可以绑定实现Factory模式的自定义类。

为避免类加载不兼容问题,请考虑将监听器,数据源等类放在Tomcat lib目录中的jar文件中,以便它们包含在公共类加载器中。

问候。

答案 1 :(得分:1)

你想做的事情是行不通的。 J2EE应用程序不允许修改应用程序服务器(J2EE规范,第5.2.2节)和Tomcat JNDI documentation也提供的JNDI环境,每个Web应用程序都获得每个自己的只读JNDI环境。我不确定为什么绑定/重新绑定您的数据源不会立即失败以及为什么它在同一个Web应用程序中工作,但即使是JNDI环境的这种应用程序内部使用也是未记录的行为,我不会依赖它。

答案 2 :(得分:0)

有几个人已对此发表评论,但我认为您的问题的答案是:Tomcat有一个名为server.xml的文件,您需要使用它。我之前使用过的一个很好的参考资料如下:

http://tomcat.apache.org/tomcat-5.5-doc/jndi-resources-howto.html

此处定义的资源将对所有部署的应用程序可见(如果设置正确)。如果您在应用程序上下文或Web xml文件中设置了JNDI资源,则该应用程序只能使用该资源。

答案 3 :(得分:0)

JNDI上下文对每个webapp都是私有的。其他人无法访问在一个应用程序中创建的上下文。

尝试在GlobalNamingResources中创建一个条目,并使用<ResourceLink>在两个webapps中进行链接,看看它是否有效。

我之前使用此设置从两个应用程序中读取但从未尝试过从一个应用程序写入。所以不确定它是否会起作用。

答案 4 :(得分:0)

实际上,如果servlet实现 org.apache.catalina.ContainerServlet ,则可以访问其他JNDI资源。此接口具有org.apache.catalina.Wrapper属性,该属性由容器本身“填充”。

通过它,我创建了一个监视资源的简单应用程序。

但是,我想在监听器中执行此操作,因此我的资源监视器可以在容器启动时启动。有人知道吗?