1

我正在尝试在 oracle 中使用第三方 Java 库。该库似乎与我们的 Oracle 10g 服务器托管的相同 1.4 版本的 jvm 兼容,因为它在 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% 的文件,但还有其他类显示相同的类解析问题。

参数:'-verbose''-schema''MYSCHEMA''-user''MYSCHEMA/MYSCHEMA@actest''-resolve''-force''saaj-impl.jar'
[剪辑]
创建:类 MYSCHEMA.com/sun/xml/messaging/saaj/soap/EnvelopeFactory
加载:类 MYSCHEMA.com/sun/xml/messaging/saaj/soap/EnvelopeFactory
创建:类 MYSCHEMA.com/sun/xml/messaging/saaj/soap/GifDataContentHandler
加载:类 MYSCHEMA.com/sun/xml/messaging/saaj/soap/GifDataContentHandler
创建:类 MYSCHEMA.com/sun/xml/messaging/saaj/soap/JpegDataContentHandler
加载:类 MYSCHEMA.com/sun/xml/messaging/saaj/soap/JpegDataContentHandler
创建:类 MYSCHEMA.com/sun/xml/messaging/saaj/soap/MessageFactoryImpl
加载:类 MYSCHEMA.com/sun/xml/messaging/saaj/soap/MessageFactoryImpl
创建:类 MYSCHEMA.com/sun/xml/messaging/saaj/soap/MessageImpl
加载:类 MYSCHEMA.com/sun/xml/messaging/saaj/soap/MessageImpl
[剪辑]
解决: MYSCHEMA.com/sun/xml/messaging/saaj/soap/AttachmentPartImpl 类
解决:类MYSCHEMA.com/sun/xml/messaging/saaj/soap/Envelope
解决:类 MYSCHEMA.com/sun/xml/messaging/saaj/soap/EnvelopeFactory
错误:类 MYSCHEMA.com/sun/xml/messaging/saaj/soap/EnvelopeFactory
    ORA-29534: 引用的对象 MYSCHEMA.com/sun/xml/messaging/saaj/soap/SOAPPartImpl 无法解析
解决: MYSCHEMA.com/sun/xml/messaging/saaj/soap/GifDataContentHandler 类
解决: MYSCHEMA.com/sun/xml/messaging/saaj/soap/JpegDataContentHandler 类
解决: MYSCHEMA.com/sun/xml/messaging/saaj/soap/MessageFactoryImpl 类
错误:类 MYSCHEMA.com/sun/xml/messaging/saaj/soap/MessageFactoryImpl
    ORA-29534: 引用的对象 MYSCHEMA.com/sun/xml/messaging/saaj/soap/MessageImpl 无法解析
错误:类 MYSCHEMA.com/sun/xml/messaging/saaj/soap/MessageImpl
    ORA-29534: 引用的对象 MYSCHEMA.com/sun/xml/messaging/saaj/soap/impl/EnvelopeImpl 无法解析
错误:类 MYSCHEMA.com/sun/xml/messaging/saaj/soap/MessageImpl$1
    ORA-29534: 引用的对象 MYSCHEMA.com/sun/xml/messaging/saaj/soap/MessageImpl 无法解析
跳过:类 MYSCHEMA.com/sun/xml/messaging/saaj/soap/MessageImpl$2
[剪辑]
以下操作失败
    MYSCHEMA.com/sun/xml/messaging/saaj/soap/EnvelopeFactory 类:分辨率
    MYSCHEMA.com/sun/xml/messaging/saaj/soap/MessageFactoryImpl 类:分辨率
    MYSCHEMA.com/sun/xml/messaging/saaj/soap/MessageImpl 类:分辨率
    MYSCHEMA.com/sun/xml/messaging/saaj/soap/MessageImpl$1 类:分辨率
[剪辑]
exiting :处理过程中发生故障
4

6 回答 6

10

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

于 2009-03-02T16:22:19.347 回答
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 
于 2009-03-07T02:07:54.507 回答
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,这是一个有趣的问题)。

于 2009-02-28T02:22:47.447 回答
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 上运行的版本?

于 2009-03-02T21:55:26.380 回答
0

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

./亚历克斯

于 2009-03-08T09:41:51.227 回答
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 发行说明中找到有用的信息。JWSDP 1.6 在 SAAJ 中有不同的 JAR 我还没有发现 JWSDP 2.0 发行说明在这方面特别有用。顺便说一句,JWSDP 2.0 会在类路径中放置不同的 JAR;所以你的问题的范围最终取决于你使用的 saaj-impl.jar 的版本。

以防万一您可能需要它,以下页面中已经提供了一些关于如何将 SOAP 客户端 JAR 加载到 Oracle 数据库中并使用它们的文档。我认为这些与您的库附带的 SAAJ JAR 不同。

于 2009-03-08T21:42:22.477 回答