2016-01-15 2 views
3

Когда драйвер Informix JDBC присутствует в моем пути к классам, он, похоже, перехватывает и отклоняет все строки подключения, прежде чем соответствующий драйвер получит шанс.Почему драйвер Informix JDBC обрабатывает несвязанные строки подключения?

Например, полностью нонсенс строка соединения, как jdbc:ghmghmghm приведет к следующей трассировки стека:

java.sql.SQLException: Invalid sub-protocol Invalid sub-protocol: 'ghmghmghm' 
    at com.informix.util.IfxErrMsg.getLocSQLException(IfxErrMsg.java:493) 
    at com.informix.jdbc.IfxDriver.checkURL(IfxDriver.java:560) 
    at com.informix.jdbc.IfxDriver.connect(IfxDriver.java:208) 
    at java.sql.DriverManager.getConnection(DriverManager.java:664) 
    at java.sql.DriverManager.getConnection(DriverManager.java:208) 

Мое понимание, что хорошо вели себя драйверы JDBC ограничивают себя соединения строк, которые начинаются с их волшебной приставкой. Является ли драйвер Informix сломанным, или у меня есть необоснованные ожидания?

Update

Если удалить только драйвера Informix, но оставить все другие водители на месте, исключение переворачивается на гораздо более здравомыслящий

java.sql.SQLException: No suitable driver found for jdbc:ghmghmghm 
    at java.sql.DriverManager.getConnection(DriverManager.java:596) 
    at java.sql.DriverManager.getConnection(DriverManager.java:187) 

Кроме того, существует конкретная допустимая строка подключения jdbc:sybase:Tds:leeta:5001/leeta_ase1, который будет работать, если драйвер Informix будет удален, но будет поврежден (Informix недопустимая трассировка стека подпротоков), если Informix присутствует.

Мой вывод заключается в том, что Informix не отвергая полностью строк подключения несовпадающих правильно, и что Informix получает первую трещину в строках подключения Sybase (но не любой другой тип строки подключения я пробовал ...)

Мой Linux JDK является

java version "1.7.0_91" 
OpenJDK Runtime Environment (IcedTea 2.6.3) (7u91-2.6.3-0ubuntu0.14.04.1) 
OpenJDK 64-Bit Server VM (build 24.91-b01, mixed mode) 

, но я видел плохие строки подключения приводит к трассировке Infx на официальном Java 8 на Windows, а также. Никогда еще не видел, чтобы Sybase перехватывала Windows, но, возможно, это проблема упорядочения классов.

Update 2

Я не могу Репрографический мое утверждение, что полностью действительные строки соединения были перехвачены и отвергнуты Informix. Я, должно быть, стараюсь делать тонкие строки, смотря на стек Informix, удаляя драйвер Informix в ответ, а затем рассматривая стек из правильного драйвера, чтобы выиграть (поскольку это позволило быстро восстановить строку соединения).

Я вижу несколько способов улучшить положение вещей:

  • прекратить использование DriverManager всякий раз, когда класс драйвера известно (экземпляр драйвера непосредственно и вызвать getConnection() на нем)
  • Написать замену DriverManager.getConnection(), что по крайней мере сообщает все стеки отказов через Throwable.addSuppressed()
  • Обезьяна с классом классов Java, чтобы попытаться сделать Informix (и другие плохие актеры) появляться позже в списке драйверов (за @jonathan-leffler)
  • Использование DriverManager.(de)registerDriver() для перемещения плохих актеров (как статический список или динамически во время выполнения испытания) в конце списка драйвера

Спасибо за все отзывы!

+1

Какие еще драйверы JDBC находятся на пути к вашему классу? Пробовали ли вы распечатать содержимое системной опоры 'jdbc.drivers'? –

+1

Можете ли вы позволить себе, чтобы драйвер Informix был последним в вашем списке? Можете ли вы убедиться, что это последнее? Будет ли это достаточным временным решением? –

+0

Вы также протестировали это с помощью реальных строк соединения? Поскольку потенциальная причина сбоя 'jdbc: ghmghmghm' может быть проблемой синтаксического анализа, поскольку JDBC указывает, что url должен быть' jdbc: : <конкретная часть драйвера> 'и' jdbc: ghmghmghm' не выполняет это требование;) –

ответ

4

Это звучит как ошибка в драйвере Informix (но в лучшем случае несовершеннолетнего). Хорошо себя драйвер JDBC требуется следовать ожиданиям, определенные в java.sql.Driver.connect(String url, Properties properties) (курсив мой):

