混淆了Oracle java存储过程中的类解析

时间:2009-02-27 23:03:29

标签: java oracle java-stored-procedures loadjava

我正在尝试在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已经加载了这些类,那么如何说服我自己的代码成功使用现有的类?

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

6 个答案:

答案 0 :(得分:9)

首先,在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必须能够解析对其他类的所有引用。

答案 1 :(得分:3)

这是您第一次在数据库上执行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 

答案 2 :(得分:1)

这样做:

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 :(得分:0)

尝试#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上运行的版本?

答案 4 :(得分:0)

类解析和加载是VM处理的复杂操作。如规范中所述的这两个操作所使用的算法对于VM实现者是开放的。 我的感觉是,在你的情况下,解析工作,因为操作只检查类本身的可用性,而后来在尝试有效加载类时失败(很可能是由于缺少依赖性:加载类时,VM需要解决至少所有对其他类的直接引用)。 您必须确保所有类都可供Oracle使用,并且对ORA-29534进行快速Google搜索显示有大量人员遇到此问题(而且我很确定有人认为是这样)。

./亚历

答案 5 :(得分:0)

saaj-impl.jar是Web Services Developer Pack的SAAJ组件的一部分。它依赖于SAAJ附带的其他JAR,例如,据我所知,它肯定依赖于saaj-api.jar和activation.jar。当然,saaj-api.jar也必然依赖于很多其他JAR。

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

如果您可能需要它,有关如何将SOAP客户端JAR加载到Oracle数据库并使用它们的文档已经可用,请参阅以下页面。我认为这些与您的图书馆附带的SAAJ JAR不同。