【发布时间】: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