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