Путаница из -за разрешения класса в Oracle Java хранящихся процедурах
-
10-09-2019 - |
Вопрос
Я пытаюсь использовать стороннюю библиотеку Java в Oracle. Библиотека кажется совместимой с той же 1,4 версией JVM, что и наши хосты Oracle 10G Server, поскольку она работает нормально за пределами Oracle, поэтому я чувствую, что смогу заставить это работать. Эта библиотека в конечном итоге делает HTTP-запросы на основе SOAP, и я получаю ошибки разрешения класса, когда я работаю в Oracle.
Вот линия, которая показывает разницу:
Class msgfact = Class.forName("com.sun.xml.messaging.saaj.soap.MessageFactoryImpl");
Я попытался зарегистрировать эти библиотеки в Oracle с утилитой LoadJava, и я получил то, что, как я думал, было успешным результатом:
C:\>loadjava -verbose -schema MYUSER -user MYUSER/MYPWD@dbinstance -force saaj-impl.jar
Похоже, что все загружается, и я вижу этот класс MessageFactoryImpl в этом списке. Но затем я пытаюсь запустить эту строку кода из Oracle SQL (внутри другого класса, который я написал и загружен с помощью LoadJava), эта линия бросает ClassNotFoundException (java.lang.classnotfoundexception: com/sun/xml/message/saaj/soap/messagefactorimpl: com/sun/xml/saaj/soapfactoryimp )
Затем я вернулся и попытался добавить переключатель «-resolve» в командной строке LoadJava. Это действует так, как эти классы SAAJ зарегистрированы, но они не решаются должным образом.
Как я могу успешно получить эти классы SAAJ в Oracle, или если по какой -то причине Oracle уже загружен, как я могу убедить свой собственный код успешно использовать существующий класс?
FWIW, я уже предпринял шаги, чтобы убедиться, что соответствующие разрешения на сокет были предоставлены, и мой код может успешно сделать общий HTTP -запрос на целевой URL. У него просто есть проблемы с использованием мыла библиотеки, чтобы это произошло.
РЕДАКТИРОВАТЬ: Вот образец моего результата LoadJava. Похоже, что это показывает именно то, что терпит неудачу, но я не понимаю, почему эти конкретные классы не решаются, когда они, кажется, обрабатываются должным образом на шагах до разрешения. Я исключил около 80% файла здесь, но есть другие классы, которые показывают те же проблемы с разрешением класса.
arguments: '-verbose' '-schema' 'MYSCHEMA' '-user' 'MYSCHEMA/MYSCHEMA@actest' '-resolve' '-force' 'saaj-impl.jar' [snip] creating : class MYSCHEMA.com/sun/xml/messaging/saaj/soap/EnvelopeFactory loading : class MYSCHEMA.com/sun/xml/messaging/saaj/soap/EnvelopeFactory creating : class MYSCHEMA.com/sun/xml/messaging/saaj/soap/GifDataContentHandler loading : class MYSCHEMA.com/sun/xml/messaging/saaj/soap/GifDataContentHandler creating : class MYSCHEMA.com/sun/xml/messaging/saaj/soap/JpegDataContentHandler loading : class MYSCHEMA.com/sun/xml/messaging/saaj/soap/JpegDataContentHandler creating : class MYSCHEMA.com/sun/xml/messaging/saaj/soap/MessageFactoryImpl loading : class MYSCHEMA.com/sun/xml/messaging/saaj/soap/MessageFactoryImpl creating : class MYSCHEMA.com/sun/xml/messaging/saaj/soap/MessageImpl loading : class MYSCHEMA.com/sun/xml/messaging/saaj/soap/MessageImpl [snip] resolving: class MYSCHEMA.com/sun/xml/messaging/saaj/soap/AttachmentPartImpl resolving: class MYSCHEMA.com/sun/xml/messaging/saaj/soap/Envelope resolving: class MYSCHEMA.com/sun/xml/messaging/saaj/soap/EnvelopeFactory errors : class MYSCHEMA.com/sun/xml/messaging/saaj/soap/EnvelopeFactory ORA-29534: referenced object MYSCHEMA.com/sun/xml/messaging/saaj/soap/SOAPPartImpl could not be resolved resolving: class MYSCHEMA.com/sun/xml/messaging/saaj/soap/GifDataContentHandler resolving: class MYSCHEMA.com/sun/xml/messaging/saaj/soap/JpegDataContentHandler resolving: class MYSCHEMA.com/sun/xml/messaging/saaj/soap/MessageFactoryImpl errors : class MYSCHEMA.com/sun/xml/messaging/saaj/soap/MessageFactoryImpl ORA-29534: referenced object MYSCHEMA.com/sun/xml/messaging/saaj/soap/MessageImpl could not be resolved errors : class MYSCHEMA.com/sun/xml/messaging/saaj/soap/MessageImpl ORA-29534: referenced object MYSCHEMA.com/sun/xml/messaging/saaj/soap/impl/EnvelopeImpl could not be resolved errors : class MYSCHEMA.com/sun/xml/messaging/saaj/soap/MessageImpl$1 ORA-29534: referenced object MYSCHEMA.com/sun/xml/messaging/saaj/soap/MessageImpl could not be resolved skipping : class MYSCHEMA.com/sun/xml/messaging/saaj/soap/MessageImpl$2 [snip] The following operations failed class MYSCHEMA.com/sun/xml/messaging/saaj/soap/EnvelopeFactory: resolution class MYSCHEMA.com/sun/xml/messaging/saaj/soap/MessageFactoryImpl: resolution class MYSCHEMA.com/sun/xml/messaging/saaj/soap/MessageImpl: resolution class MYSCHEMA.com/sun/xml/messaging/saaj/soap/MessageImpl$1: resolution [snip] exiting : Failures occurred during processing
Решение
Прежде всего, проверьте за пределами Oracle, что класс, который вы ищете, на самом деле находится в этом файле JAR. Я ожидаю, что это так, но не повредит проверить.
Затем я бы проверил, какие классы были загружены и есть ли у них действительные статусы.
SELECT object_name, dbms_java.longname(object_name), status
FROM user_objects
WHERE object_type='JAVA CLASS'
ORDER BY 1
Вы можете немного ограничить это, если есть много занятий, например:
WHERE dbms_java.longname(object_name) LIKE '%MessageFactoryImpl'
Если класса там нет, или его там с неправильным именем пакета, то проблема заключается в команде LoadJava.
Если класс есть, но его статус недействителен, проверьте user_errors, чтобы увидеть, каковы ошибки. Я не помню, если бы я сделал динамическую загрузку класса в Oracle, но я помню, что статическое связывание дало бы ошибки, которые подразумевают, что класс не существует, когда он действительно существовал, но имел ошибки.
Новая информация после вывода LoadJava опубликовано
Выход LoadJava кажется непоследовательной с вашей попыткой найти класс в базе данных. Если он загружается, но не решается, его все равно следует перечислить, но с неверным статусом.
Я получил банку и сам попробовал ее в пустой схеме. Класс загружается, но является недействительным, как и ожидалось:
dev> select object_name, dbms_java.longname(object_name),status
2 from user_objects
3 where object_name like '%MessageFactoryImpl';
OBJECT_NAME
--------------------------------------------------------------------------------
DBMS_JAVA.LONGNAME(OBJECT_NAME)
--------------------------------------------------------------------------------
STATUS
-------
/3e484eb0_MessageFactoryImpl
com/sun/xml/messaging/saaj/soap/MessageFactoryImpl
INVALID
Затем я проверил, что была ошибка в классе:
dev> alter java class "com/sun/xml/messaging/saaj/soap/MessageFactoryImpl" resolve;
dev> /
Warning: Java altered with compilation errors.
dev> show error
Errors for JAVA CLASS "/3e484eb0_MessageFactoryImpl":
LINE/COL ERROR
-------- -----------------------------------------------------------------
0/0 ORA-29521: referenced name javax/xml/soap/MessageFactory could
not be found
0/0 ORA-29521: referenced name javax/xml/soap/SOAPMessage could not
be found
0/0 ORA-29521: referenced name javax/xml/soap/MimeHeaders could not
be found
0/0 ORA-29521: referenced name javax/xml/soap/SOAPException could not
be found
(Эти ошибки также будут перечислены в user_errors, предполагая, что разрешение было предпринято как минимум один раз.)
Так ясно, что этот класс ссылается на классы из базовой библиотеки SOAP. Вы тоже должны были бы загрузить это - вы сделали это?
К вашему сведению, когда я пишу какой -то код для выполнения звонка class.forname (), я получаю ClassNotFoundException. Что может показаться нелогичным, поскольку объект класса существует в схеме. Тем не менее, недопустимый класс на самом деле не «существует» с точки зрения загрузчика класса в Oracle; и для того, чтобы класс был действительным, Oracle должен иметь возможность разрешить все свои ссылки на другие классы.
Другие советы
Это первый раз, когда вы выполняете Java в базе данных? Вот реализация Hello World, чтобы убедиться, что ваш Oracle JVM работает должным образом, и у вас есть необходимые разрешения. Вы сказали: «Моя схема базы данных, так что я могу делать все, что хочу», -это не значит, что у вас есть правильные гранты.
SQL> create or replace and compile java source named "Hello" as
public class Hello{
public static String world() {
return "Hello World ";
}
};
/
Java created.
Теперь функция обертки
SQL> create or replace function Hello RETURN VARCHAR2
as LANGUAGE JAVA NAME 'Hello.world() return String';
/
Function created.
Теперь проверьте это
SQL> select Hello from dual;
HELLO
-----------------------------------
Hello World
Сделай это:
try
{
System.out.println("Class.forName returned: " +
Class.forName("com.sun.xml.messaging.saaj.soap.MessageFactoryImpl"));
}
catch(final Throwable ex)
{
ex.printStackTrace();
System.exit(1);
}
Просто чтобы быть на 100 и 10% уверен, что это не бросает исключение, которое каким -то образом скрыто и что он действительно возвращает NULL. Если это все еще так, пожалуйста, дайте мне знать (интересная проблема, если приведенный выше код работает, но возвращает NULL).
Попробуйте # 3 :-) (Я не использую Oracle ... но это аккуратная проблема для отладка ...)
Информация здесь на классе.
http://download.oracle.com/docs/cd/b14117_01/java.101/b12021/appover.htm#i1006547
Это представляет собой проблему загрузчика класса, так что решение, решение соответствует тому же, что и в мире «реального, не оракула» :-)
Изменить ... еще одна попытка ...
Хорошо, посмотрю на это еще немного ... какова вывода следующего:
System.out.println("vm vendor: " + System.getProperty("java.vendor"));
System.out.println("vm version: " + System.getProperty("java.version"));
System.out.println("class version: " + System.getProperty("java.class.version"));
Мне интересно, есть ли проблема с версией файла класса - есть ли файлы классов версию, которую нельзя запустить на виртуальной машине Oracle?
Разрешение класса и нагрузка являются сложными операциями, обрабатываемыми виртуальной машиной. Алгоритм, который будет использоваться этими двумя операциями, как описано в спецификации, остается открытым для ревизоров VM. Я чувствую, что в вашем случае разрешение работает, поскольку операция проверяет только наличие самого класса, в то время как оно не удается позже, когда пытается эффективно загрузить класс (скорее всего, из -за отсутствующих зависимостей: при загрузке класса необходима виртуальная машина. решить, по крайней мере, все прямые ссылки на другие классы). Вы должны убедиться, что все классы доступны для Oracle, и выполнение быстрого поиска в Google ORA-29534 показывает тонны людей, имеющих эту проблему (и я уверен, что кто-то это понял).
./Алекс
SAAJ-IMPL.JAR является частью компонента SAAJ Pack Developer Pack. Например, он имеет зависимости от других банок, которые поставляются с Saaj, это определенно зависит от Saaj-Api.jar и Activation.jar, насколько мне известно. Конечно, Saaj-Api.jar также обязательно будет зависеть от многих других банок.
Что касается JWSDP 1.5, вы можете найти информацию в Jwsdp 1.5. быть полезным. JWSDP 1.6 имеет разные банки в Saaj, я не нашел выпуск JWSDP 2.0, которые были особенно полезны в этом отношении. Кстати, у JWSDP 2.0 будут разные банки, которые будут размещены в обмене класса; Таким образом, объем вашей проблемы в конечном итоге зависит от версии Saaj-Impl.jar, которую вы используете.
На случай, если вам это может понадобиться, некоторая документация уже доступна о том, как загрузить банки клиентов SOAP в базу данных Oracle и использовать их на следующих страницах. Я предполагаю, что это отличается от банок Saaj, которые поставляются с вашей библиотекой.