【问题标题】:Using a JNDI datasource created by another application with Tomcat将另一个应用程序创建的 JNDI 数据源与 Tomcat 一起使用
【发布时间】:2010-12-28 18:33:12
【问题描述】:

我的应用程序中有一个 .properties 文件,其中包含数据源属性。 我使用以下代码设置了对此数据源的 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);

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

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...

现在我想在另一个应用程序中使用这个数据源。但是,如果我执行与以前相同的查找,则找不到 myDataSource(而在 tomcat 中仍然存在以前的应用程序,并且 jndi 绑定是在侦听器的帮助下在启动时完成的)。

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

谢谢

【问题讨论】:

  • 如果您希望它在服务器范围内,则必须在 Server.xml 文件中进行设置。
  • 我认为 Tomcat 中一个 webapp 绑定的 JNDI 资源对其他 webapp 根本不可见。
  • 所以你有一个将在 tomcat 中运行的 web 应用程序,你不能使用 context.xml 或 web.xml?

标签: java tomcat jndi


【解决方案1】:

“本地”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" />

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

(*) 一些注释:

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

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

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

问候。

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

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

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

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

      【讨论】:

        【解决方案4】:

        JNDI 上下文对每个 webapp 都是私有的。在一个应用中创建的上下文不能被其他应用访问。

        尝试在GlobalNamingResources 中创建一个条目,并使用&lt;ResourceLink&gt; 在两个 web 应用程序中创建链接,看看它是否有效。

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

        【讨论】:

          【解决方案5】:

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

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

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

          【讨论】:

            猜你喜欢
            • 2011-11-22
            • 1970-01-01
            • 2013-04-10
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-08-20
            相关资源
            最近更新 更多