2011-02-26 37 views
2

我查找了一個類似的問題,但只找到類似的問題,如Godaddy JNDI Problem---Cannot create JDBC driver of class '' for connect URL 'null',它不回答我的通用問題。爲什麼JNDI返回一個帶有NULL URI的數據源而不是查找失敗?

的Tomcat 7.0.8 ..以下代碼

Context initialContext = new InitialContext(); 
datasource = (DataSource) initialContext.lookup("java:comp/env/" + "blah"); 
Connection c = null; 
c = datasource.getConnection(); 

引發此錯誤。

org.apache.tomcat.dbcp.dbcp.SQLNestedException: Cannot create JDBC driver of class '' for connect URL 'null' 
    at org.apache.tomcat.dbcp.dbcp.BasicDataSource.createConnectionFactory(BasicDataSource.java:1452) 
    at org.apache.tomcat.dbcp.dbcp.BasicDataSource.createDataSource(BasicDataSource.java:1371) 
    at org.apache.tomcat.dbcp.dbcp.BasicDataSource.getConnection(BasicDataSource.java:1044) 
... 
Caused by: java.lang.NullPointerException 
    at sun.jdbc.odbc.JdbcOdbcDriver.getProtocol(JdbcOdbcDriver.java:527) 
    at sun.jdbc.odbc.JdbcOdbcDriver.knownURL(JdbcOdbcDriver.java:496) 
    at sun.jdbc.odbc.JdbcOdbcDriver.acceptsURL(JdbcOdbcDriver.java:319) 
    at java.sql.DriverManager.getDriver(DriverManager.java:386) 
    at org.apache.tomcat.dbcp.dbcp.BasicDataSource.createConnectionFactory(BasicDataSource.java:1437) 
    ... 24 more 

我不是問爲什麼它失敗或如何解決它。

我的問題是,爲什麼沒有查找失敗?

爲什麼查找創建一個空的URL無用的BasicDataSource?有沒有更好的方法來檢測JNDI名稱是否「不存在」,而不是嘗試使用它並查看它是否炸燬?這種方法讓我想起了how they test bridges

我終於忍辱負重,移動一串代碼從原始JDBC代碼,JNDI,和許多奧祕仍然存在。

我想避免向下類型轉換的BasicDataSource如果可能的話,至少保持數據庫的獨立性的錯覺。

TIA

+0

人不能丟掉幻想應對... – Chucky 2015-09-28 11:28:37

+0

@Chucky你是什麼意思? – 2015-09-29 17:35:13

回答

4

據我瞭解JNDI,是指保持引用對象對象工廠

對象業務很簡單 - configurer提供對象的引用,應用程序使用它,就像那樣簡單。但對於更復雜或更通用的情況,提供對對象工廠的引用會更方便,因爲它可以更加自由地創建對象。

當你還沒有發佈你的webapp的web.xml也不Tomcat的conf/server.xml,很難更詳細地說明,但我猜你有類似的東西在你的web.xml

<resource-ref> 
    <description>DB Connection</description> 
    <res-ref-name>jdbc/myDB</res-ref-name> 
    <res-type>javax.sql.DataSource</res-type> 
    <res-auth>Container</res-auth> 
</resource-ref> 

如果你讀Tomcat's JNDI howto,你應該看到這一點:

提供Tomcat是能夠識別適當的資源工廠用來 創建資源,並且不需要進一步的配置信息,Tomcat的 將使用/WEB-INF/web.xml中的信息來創建資源。

現在,讓我們看看Tomcat's implementation of the above。在112行,你可以看到,如果給出res-type等於javax.sql.DataSource,它使用org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory創建一個新的數據源。

就是這樣。在這一點上,JNDI的工作已經結束了,因爲它對於如何創建對象沒有影響 - 正確的做法!不要忘記,JNDI意味着存儲對任何類型對象(郵件連接,安全領域等)的引用。爲每種不同類型的對象編寫測試都是不可能的也是不合理的。即便如此,僅僅通過數據庫設置就無法確定這些數據是否足以建立與真實數據庫的實時連接。

這就是爲什麼你有一個單獨的電話,datasource.getConnection(),這就是爲什麼它拋出SQLException,你應該趕上和處理。

p.s.你可能認爲BasicDataSourceFactory應該更聰明和有強制屬性/參數列表。也許。但是,這是受另外一個問題,原來你問爲什麼沒有查找失敗;)

+0

謝謝,我覺得我的理解更好一點。我沒有發佈conf/server.xml,因爲我的問題不是,「我該如何做這項工作」。但是,我有一個類似的資源引用在我的web.xml中,並沒有匹配參考。 (也許我應該問的問題是,「我怎麼檢測,當用戶沒有提供一個實體?」 這聽起來像是回答我的問題是,查找沒有失敗,因爲它找到了<資源-REF>對象,但返回的數據源具有空URI,因爲沒有被發現。 – 2011-02-28 20:08:15

+0

重讀JNDI HOWTO,資源和資源引用是基本相當。所以,我的查找()成功是因爲我有一個資源 - 你最後的評論,正是我應該問的:「爲什麼不是BasicDataSourceFactory ...更聰明,並有一個強制屬性/參數列表」。所以,我認爲你已經回答了我的問題。 – 2011-02-28 20:25:47

+1

作爲一個側面說明,我想我會選擇其他數據源工廠(如C3P0)我的下一個項目作爲我不會(不是因爲JNDI,但由於其他原因)DBCP非常高興。不幸的是,用其他方法替換底層庫並不那麼簡單,需要進行大量的測試,並且測試邊緣案例特別困難。 – mindas 2011-02-28 21:57:56

1

當運行Tomcat上war文件,web.xml和server.xml中將攜手給你在這裏描述的定義。有時,在Eclipse中,您可能會使用與您想象的不同的web.xml。確保Eclipse中的調試器正在加載您期望的web和server.xml文件。我發現在我的情況下,web.xml沒有定義,所以添加它,這工作。

+0

這是一個真實的陳述,但它是(1)更多評論而不是答案(所以應該作爲評論輸入),但(2)不回答我的問題。正如我在3年前的其他主題中所提到的,我並沒有問如何讓我的應用程序工作,而是詢問JDNI行爲。感謝您嘗試回答並歡迎SO! – 2014-04-01 01:33:01