带有嵌入式Tomcat的Spring Boot,带有Apache CXF和JNDI查找javax.naming.NameNotFoundException

时间:2017-08-17 20:24:10

标签: tomcat spring-boot cxf jndi

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

  

名称[java:comp / env / jdbc / myDataSource]未绑定在此Context中。   无法找到[java:comp]。

     

NamingException:javax.naming.NameNotFoundException:Name   [java:comp / env / jdbc / myDataSource]未绑定在此Context中。无法   找到[java:comp]。

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

所以,如果有人能指出一个有效的例子和/或提供解决问题的建议,那么我们将非常感激。

添加更多详情......

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

/**
 * 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=***

1 个答案:

答案 0 :(得分:0)

我不确定为什么在Apache CXF SOAP Web服务调用的上下文中执行直接JNDI查找失败。但是,使用JndiObjectFactoryBean bean完成的查找正在运行,因此我将使用它。