Почему jrunscript не учитывает мой путь к классам?

Я пытаюсь получить доступ к JDBC из JavaScript, используя Rhino, включенный в Java 6. Но я не могу заставить DriverManager найти Driver, который я хочу использовать.

Эти два примера должны быть эквивалентны:

Ява:

public class DbTest {
    public static void main(String[] argv) {
        java.sql.Connection c = null;
        try {
            java.lang.Class.forName("net.sourceforge.jtds.jdbc.Driver");
            c = java.sql.DriverManager.getConnection(
                "jdbc:jtds:sqlserver://myserver/mydb", "user", "password");
        }
        catch (Exception e) {
            c = null;
            System.out.println(e);
        };

        if(c != null) {
           System.out.println("yay, got c!");
           try {
               c.close();
           }
           catch(Exception e) {}
        } else {
           System.out.println("awww.");
        }
    }
}

JavaScript:

importPackage(Packages.net.sourceforge.jtds.jdbc);
java.lang.Class.forName('net.sourceforge.jtds.jdbc.Driver');
var c = null;
try {
    c = java.sql.DriverManager.getConnection(
        'jdbc:jtds:sqlserver://myserver/mydb', 'user', 'password');
}
catch (e) {
    c = null;
    println(e);
};

if(c) {
   println('yay, got c!');
   c.close();
} else {
   println('awww.');
}

... но когда я запускаю их, я получаю такое поведение:

Ява:

> java -cp .;jtds-1.2.5.jar DbTest
java.sql.SQLException: Unknown server host name 'myserver'.
awww.

Это здорово, ему удалось загрузить драйвер и попытаться разрешить сервер.

JavaScript:

> jrunscript -cp .;jtds-1.2.5.jar dbtest.js
script error in file dbtest.js :
sun.org.mozilla.javascript.internal.WrappedException: 
Wrapped java.lang.ClassNotFoundException: 
net.sourceforge.jtds.jdbc.Driver (dbtest.js#2) in dbtest.js at line number 2

Почему не находит класс? Я пробовал с importPackage() и importClass() и без, с префиксом Packages и без него. Если я закомментирую forName, то DriverManager не найдет подходящего драйвера.


person clacke    schedule 28.07.2010    source источник
comment
Пробовал сейчас и в Linux, точно такое же поведение. Тоже пробовал запустить java -cp blabla com.sun.tools.script.shell.Main dbtest.js, без разницы.   -  person clacke    schedule 29.07.2010
comment
Подозрение, что это проблема безопасности и что механизм сценариев работает с использованием собственного загрузчика классов. Итак, вопрос в том, где это можно изменить. Пытался запустить Ant <script />, у которого есть атрибут classpath, очевидно, в интересах сценария. Тоже не работает.   -  person clacke    schedule 29.07.2010
comment
java -cp $JAVA_HOME/lib/tools.jar -Xbootclasspath:"$JAVA_HOME/jre/lib/rt.jar:$JAVA_HOME/jre/lib/resources.jar:jtds-1.2.5.jar" com.sun.tools.script.shell.Main dbtest.js работает. Но я хочу знать, почему ни jrunscript, ни <script />, похоже, не используют обычный путь к классам и какой из них они используют.   -  person clacke    schedule 29.07.2010


Ответы (1)


Согласно сообщение на форуме IBM DeveloperWorks, "значение jrunscript -classpath используется отдельным" скриптовым "загрузчиком классов, который параллелен обычному загрузчику классов приложения и используется для разрешения классов, упомянутых в importClass () и importPackage () ".

И согласно этот SO-ответ," ... DriverManager выполняет "задачи, используя экземпляр загрузчика класса непосредственного вызывающего объекта" ".

Итак, если вы не поместите jar-файл с драйвером в путь к загрузочному классу или не найдете способ изменить то, как jrunscript (и Ant <script />) устанавливают системный загрузчик классов среды сценария, единственный способ заставить это работать - полностью пропустить DriverManager:

var c = null;
try {
    var p = new java.util.Properties();
    p.setProperty('user', 'user');
    p.setProperty('password', 'password');
    c = (new net.sourceforge.jtds.jdbc.Driver()).connect(
             'jdbc:jtds:sqlserver://myserver/mydb', p);
}
catch (e) {
    c = null;
    println(e);
};

if(c) {
   println('yay, got c!');
   c.close();
} else {
   println('awww.');
}

Он удаляет один уровень косвенного обращения, который может быть или не быть одной чашкой чая, но он работает (со вставленным реальным сервером / пользователем / паролем):

$ jrunscript -cp jtds-1.2.5.jar dbtest_realparams.js 
yay, got c!
person clacke    schedule 29.07.2010