[英]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.