JNI and Web Services
I have a *BIG* problem concerning callin a C++ .so library function
from a java Web Service (I am using JNI). Every time I start the Web
Service client I get a following error:
javax.xml.ws.soap.SOAPFaultException: Unknown fault type:class
java.lang.UnsatisfiedLinkError
at
com.sun.xml.internal.ws.fault.SOAP11Fault.getProtocolException(SOAP11Fault.j=
ava:
171)
at
com.sun.xml.internal.ws.fault.SOAPFaultBuilder.createException(SOAPFaultBuil=
der.java:
94)
at
com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandle=
r.java:
240)
at
com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandle=
r.java:
210)
at
com.sun.xml.internal.ws.client.sei.SEIStub.invoke(SEIStub.java:103)
at $Proxy28.p(Unknown Source)
at p_versionclient.Main.main(Main.java:31)
as if the function wasn't there! And it is!
Not to mention that when I call the function from a regular java
program (with a main function) OR a C program - it works! I have no
idea what's going on...
The regular java program looks like this:
//Web_Serwis.java
=81public class Web_Serwis
{
=81
=81 public native String
p();
=81
=81 public static void main(String[] args)
{
=81 System.load("/u/agata/ala/
libmy.so");
=81 Web_Serwis serwis = new
Web_Serwis();
=81
=81 String version =
serwis.p();
=81
=81 System.out.println("wersja=" +
version);
=81 }
=81}
This is the header file:
//Web_Serwis.h
=81/* DO NOT EDIT THIS FILE - it is machine generated
*/
=81
=81#include
<jni.h>
=81/* Header for class Web_Serwis
*/
=81char
*p_version_c();
=81#ifndef
_Included_Web_Serwis
=81#define
_Included_Web_Serwis
=81#ifdef
__cplusplus
=81extern
"C" {
=81#endif
=81
=81/
*
=81 * Class:
Web_Serwis
=81 * Method:
p
=81 * Signature: ()Ljava/lang/
String;
=81
*/
=81JNIEXPORT jstring JNICALL
Java_Web_1Serwis_p
=81 (JNIEnv *,
jobject);
=81
=81#ifdef
__cplusplus
=81}
=81#endif
=81#endif
And this is the C++ program (p_version_c() is a function from another
library that I link to this one):
//Web_Serwis.cc
=81#include
"Web_Serwis.h"
=81#include
<string>
=81
=81JNIEXPORT jstring JNICALL
Java_Web_1Serwis_p
=81 (JNIEnv *env, jobject
obj)
=81{
=81 const char *str =
p_version_c();
=81 if(str ==
NULL)
=81
{
=81 return (*env).NewStringUTF("ERROR: p_version_c()
returned NULL")
=81 }
=81 return
(*env).NewStringUTF(str);
=81}
Oh, and this is how I compile and run the program:
=81g++ -shared -m32 -c -g3 -gdwarf-2 -I/opt/SDK/jdk/include/linux -I/opt/
SDK/jdk/include -o Web_Serwis.o Web_Serwis.cc
=81g++ -shared -m32 -o libmy.so Web_Serwis.o /u/adm/bin.pg8.2/o/za/kk.o /
u/adm/bin.pg8.2/o/za/m_action.o /u/adm/bin.pg8.2/ar/k
=81/opt/jdk1.6/bin/java Web_Serwis
So far it works. Now I make a similar Web Service, exposing the call
to the library function (p() calls p_version_c()):
//p_versionSerwer.java
package ws;
import javax.jws.WebMethod;
import javax.jws.WebService;
/**
*
* @author agata
*/
@WebService()
public class p_versionSerwer {
static
{
try {
System.out.println ("loading library...");
System.load("/u/agata/ws/libp.so");
}
catch (Exception e) {
System.out.println ("Can't load library!!!");
e.printStackTrace();
}
catch (Error err) {
System.out.println ("ERROR: Can't load
library!!!");
err.printStackTrace();
}
}
/**
* Web service operation
*/
@WebMethod
public native String p();
}
I create a header file:
//p_version.h
=81/* DO NOT EDIT THIS FILE - it is machine generated
*/
=81#include
<jni.h>
=81/* Header for class ws_p_versionSerwer
*/
=81char *
p_version_c();
=81#ifndef
_Included_ws_p_versionSerwer
=81#define
_Included_ws_p_versionSerwer
=81#ifdef
__cplusplus
=81extern
"C" {
=81#endif
=81/
*
=81 * Class:
ws_p_versionSerwer
=81 * Method:
p
=81 * Signature: ()Ljava/lang/
String;
=81
*/
=81 JNIEXPORT jstring JNICALL
Java_ws_p_1versionSerwer_p
=81 (JNIEnv *,
jobject);
=81
=81 #ifdef
__cplusplus
=81 }
=81
#endif
=81 #endif
And a C++ file that calls p_version_c():
// p_version.cc
#include
"p_version.h"
=81#include
<string>
=81
=81JNIEXPORT jstring JNICALL
Java_ws_p_1versionSerwer_p
=81 (JNIEnv * env, jobject
obj)
=81{
=81 const char *str =
p_version_c();
=81
if(str==NULL)
=81Ireturn (*env).NewStringUTF("ERROR: funkcja p_version_c zwrocila
NULL"); =81
=81 return
(*env).NewStringUTF(str);
=81}
Finally I compile the files with other library files into libp.so:
g++ -shared -m32 -g3 -gdwarf-2 -I/opt/SDK/jdk/include/linux -I/opt/SDK/
jdk/include -o p_version.o p_version.cc
g++ -shared -m32 -o libp.so p_version.o /u/adm/bin.pg8.2/o/za/kk.o /u/
adm/bin.pg8.2/o/za/m_action.o /u/adm/bin.pg8.2/ar/k
And run a simple client:
//Main.java
package p_versionclient;
/**
*
* @author agata
*/
public class Main {
/** Creates a new instance of Main */
public Main() {
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
try { // Call Web Service Operation
cli.PVersionSerwerService service = new
cli.PVersionSerwerService();
cli.PVersionSerwer port = service.getPVersionSerwerPort();
// TODO process result here
java.lang.String result = port.p();
System.out.println("Result = "+result);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
And that's when I get the error message... I've been trying to get
this to work for a week now, so I would really appreciate some help
(maybe a way to check where's the problem or a way to get an error
message, that actually SAYS something) .
I'm running this Web Service on a remote server, if that's of any
significance.
Thanks in advance! :)