Confusion over class resolution in Oracle java stored procedures

Chris Farmer picture Chris Farmer · Feb 28, 2009 · Viewed 10.2k times · Source

I'm trying to use a third-party java library within oracle. The library seems compatible with the same 1.4 version of the jvm that our Oracle 10g server hosts, since it runs fine outside of Oracle, so I feel like I should be able to get this to work. This library ends up making SOAP-based http requests, and I get class resolution errors when I run in Oracle.

Here's a line that shows the difference:

Class msgfact = Class.forName("com.sun.xml.messaging.saaj.soap.MessageFactoryImpl");

I tried to register these libraries into Oracle with the loadjava utility, and I got what I thought was a successful result:

C:\>loadjava -verbose -schema MYUSER -user MYUSER/MYPWD@dbinstance -force saaj-impl.jar

It looks like everything gets loaded, and I can see this MessageFactoryImpl class in that list. But then I try to run this line of code from Oracle SQL (inside another class I wrote and loaded with loadjava), this line throws a ClassNotFoundException (java.lang.ClassNotFoundException: com/sun/xml/messaging/saaj/soap/MessageFactoryImpl).

Then I went back and tried to add the "-resolve" switch at the loadjava command line. It acts like these saaj classes are getting registered, but they aren't resolving properly.

How can I successfully get these saaj classes into Oracle, or if for some reason Oracle already has these loaded, how can I convince my own code to successfully use the existing class?

FWIW, I already took the steps to make sure that the appropriate socket permissions were granted and my code can successfully make a generic http request to the target url. It just has trouble using the library's SOAP stack to make it happen.

EDIT: Here is a sample of my loadjava result. This seems to be showing exactly what's failing, but I'm confused as to why these particular classes aren't being resolved when they seem to be handled properly in the pre-resolution steps. I've eliminated about 80% of the file here, but there are other classes that show the same class resolution issues.

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

Answer

Dave Costa picture Dave Costa · Mar 2, 2009

First of all, verify outside of Oracle that the class you are looking for is actually in that jar file. I expect it is, but it doesn't hurt to check.

Then, I would check what classes have been loaded and whether they have valid statuses.

SELECT object_name, dbms_java.longname(object_name), status
  FROM user_objects
  WHERE object_type='JAVA CLASS'
  ORDER BY 1

You might want to limit this somewhat if there are a lot of classes, e.g.:

WHERE dbms_java.longname(object_name) LIKE '%MessageFactoryImpl'

If the class is not there, or it is there with the wrong package name, then the problem is with the loadjava command.

If the class is there but its status is INVALID, then check USER_ERRORS to see what the errors are. I don't recall if I've done dynamic class loading within Oracle, but I recall that static linking would give errors that implied a class didn't exist when it really existed but had errors.

New info after loadjava output posted

The loadjava output seems inconsistent with your attempt to find the class in the database. If it is being loaded but not resolved, it should still be listed, but with an INVALID status.

I got the JAR and tried it myself in an empty schema. The class loads but is invalid as expected:

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

I then checked what the error were on the class:

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

(These errors would also be listed in USER_ERRORS, assuming resolution was attempted at least once.)

So clearly this class references classes from the base SOAP library. You would have to load that too -- have you done that?

FYI, when I write some code to do the Class.forName() call, I do get the ClassNotFoundException. Which may seem counter-intuitive since the class object does exist in the schema. However, an invalid class doesn't really "exist" from the point of view of the class loader in Oracle; and in order for the class to be valid Oracle has to be able to resolve all of its references to other classes.