2017-08-17 75 views
1

我將一個遺留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=*** 
+0

你的jndi設置在哪裏? – ndrone

+0

爲什麼你需要一個嵌入式tomcat的JNDI?! –

+0

我在我的文章中添加了更多詳細信息,請讓我知道這是否有助於回答您的問題,以及來自@ndrone的問題。 –

回答

0

我不確定爲什麼直接的JNDI查找在Apache CXF SOAP Web服務調用的上下文中執行失敗。但是,使用JndiObjectFactoryBean bean完成的查找工作正常,所以這就是我要運行的。

相關問題