【问题标题】:Spring Boot with embedded Tomcat with Apache CXF and JNDI lookup javax.naming.NameNotFoundException带有 Apache CXF 和 JNDI 查找 javax.naming.NameNotFoundException 的嵌入式 Tomcat 的 Spring Boot
【发布时间】:2018-01-26 09:57:49
【问题描述】:

我在将遗留 Java 应用程序迁移到 Spring Boot 时遇到了障碍。具体来说,该应用程序将 Apache CXF 用于具有从 Oracle 数据库获取数据的操作的 SOAP Web 服务。我看到的问题是,只要 Web 服务尝试进行 JNDI 查找,就会引发以下异常:

名称 [java:comp/env/jdbc/myDataSource] 未绑定在此上下文中。 找不到 [java:comp]。

命名异常:javax.naming.NameNotFoundException:名称 [java:comp/env/jdbc/myDataSource] 未绑定在此上下文中。无法 找到 [java:comp]。

作为参考,我在这里查看了一个问题示例: https://github.com/pmercer/spring-boot-sample-tomcat-jndi-cxf-ws

因此,如果有人可以为我指出一个可行的示例和/或提供解决问题的建议,那么将不胜感激。

添加更多细节...

这是在现有应用程序中执行查找的方式,该应用程序作为 .war 文件部署在外部 Tomcat 服务器上...

/**
 * Returns a database connection for the specified datasource
 * @param db - ex. "jdbc/DatasourceXyz"
 * @return db Connection
 * @throws Exception
 */
public static Connection getDbConnection(String db) throws Exception {
    java.sql.Connection conn = null;

    try {
        LOG.debug("getting db connection for " + db + " ...");

        javax.naming.Context initCtx = new javax.naming.InitialContext();
        javax.naming.Context envCtx = (javax.naming.Context) initCtx.lookup("java:comp/env");
        javax.sql.DataSource ds = (javax.sql.DataSource) envCtx.lookup(db);
        conn = ds.getConnection();

        initCtx.close();
        LOG.debug("got db connection for " + db);
        LOG.debug("url = " + conn.getMetaData().getURL());

    } catch (Exception e) {
        String message = String.format("Exception thrown while creating a JDBC connection for %s: %s", db,
                e.getMessage());
        throw new Exception(message);
    }

    return conn;
}

并且数据库属性存储在Tomcat服务器的context.xml文件中……

<Context>
<WatchedResource>WEB-INF/web.xml</WatchedResource>
<WatchedResource>${catalina.base}/conf/web.xml</WatchedResource>
<!-- environment-specific jdbc data sources: -->
<Resource name="jdbc/DatasourceXyz" auth="Container" type="javax.sql.DataSource" driverClassName="oracle.jdbc.OracleDriver" url="jdbc:oracle:thin:@hostname:1521:database" username="someUser" password="***" maxTotal="20" maxIdle="10" maxWaitMillis="60000"/>
<!-- set other jdbc data sources below: -->

此外,由于现有的 getDbConnection 方法调用很普遍,并且由于应用程序的数据库 CRUD 代码很广泛,因此我们的目标是让该代码保持原样。所以基本上我只需要能够创建数据库连接,就像这样......

public static Connection getDbConnection(String db) throws Exception {
    java.sql.Connection conn = null;

    try {
        LOG.debug("getting db connection for " + db + " ...");

        // Get the SampleUtilService from the Bridge
        SampleUtilService sampleUtilService = SpringContextBridge.services().getSampleUtilService();

        // Get DataSource from the JndiObjectFactoryBean
        javax.sql.DataSource ds = sampleUtilService.getDataSourcefromFactoryBean(db);

        conn = ds.getConnection();

        LOG.debug("got db connection for " + db);
        LOG.debug("url = " + conn.getMetaData().getURL());

    } catch (Exception e) {
        String message = String.format("Exception thrown while creating a JDBC connection for %s: %s", db,
                e.getMessage());
        throw new Exception(message);
    }

    return conn;
}

因此,借助 SpringContextBridge 功能并使用嵌入式 Tomcat 服务器配置 JNDI,正如我的示例项目的 README 中所述,基本上这就是我的计划。另外,由于我对 Spring Boot 还很陌生,我不确定这是否是最好的方法。

另外,在我最初的帖子之后做了一些额外的测试之后,我看到的问题似乎可能只是由将 JndiObjectFactoryBean.setLookupOnStartup 属性设置为 false 引起的,即,

    @Bean(destroyMethod="")
public DataSource jndiDataSource() throws IllegalArgumentException, NamingException {
    JndiObjectFactoryBean bean = new JndiObjectFactoryBean();
    bean.setJndiName("java:comp/env/jdbc/myDataSource");
    bean.setProxyInterface(DataSource.class);
    bean.setLookupOnStartup(false);
    bean.afterPropertiesSet();
    return (DataSource)bean.getObject();
}

当我将 bean 的 setLookupOnStartup 属性设置为 true 时,应用程序能够成功获得数据库连接。但是,当应用程序尝试通过 JNDI 进行查找时,我仍然看到问题,即,

        DataSource dataSource =
            (DataSource) new InitialContext().lookup("java:comp/env/jdbc/myDataSource");

所以,如果使用 bean 的附加测试证明是成功的,那么我可能会继续使用 bean 进行查找。另外,如果有更好的方法,我愿意提供建议。

另外,据我了解,数据源配置应该存储在应用程序的 application.properties 文件中...

jdbc.xyz.datasource.name=jdbc/DatasourceXyz
jdbc.xyz.datasource.driver=oracle.jdbc.OracleDriver
jdbc.xyz.datasource.url=jdbc:oracle:thin:@hostname:1521:database
jdbc.xyz.datasource.username=someUser
jdbc.xyz.datasource.password=***

【问题讨论】:

  • 你的 jndi 设置在哪里?
  • 为什么需要带有嵌入式 tomcat 的 JNDI?!
  • 我在帖子中添加了更多详细信息,如果这有助于回答您的问题以及@ndrone 之前的问题,请告诉我。
  • 是的,您将其设置为连接到java:comp/env/jdbc/myDataSource,但该定义或配置在哪里?在 WebSphere 中,它将存在于控制台中......它存在于嵌入式 tomcat 中的什么地方?
  • 在使用嵌入式 Tomcat 服务器的 Spring Boot 应用中,我的理解是数据源配置存储在应用的 application.properties 文件中。

标签: tomcat spring-boot cxf jndi


【解决方案1】:

我不确定为什么在 Apache CXF SOAP Web 服务调用的上下文中执行直接 JNDI 查找会失败。但是,使用 JndiObjectFactoryBean bean 完成的查找是有效的,所以这就是我要运行的。

【讨论】:

    猜你喜欢
    • 2015-04-18
    • 2018-08-08
    • 2015-03-23
    • 2019-06-30
    • 2014-07-23
    • 2018-01-05
    • 2016-08-19
    • 2016-01-07
    • 1970-01-01
    相关资源
    最近更新 更多