簡體   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