我將一個遺留Java應用程序遷移到Spring Boot時遇到了阻塞問題。具體而言,該應用程序使用Apache CXF進行SOAP Web服務,該服務具有從Oracle數據庫獲取數據的操作。我看到的問題是,只要JNDI查找嘗試通過Web服務,然後拋出以下異常:帶有Apache CXF和JNDI查找的嵌入式Tomcat的Spring Boot javax.naming.NameNotFoundException
名稱[java:comp/env/jdbc/myDataSource]未綁定到這個上下文。 無法找到[java:comp]。
NamingException的:javax.naming.NameNotFoundException:名稱 【JAVA:comp/env的/ JDBC/myDataSource]未在此上下文中的約束。無法找到[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=***
你的jndi設置在哪裏? – ndrone
爲什麼你需要一個嵌入式tomcat的JNDI?! –
我在我的文章中添加了更多詳細信息,請讓我知道這是否有助於回答您的問題,以及來自@ndrone的問題。 –