繁体   English   中英

Oracle Java存储过程中的类解析混乱

[英]Confusion over class resolution in Oracle java stored procedures

我正在尝试在Oracle中使用第三方Java库。 该库似乎与我们的Oracle 10g服务器托管的jvm的1.4版本兼容,因为它可以在Oracle外部正常运行,因此我认为我应该能够使其工作。 该库最终发出基于SOAP的http请求,并且在Oracle中运行时遇到类解析错误。

这是显示差异的行:

Class msgfact = Class.forName("com.sun.xml.messaging.saaj.soap.MessageFactoryImpl");

我尝试使用loadjava实用程序将这些库注册到Oracle中,并且得到了我认为成功的结果:

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 )。

然后我回去尝试在loadjava命令行中添加“ -resolve”开关。 就像这些saaj类正在注册一样,但是它们没有正确解析。

我如何才能成功地将这些saaj类放入Oracle,或者如果由于某种原因Oracle已经加载了这些saaj类,如何说服自己的代码成功使用现有类?

FWIW,我已经采取步骤来确保已授予适当的套接字权限,并且我的代码可以成功地向目标URL发出通用的HTTP请求。 使用库的SOAP堆栈来实现它只是有麻烦。

编辑:这是我的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命令。

如果该类在那里,但其状态为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必须能够解析其对其他类的所有引用。

这是您第一次在数据库上执行Java吗? 这是您好世界的实现,以确保您的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);
}

仅需100and10%,就可以确保它不会引发某种被隐藏的异常,并且它实际上返回的是null。 如果仍然如此,请告诉我(如果上面的代码可行,那么有趣的问题,但返回null)。

尝试#3:-)(我不使用Oracle ...但是这是调试的一个好问题...)

Oracle中有关Class.forName的信息对您有帮助吗?

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上运行?

类解析和加载是VM处理的复杂操作。 规范中描述的这两个操作要使用的算法对VM实现者开放。 我的感觉是,在您的情况下,解决方案在操作仅检查类本身的可用性时起作用,而稍后在尝试有效加载类时却失败了(很可能是由于缺少依赖项:在加载类时,VM需要至少解决所有对其他类的直接引用)。 您必须确保所有类都对Oracle可用,并对Google快速执行ORA-29534进行的Google搜索表明,有很多人有此问题(而且我敢肯定,有人会发现这一问题)。

./alex

saaj-impl.jar是Web服务开发人员包的SAAJ组件的一部分。 它依赖于SAAJ附带的其他JAR,例如,据我所知,它绝对依赖于saaj-api.jar和activation.jar。 当然,saaj-api.jar也必然依赖于许多其他JAR。

就JWSDP 1.5而言,您可以在JWSDP 1.5发行说明中找到有用的信息。 JWSDP 1.6在SAAJ中具有不同的JAR,我还没有发现JWSDP 2.0发行说明在这方面特别有用。 顺便说一句,JWSDP 2.0将在类路径中放置不同的JAR。 因此,问题的范围最终取决于您使用的saaj-impl.jar的版本。

为了防万一,您可能会在接下来的页面中找到一些文档,以了解如何将SOAP客户端JAR加载到Oracle数据库中以及如何使用它们。 我认为它们与您的库随附的SAAJ JAR不同。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM