2011-02-26 30 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