Почему JNDI возвращает DataSource с нулевым URI вместо ошибки поиска? - PullRequest
2 голосов
/ 26 февраля 2011

Я искал похожий вопрос, но нашел только похожие, такие как Godaddy JNDI Проблема --- Невозможно создать драйвер JDBC класса '' для URL-адреса соединения 'null' , который не отвечает на мой общийвопрос.

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

Я не спрашиваю, почему это не удалось или как это исправить.

Мой вопрос: почему не произошел сбой LOOKUP?

Почему при поиске был создан бесполезный BasicDataSource с нулевым URL-адресом?Есть ли лучший способ обнаружить, если имя JNDI «не существует», чем попытаться использовать его и посмотреть, не взорвется ли оно?Этот подход напоминает мне о том, как они тестируют мосты .

Я наконец укусил пулю и переместил кучу кода из необработанного кода JDBC в JNDI, и многие загадки все еще остаются.

Я бы хотел, по возможности, не снижать BasicDataSource, чтобы хотя бы сохранить иллюзию независимости базы данных.

TIA

Ответы [ 2 ]

4 голосов
/ 27 февраля 2011

Как я понимаю, JNDI предназначен для хранения ссылок на объекты или объектов фабрики .

Объект дело простое - configurer предоставляет ссылку на объект, приложение использует его, так просто. Но для более сложных или общих случаев удобнее предоставить ссылку на фабрику объектов , которая дает гораздо больше свободы при создании объектов.

Так как вы не опубликовали web.xml своего веб-приложения или conf/server.xml Tomcat, сложно еще что-то уточнить, но я думаю, у вас есть что-то подобное в вашем 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 выше . В строке 112 вы можете видеть, что если задано res-type равно javax.sql.DataSource, оно использует org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory для создания нового источника данных.

Вот и все. На данный момент работа JNDI завершена, поскольку она не имеет никакого влияния на то, как создаются объекты - и это справедливо! Не забывайте, что JNDI предназначен для хранения ссылок на любые объекты (почтовые соединения, области безопасности и т. Д.). Было бы невозможно и неразумно написать тест для каждого другого типа объекта. И даже в этом случае, просто имея настройки базы данных, было бы невозможно определить, достаточно ли их для установления реального соединения с реальной базой данных.

Вот почему у вас есть отдельный вызов, datasource.getConnection(), и поэтому он выбрасывает SQLException, который вы должны ловить и обрабатывать.

p.s. Вы могли бы поспорить, что BasicDataSourceFactory должен быть более умным и иметь список обязательных свойств / аргументов. Может быть. Но это вопрос другого вопроса, как вы изначально задали , почему LOOKUP не сработал ;)

1 голос
/ 25 марта 2014

При запуске файла war на tomcat, web.xml и server.xml будут работать вместе, чтобы дать вам определения, как описано здесь.Иногда в Eclipse вы можете использовать файл web.xml, отличный от вашего.Убедитесь, что отладчик в Eclipse загружает ожидаемые файлы web и server.xml.В моем случае я обнаружил, что в файле web.xml нет определения, поэтому добавил его туда, и это сработало.

...