Путаница в разрешении классов в хранимых процедурах Oracle Java - PullRequest
1 голос
/ 28 февраля 2009

Я пытаюсь использовать стороннюю библиотеку Java в Oracle. Библиотека кажется совместимой с той же версией 1.4 jvm, что и на нашем сервере Oracle 10g, поскольку она прекрасно работает за пределами 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 / messaging / saaj / soap / MessageFactoryImpl ).

Затем я вернулся и попытался добавить ключ «-resolve» в командной строке loadjava. Похоже, что эти классы saaj регистрируются, но они не разрешаются должным образом.

Как мне успешно перенести эти классы saaj в Oracle или, если по какой-то причине Oracle уже загрузил их, как я могу убедить свой собственный код в успешном использовании существующего класса?

FWIW, я уже предпринял шаги, чтобы убедиться, что соответствующие разрешения сокета были предоставлены, и мой код может успешно сделать общий http-запрос к целевому URL. У него просто проблемы с использованием стека библиотеки SOAP, чтобы это произошло.

EDIT: Вот пример моего результата 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

Ответы [ 6 ]

9 голосов
/ 02 марта 2009

Прежде всего, проверьте вне Oracle, что класс, который вы ищете, на самом деле находится в этом jar-файле. Я ожидаю, что это так, но это не помешает проверить.

Затем я бы проверил, какие классы были загружены и имеют ли они допустимые статусы.

SELECT object_name, dbms_java.longname(object_name), status
  FROM user_objects
  WHERE object_type='JAVA CLASS'
  ORDER BY 1

Возможно, вы захотите немного ограничить это, если есть много классов, например ::100100

WHERE dbms_java.longname(object_name) LIKE '%MessageFactoryImpl'

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

Если класс существует, но его статус - INVALID, проверьте USER_ERRORS, чтобы увидеть, что это за ошибки. Я не помню, выполнял ли я динамическую загрузку классов в Oracle, но я вспоминаю, что статическое связывание давало бы ошибки, которые подразумевали, что класс не существовал, когда он действительно существовал, но имел ошибки.

Добавлена ​​новая информация после выхода loadjava

Вывод loadjava кажется несовместимым с вашей попыткой найти класс в базе данных. Если он загружается, но не разрешается, он все равно должен быть в списке, но со статусом INVALID.

Я получил JAR и попробовал сам в пустой схеме. Класс загружается, но, как и ожидалось, неверен:

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 должен иметь возможность разрешать все свои ссылки на другие классы.

3 голосов
/ 07 марта 2009

Это ваш первый запуск 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 
1 голос
/ 28 февраля 2009

Сделайте это:

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% уверенным, что оно не выдает исключение, которое каким-то образом скрыто, и что оно действительно возвращает ноль. Если это все еще так, пожалуйста, дайте мне знать (интересная проблема, если приведенный выше код работает, но возвращает ноль).

0 голосов
/ 09 марта 2009

saaj-impl.jar является частью SAAJ-компонента пакета разработчика веб-служб. Например, у него есть зависимости от других JAR-файлов, которые поставляются с SAAJ, это, безусловно, зависит от saaj-api.jar и активации.jar. Конечно, saaj-api.jar также зависит от множества других JAR-файлов.

Что касается JWSDP 1.5, вы можете найти полезную информацию в Замечания к выпуску JWSDP 1.5 . JWSDP 1.6 имеет различные JAR-файлы в SAAJ. Я не нашел, что примечания к выпуску JWSDP 2.0 особенно полезны в этом отношении. Кстати, JWSDP 2.0 будет иметь разные JAR для размещения в пути к классам; поэтому масштаб вашей проблемы в конечном итоге зависит от используемой вами версии saaj-impl.jar.

На всякий случай вам может понадобиться некоторая документация о том, как загрузить JAR-файлы SOAP-клиента в базу данных Oracle и как их использовать, на следующих страницах. Полагаю, они отличаются от файлов JAR SAAJ, которые входят в вашу библиотеку.

0 голосов
/ 08 марта 2009

Разрешение класса и загрузка являются сложными операциями, обрабатываемыми виртуальной машиной. Алгоритм, который будет использоваться этими двумя операциями, как описано в спецификации, остается открытым для разработчиков виртуальных машин. Мне кажется, что в вашем случае разрешение работает, так как операция проверяет только доступность самого класса, а позже она терпит неудачу при попытке эффективно загрузить класс (скорее всего из-за отсутствующих зависимостей: при загрузке класса виртуальной машине нужны разрешить хотя бы все прямые ссылки на другие классы). Вам нужно убедиться, что все классы доступны для Oracle, и при быстром поиске в Google для ORA-29534 вы обнаружите множество людей, столкнувшихся с этой проблемой (и я почти уверен, что кто-то решил ее).

. / Алекс

0 голосов
/ 03 марта 2009

Попробуйте # 3 :-) (Я не использую Oracle ... но это аккуратная проблема для отладки ...)

Помогает ли здесь информация о Class.forName в Oracle?

http://download.oracle.com/docs/cd/B14117_01/java.101/b12021/appover.htm#i1006547

Это представляет проблему ClassLoader, так что, к счастью, решение в том же духе, что и в мире "реального, не Oracle"

Редактировать ... еще одну попытку ...

Хорошо, посмотрим на это еще ... что выдает следующее:

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?

...