попытки сделать подключение к базе данного URL. Водитель должен возвращать «null», если он понимает, что это неправильный тип драйвера для . Соедините с заданным URL. Это будет распространено, так как когда диспетчеру JDBC попросят подключиться к данному URL, он передает URL-адрес каждому загруженному драйверу .

Водитель должен бросить SQLException, если это правильный драйвер для подключения к данному URL, но имеет проблемы с подключением к базе данных.

java.sql.DriverManager.getConnection будет запрашивать метод connect всех зарегистрированных драйверов один за другим. Если драйвер вернется null, он будет продолжен со следующим драйвером. Если драйвер возвращает соединение, это соединение возвращается вызывающему. Если все драйверы возвращаются null, тогда SQLException бросается с «Не найдено подходящего драйвера для [url]».

Если водитель выбрасывает SQLException, последнее исключенное исключение сохраняется, а диспетчер драйверов продолжит работу со следующим драйвером.Если все остальные драйверы отклонят попытку подключения с помощью null, то вместо исключения будет исключено последнее исключение «Нет подходящего драйвера ...» исключение. Насколько я знаю в старых версиях Java, это фактически остановит попытки других драйверов. Но код DriverManager (по крайней мере, с Oracle/Sun Java 5) защищает от этого и предотвращает неправильное использование драйверов от монополизации JDBC и позволяет использовать несколько драйверов для одной и той же базы данных (и протокола).

Итак, если ваша версия Java не имеет другой версии DriverManager (которая останавливается при первом исключении), она должна продолжаться с другими зарегистрированными драйверами, и если какой-либо из них принимает URL-адрес, тогда проблем не должно быть.

0

Согласно DriverManager документу:

В рамках своей инициализации класса DriverManager будет пытаться загрузить классы драйверов, на которые ссылается «jdbc.drivers» системного свойства. Это позволяет пользователю настраивать драйверы JDBC, используемые их приложениями. Например, в вашем ~/.hotjava/свойства файла можно указать:

jdbc.drivers=foo.bah.Driver:wombat.sql.Driver:bad.taste.ourDriver

Итак, у вас есть 3 JDBC драйверов, например, что ваш jdbc.drivers свойство выглядит следующим образом:

jdbc.drivers=com.DriverA:com.DriverB:com.DriverC 

Если вы вызываете DriverManager.getConnection("jdbc:driverA:blahblah");, то DriverManager не знает, какой драйвер в свойстве jdbc.drivers использовать, поэтому он должен перебирать все из них.

DriverManager.getConnection(), вероятно, делает что-то похожее на это:

public Connection getConnection(String url) { 

    Set<Driver> drivers = // drivers in 'jdbc.drivers' prop 

    SQLException failure = null; 

    for(Driver driver : drivers) { 
     try { 
      Connection conn = driver.connect(url); 
      if(conn != null) 
       return conn; 
     } catch (SQLException sqle) { 
      // potentially not trying to connect to the right driver 
      if(failure == null) 
       failure = sqle; 
     } 
    } 

    // If we get here, no drivers could connect 
    if(failure != null) 
     throw failure; 
    else // no connection obtained, but no drivers complained 
     throw new SQLException("No driver found for URL " + url); 
} 

UPDATE: (образец кода был обновлен)

Оказывается, что OpenJDK терпит сценарий, в котором Драйвер возвращает null для протокола, который он не распознает, а также допускает сценарий, в котором драйвер выдает исключение для протокола, который он не распознает.

Я бы сказал, что OpenJDK никогда не должен генерировать исключение, которое поступает непосредственно из Драйвера, и всегда бросать новое SQLException, если для URL-адреса не найдено ни одного драйвера.

+0

Итак, если я понимаю вас, любая строка соединения, которая не работает в * подходящем * драйвере, может привести к стеку из несвязанного драйвера, потому что он был последним? – Raven

+0

Потенциально. Я уверен, что надежный JDK справится с этим разумным способом. Похоже, что OpenJDK 6, например, бросает первый сбой, который он видит (при условии, что все попытки подключения терпят неудачу) –

+0

Я провел некоторое тестирование этой теории и обновил свой вопрос; Я думаю, что мои результаты подтверждают, что Informix имеет проблемы. – Raven

1

Проблема устранена в последней версии драйвера JDBC версии Informix (JDBC.4.10.JC8DE).

+0

Печально новый драйвер также ломает LOB-поддержку, но я думаю, вы не можете иметь все. – Raven