Confusion over class resolution in Oracle java stored procedures - java

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

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.

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

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).

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?

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

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.
Calling a webservice from the database.
How to install the SOAP client stack in the Oracle database.
Install JAR files in the database

Related

Tomcat webclassloader fails to find a class

In a Tomcat 7 I have a pretty standar jar file on WEB-INF/lib. Inside this jar I have this class called Parser, and next to it (on the same dir) I have another one called AutomaticLocalLoader. Compilation gives no problem at all. In run time the AutomaticLoader class is found, and when It needs the Parser class, I get a NoClassDefFoundError
The Parser and AutomaticLoader class have been working without this problem for 15 years!! in many diferent vers of java and tomact; and now out of the blue, I am getting this NoClassDefFoundError, only for the Parser class. I already put a copy on a directory inside the WEB-INF/classes path and still got the same error. I already created my own ClassLoader to see if I get some error loading the class from the WEB-INF/classes directory by myself, but I can load it without problems.
log.info("Leer " + aFlInstructions[i].getAbsolutePath());
LoaderTest A = new LoaderTest();
A.test("com.hds.resolve.model.aguila.AutomaticLocalLoader");
LoaderTest B = new LoaderTest();
B.test("com.hds.resolve.model.aguila.Parser");
if(!bOverrideInputDir)
Psr = new Parser(aFlInstructions[i]);
else
Psr = new Parser(aFlInstructions[i], new String[] { StrLocalDirectory } );
The LoaderTest class, try to create the Class Object for the given name using Class.forName. If NoClassDefFoundError, then try to load the class using my own classloader and then create the class.
For the AutomaticLoader, it succed at the first try. For the Parser class if fails, then successfully load it with the custom classloader. Of course when the code reach the "new Parser" part, the old webclassloader still fails and throws the NoClassDefFoundError.
Both Parser and AutomaticLocalLoader belong to the same package and are stored on the same jar inside WEB-LIB.
Funny enough, the error does always happen on production... but never in my machine. I do not use customs classloaders except for doing this debug. Also, trying an old version of the software seems to fix the error. No idea why.
I think I can hack a solution messing with the tomcat's webclassloader, but I really would prefer to understand what is going wrong with this code.

How to call java methods (which is inside a java package) from PLSQL

