views:

1119

answers:

7

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
+1  A: 

Do this:

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);
}

Just to be 100and10% sure that it is not throwing an exception that is somehow being hidden and that it is really returning null. If it is still the case please let me know (interesting problem if the code above works, but returns null).

TofuBeer
Sheesh. My mistake. The Class.forName("com.sun.yada.yada..") line throws an exception: java.lang.ClassNotFoundException: com/sun/xml/messaging/saaj/soap/MessageFactoryImpl
Chris Farmer
+4  A: 

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.

Dave Costa
The saaj-impl.jar file does indeed contain the com.sun.xml.messaging.saaj.soap.MessageFactoryImpl class.Thanks for the use of the "longname" function. I couldn't figure out how to get those full names back! There are no longname classes that are LIKE '%MessageFactory%' in my Oracle instance.
Chris Farmer
So, it looks pretty clear that loadjava isn't doing what I want it to do. Do you have any ideas how I can debug my use of that?
Chris Farmer
I would expect that the verbose output from loadjava would contain at least some indication. Can you post a representative sample of the output?
Dave Costa
Thanks. I edited my post to contain the verbose loadjava output.
Chris Farmer
Edited answer. My best guess at this point is that you haven't loaded other jars that contain classes referenced by the SAAJ classes.
Dave Costa
Nice investigation
stjohnroe
A: 

Try # 3 :-) (I don't use Oracle... but this is a neat problem to debug...)

Does the info here on Class.forName in Oracle help?

http://download.oracle.com/docs/cd/B14117_01/java.101/b12021/appover.htm#i1006547

This presents as a ClassLoader issue, so hoepfully the solution is along the same lines as what happens in the "real, non-Oracle" world :-)

Edit... another try...

Ok looking at it some more... what is the output of the following:

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"));

I am wondering if there is an issue with the class file version - do the class files have a version that cannot be run on the Oracle VM?

TofuBeer
Yeah, this is my database schema, so I can do whatever I want. The problem is I don't necessarily know what I'm doing!
Chris Farmer
that make two of us :-)
TofuBeer
+1  A: 

Is this the first time your executing Java on the database? Here is hello world implementation to make sure your Oracle JVM is running properly and you have the necessary permissions. You said "my database schema, so I can do whatever I want" -doesn't mean you have the proper grants.

SQL> create or replace and compile java source named "Hello" as 
   public class Hello{ 
      public static String world() { 
         return "Hello World "; 
      } 
   }; 
/ 

Java created.

Now the wrapper function

SQL> create or replace function Hello RETURN VARCHAR2 
     as LANGUAGE JAVA NAME 'Hello.world() return String'; 
     / 

Function created.

Now test it

SQL> select Hello from dual; 

HELLO 
----------------------------------- 
Hello World
Brian
Oh, I can run other methods just fine. I tried to say that in my message when I said that I can access the target url via http. That's within my java class running in oracle. It's my hello world.
Chris Farmer
A: 

Class resolution and loading are complex operations handled by the VM. The algorithm to be used by these 2 operations as described in the spec is left open for VM implementors. My feeling is that in your case the resolution works as the operation checks only the availability of the class itself, while it is failing later when trying to effectively load the class (most probably due to missing dependencies: when loading the class, the VM needs to resolve at least all direct references to other classes). You'll have to make sure that all classes are available to Oracle and performing a quick Google search for ORA-29534 shows tons of people having this problem (and I'm pretty sure somebody figured it out).

./alex

alexpopescu
A: 

The saaj-impl.jar is part of the SAAJ component of the Web Services Developer Pack. It has dependencies on other JARs that ship with SAAJ, for instance, it definitely depends on saaj-api.jar and activation.jar, to my knowledge. Of course, saaj-api.jar is bound to depend on a lot of other JARs as well.

As far as JWSDP 1.5 is concerned, you could find the information in JWSDP 1.5 Release Notes to be useful. JWSDP 1.6 has different JARs in SAAJ I havent found the JWSDP 2.0 Release Notes to be particularly useful in this regard. BTW, JWSDP 2.0 would have different JARs to be placed in the classpath; so the scope of your problem eventually depends on the version of saaj-impl.jar that you use.

Just in case you might need it, some documentation is already available on how to load the SOAP client JARs into an Oracle database and to utilize them, in the following pages. I presume these to be different from the SAAJ JARs that comes with your library though.

Vineet Reynolds
A: 

Hi I would like to ask you what appropriate socket permissions need to be granted?