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.java:
171)
at
com.sun.xml.internal.ws.fault.SOAPFaultBuilder.createException(SOAPFaultBuilder.java:
94)
at
com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:
240)
at
com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.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
│public class Web_Serwis
{
│
│ public native String
p();
│
│ public static void main(String[] args)
{
│ System.load("/u/agata/ala/
libmy.so");
│ Web_Serwis serwis = new
Web_Serwis();
│
│ String version =
serwis.p();
│
│ System.out.println("wersja=" +
version);
│ }
│}
This is the header file:
//Web_Serwis.h
│/* DO NOT EDIT THIS FILE - it is machine generated
*/
│
│#include
<jni.h>
│/* Header for class Web_Serwis
*/
│char
*p_version_c();
│#ifndef
_Included_Web_Serwis
│#define
_Included_Web_Serwis
│#ifdef
__cplusplus
│extern
"C" {
│#endif
│
│/
*
│ * Class:
Web_Serwis
│ * Method:
p
│ * Signature: ()Ljava/lang/
String;
│
*/
│JNIEXPORT jstring JNICALL
Java_Web_1Serwis_p
│ (JNIEnv *,
jobject);
│
│#ifdef
__cplusplus
│}
│#endif
│#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
│#include
"Web_Serwis.h"
│#include
<string>
│
│JNIEXPORT jstring JNICALL
Java_Web_1Serwis_p
│ (JNIEnv *env, jobject
obj)
│{
│ const char *str =
p_version_c();
│ if(str ==
NULL)
│
{
│ return (*env).NewStringUTF("ERROR: p_version_c()
returned NULL")
│ }
│ return
(*env).NewStringUTF(str);
│}
Oh, and this is how I compile and run the program:
│g++ -shared -m32 -c -g3 -gdwarf-2 -I/opt/SDK/jdk/include/linux -I/opt/
SDK/jdk/include -o Web_Serwis.o Web_Serwis.cc
│g++ -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
│/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
│/* DO NOT EDIT THIS FILE - it is machine generated
*/
│#include
<jni.h>
│/* Header for class ws_p_versionSerwer
*/
│char *
p_version_c();
│#ifndef
_Included_ws_p_versionSerwer
│#define
_Included_ws_p_versionSerwer
│#ifdef
__cplusplus
│extern
"C" {
│#endif
│/
*
│ * Class:
ws_p_versionSerwer
│ * Method:
p
│ * Signature: ()Ljava/lang/
String;
│
*/
│ JNIEXPORT jstring JNICALL
Java_ws_p_1versionSerwer_p
│ (JNIEnv *,
jobject);
│
│ #ifdef
__cplusplus
│ }
│
#endif
│ #endif
And a C++ file that calls p_version_c():
// p_version.cc
#include
"p_version.h"
│#include
<string>
│
│JNIEXPORT jstring JNICALL
Java_ws_p_1versionSerwer_p
│ (JNIEnv * env, jobject
obj)
│{
│ const char *str =
p_version_c();
│
if(str==NULL)
│Ireturn (*env).NewStringUTF("ERROR: funkcja p_version_c zwrocila
NULL"); │
│ return
(*env).NewStringUTF(str);
│}
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! :)
Lothar Kimmeringer - 15 Feb 2008 11:51 GMT
> /**
> * Web service operation
> */
> @WebMethod
> public native String p();
personally I would do the following:
@WebMethod
public String callP(){
return p();
}
private native String p();
I'm not sure how JWS behaves but if the native-declaration is
kept in the ServerPort you receive on the client-side, the
WebService-Client will try to call a native method on the
client side that must fail unless you don't have the same
JNI-Library installed there.
> cli.PVersionSerwerService service = new
> cli.PVersionSerwerService();
> cli.PVersionSerwer port = service.getPVersionSerwerPort();
> // TODO process result here
> java.lang.String result = port.p();
Instead of the above line, you would use
String result = port.callP();
Regards, Lothar

Signature
Lothar Kimmeringer E-Mail: spamfang@kimmeringer.de
PGP-encrypted mails preferred (Key-ID: 0x8BC3CD81)
Always remember: The answer is forty-two, there can only be wrong
questions!
Roedy Green - 16 Feb 2008 22:26 GMT
>java.lang.UnsatisfiedLinkError
see
http://mindprod.com/jgloss/runerrormessages.html#UNSATISFIEDLINKERROR
--
Roedy Green Canadian Mind Products
The Java Glossary
http://mindprod.com