The requirement is to call java methods from plsql and I am able to achieve it through loadjava command. The steps which I am following is :
Step 1: Create the Java Class/jar file and place it on unix box
Step 2: Load the Java Class/jar into the Database and i can see a new object in ALL_OBJCETS table with object type as JAVA CLASS
Step 3: Publish the Function: Creating the function/proc using java static method
Step 4: Execute the Function/proc.
And it's working fine for me but the challenge I am facing here when the java classs is defined in java package. for example:
the class file is:
==========================
package emrsn.com;
public class DBTEST {
public static String callMe(String input){
return input;
}
}
========================
Now when I am uploading the above java code (class file) in database I can see the object name is "emrsn\com\DBTEST", instead of "DBTEST" in ALL_OBJECTS table and the status is INVALID.
I am not able to even recompile the class file in database (using ALTER JAVA CLASS obj_name RESOLVE), when the object name is like emrsn\DBTEST.
Please let em know if there is any other specific way to refer this type of java class file in database , when it is packaged in Java.
Can you please let me know how do I use these JAVA class objects (when it is emrsn/com/DBTEST) while creating function or while recompiling this object. As mentioned earlier, I can't recompile them to see the exact error.
ALTER JAVA CLASS com/emrsn/DBTEST RESOLVE
Getting below error
Error report:
SQL Error: ORA-00922: missing or invalid option
00922. 00000 - "missing or invalid option"
*Cause:
And if I am using ALTER JAVA CLASS DBTEST RESOLVE, it's saying object not found. Let me know how I can refer these objects.
You need to use double quotes (and forward slashes) and the right keyword depending wether you used class or source files:
alter java source "emrsn/com/DBTEST" compile;
-- or
alter java class "emrsn/com/DBTEST" compile;
-- alternatively use resolve clause
To get the full name of all invalid objects use
SELECT dbms_java.longname (object_name) FROM user_objects
WHERE object_type = 'JAVA CLASS' AND status = 'INVALID';
(http://docs.oracle.com/cd/B19306_01/java.102/b14187/appendixa.htm)
To use your "callMe"
CREATE OR REPLACE FUNCTION f_call_me(p_input VARCHAR2) RETURN VARCHAR IS LANGUAGE JAVA name 'emrsn.com.DBTEST.callMe(java.lang.String) return java.lang.String';
/
sho err
select f_call_me('blah') from dual;

Using Inline::Java in perl with threads

I am writing a trading program in perl with the newest Finance::InteractiveBrokers::TWS
module. I kick off a command line interface in a separate thread at the
beginning of my program but then when I try to create a tws object, my program
exits with this message:
As of Inline v0.30, use of the Inline::Config module is no longer supported or
allowed. If Inline::Config exists on your system, it can be removed. See the
Inline documentation for information on how to configure Inline. (You should
find it much more straightforward than Inline::Config :-)
I have the newest versions of Inline and Inline::Java. I looked at TWS.pm and it doesn't seem to be using Inline::Config. I set 'SHARED_JVM => 1' in the 'use Inline()' and 'Inline->bind()' calls in TWS.pm but that did not resolve the issue...
My Code:
use Finance::InteractiveBrokers::TWS;
use threads;
use threads::shared;
our $callback;
our $tws;
my $interface = UserInterface->new();
share($interface);
my $t = threads->create(sub{$interface->runUI()});
$callback= TWScallback->new();
$tws = Finance::InteractiveBrokers::TWS->new($manager); #This is where the program fails
So is Inline::Config installed on your system or not? A cursory inspection of the code is not sufficient to tell whether Perl is loading a module or not. There are too many esoteric ways (some intentional and some otherwise) to load a package or otherwise populate a namespace.
The error message in question comes from this line of code in Inline.pm:
croak M14_usage_Config() if %main::Inline::Config::;
so something in your program is populating the Inline::Config namespace. You should do what the program instructs you to do: find out where Inline/Config.pm is installed on your system (somewhere in your #INC path) and delete it.

interface exception

i have these codes
UserAgentContext uAgent=new SimpleUserAgentContext();
DocumentBuilderImpl docBuild=new DocumentBuilderImpl(uAgent);
docBuild.parse(new InputSourceImpl("http://dic.amdz.com/"));
when i run , it gives me the following error:
Exception in thread "main" java.lang.IncompatibleClassChangeError: Found interface sun.font.FontManager, but class was expected
at org.lobobrowser.util.gui.FontFactory.createFont(FontFactory.java:210)
at org.lobobrowser.util.gui.FontFactory.createFont_Impl(FontFactory.java:180)
at org.lobobrowser.util.gui.FontFactory.createFont(FontFactory.java:127)
at org.lobobrowser.util.gui.FontFactory.getFont(FontFactory.java:98)
at org.lobobrowser.html.style.StyleSheetRenderState.<clinit>(StyleSheetRenderState.java:43)
at org.lobobrowser.html.domimpl.NodeImpl.<clinit>(NodeImpl.java:39)
at org.lobobrowser.html.parser.DocumentBuilderImpl.createDocument(DocumentBuilderImpl.java:143)
at org.lobobrowser.html.parser.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:97)
at cobratest2.Cobratest2.main(Cobratest2.java:21)
then pointing me to the last line. so the question is, what to do?
The problem is at
org.lobobrowser.util.gui.FontFactory.createFont(FontFactory.java:210)
That class was compiled against an old version of the libraries in whichsun.font.FontManager was a class, but you are trying to run it with newer libraries in which it is now an interface. You will probably have to recompile all of the org.lobobrowser package against current libraries.
And BTW, the link What causes java.lang.IncompatibleClassChangeError? mentioned by e-zinc does contain all the information you need to have figured this out yourself.

ClassFormatError: Illegal class modifiers in class ... 0x209

I have a few some strange issues with my class after migrating from JDK5/Tomcat5 to JDK6/Tomcat7 both with MyEclipse 9.
Whenever I try to access 'myclass' via jsp:usebean I got following error
org.apache.jasper.JasperException: javax.servlet.ServletException: java.lang.ClassFormatError: Illegal class modifiers in class myclass: 0x209
The rest of log points nowhere. By trial and error I have trimmed huge class to the following problematic part:
...
rf = store.getDefaultFolder();
f = (IMAPFolder)rf;
final IMAPStore storeNew = store;
Object val = f.doCommand(new IMAPFolder.ProtocolCommand() { <-- problem propably starts here
public Object doCommand(IMAPProtocol p)
throws ProtocolException {
...
The next strange thing is that my colleague is using the same environment with no problems. I have compared our class files and the only difference is in last but one byte. My class ends with '02 09', his '06 09'
After several days I am out of options how to get rid of it.
EDIT:
I have reinstalled/updated to MyEclipse 9.1. No luck so far.
SOLUTION
After another day trying to reproduce problem with a new project with a single file in it, I have realised that only remaining difference is in project/properties/java build path/libraries. There was J2EE 1.4 Libraries in the main project, so I have replaced it. After adding Java EE 6 Libraries voila. I am able to compile and run w/o any problems

Categories