PDA

View Full Version : [Java C] Problema JNI e Web Services


Unrue
18-12-2006, 11:34
Sto cercando di costruire un Web Services che richiama un metodo Java che a sua volta richiama un metodo C mediante JNI. Il fatto è che il metodo c non viene richiamato e non viene restituito alcun errore. Premetto che nel codice C non c'è nessun errore in quanto se provo a richiamarlo da una semplice classe Java funziona perfettamente, Dunque,io creo la classe TestJNI.java, che contiene il metodo nativo:

package provajni;
import java.lang.String;

public class TestJNI {
public native void metodoc(String firstarg,String secarg);

}

Qua ci andrebbe anche la System.loadLibrary, ho provato a metterla li,ma non succede nulla. Quindi la inserisco nella classe client,tanto credo sia lo stesso, basta che da qualche parte la carichi.

A questo punto compilo la classe e ,dal lato C creo l'header con javah e la libreria dinamica.
Adesso dal lato Java creo il WSDL:

java org.apache.axis.wsdl.Java2WSDL -o TestJNI.wsdl -l"http://localhost:8080/axis/services/TestJNI" -n "urn:TestJNI" -p"provajni" "urn: TestJNI " provajni.TestJNI

Poi i vari files per il WS:

java org.apache.axis.wsdl.WSDL2Java -o . -s -S true -Nurn:TestJNI provajni TestJNI.wsdl

Li compilo tutti e li copio sotto Tomcat. In seguito faccio il deploy del ws. Il WSDL di TestJNi quindi appare correttamente sotto i servizi di Axis ed espone il metodo "metodoc".

A questo punto creo la classe client:

import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import javax.xml.namespace.QName;
//import java.lang.*;

public class ClasseProva
{
public ClasseProva()
{
}
public static void main(String [] args) throws Exception {
String endpoint = "http://localhost:8080/axis/services/TestJNI";
String method = "metodoc" ;

try{
System.loadLibrary("metodoc");

}
catch(UnsatisfiedLinkError e)
{e.printStackTrace();

}
}
Service service = new Service(); //creo un nuovo servizio
Call call = (Call)service.createCall();
call.setTargetEndpointAddress(new java.net.URL(endpoint));
call.setOperationName(method); // Definisco il metodo da invocare
call.invoke( new Object [] {"2","Funzionaaaaa!!!! :) :) "});
System.out.println("Ciao ciao");
}
}




LA libreria c la carica correttamente, viene scritta l'ultima stringa, ma il programma C non viene chiamato. Secondo me , il problema potrebbe essere che quando creo i vari files del WS, il metodo nativo, non viene visto come nativo, ovvero viene visto come void metodoc e non native void metodoc

Ringrazio chiunque mi aiuti :)

^TiGeRShArK^
18-12-2006, 19:32
Sto cercando di costruire un Web Services che richiama un metodo Java che a sua volta richiama un metodo C mediante JNI. Il fatto è che il metodo c non viene richiamato e non viene restituito alcun errore. Premetto che nel codice C non c'è nessun errore in quanto se provo a richiamarlo da una semplice classe Java funziona perfettamente, Dunque,io creo la classe TestJNI.java, che contiene il metodo nativo:

package provajni;
import java.lang.String;

public class TestJNI {
public native void metodoc(String firstarg,String secarg);

}

Qua ci andrebbe anche la System.loadLibrary, ho provato a metterla li,ma non succede nulla. Quindi la inserisco nella classe client,tanto credo sia lo stesso, basta che da qualche parte la carichi.

A questo punto compilo la classe e ,dal lato C creo l'header con javah e la libreria dinamica.
Adesso dal lato Java creo il WSDL:

java org.apache.axis.wsdl.Java2WSDL -o TestJNI.wsdl -l"http://localhost:8080/axis/services/TestJNI" -n "urn:TestJNI" -p"provajni" "urn: TestJNI " provajni.TestJNI

Poi i vari files per il WS:

java org.apache.axis.wsdl.WSDL2Java -o . -s -S true -Nurn:TestJNI provajni TestJNI.wsdl

Li compilo tutti e li copio sotto Tomcat. In seguito faccio il deploy del ws. Il WSDL di TestJNi quindi appare correttamente sotto i servizi di Axis ed espone il metodo "metodoc".

A questo punto creo la classe client:

import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import javax.xml.namespace.QName;
//import java.lang.*;

public class ClasseProva
{
public ClasseProva()
{
}
public static void main(String [] args) throws Exception {
String endpoint = "http://localhost:8080/axis/services/TestJNI";
String method = "metodoc" ;

try{
System.loadLibrary("metodoc");

}
catch(UnsatisfiedLinkError e)
{e.printStackTrace();

}
}
Service service = new Service(); //creo un nuovo servizio
Call call = (Call)service.createCall();
call.setTargetEndpointAddress(new java.net.URL(endpoint));
call.setOperationName(method); // Definisco il metodo da invocare
call.invoke( new Object [] {"2","Funzionaaaaa!!!! :) :) "});
System.out.println("Ciao ciao");
}
}




LA libreria c la carica correttamente, viene scritta l'ultima stringa, ma il programma C non viene chiamato. Secondo me , il problema potrebbe essere che quando creo i vari files del WS, il metodo nativo, non viene visto come nativo, ovvero viene visto come void metodoc e non native void metodoc

Ringrazio chiunque mi aiuti :)
mmmm..
non ho mai provato a lanciare una kiamata jni tramite tomcat..
non è ke il problema è proprio ke il classloader di tomcat non riesce a trovarti la libreria nativa?
Se non erro bisogna inserire la directory dove hai la libreria nel path di sistema o alternativamente settare il java.library.path per fargli caricare la libreria nativa correttamente...
ma cmq possibile ke nn ti lanci nessuna eccezione?
hai provato a guardare i log di tomcat?

Unrue
19-12-2006, 20:56
In effetti qualcosa c'è:

INFO: The Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path:

Ho installato allora APR e jsvc. Devo capire bene come configurarli però.

^TiGeRShArK^
19-12-2006, 21:51
In effetti qualcosa c'è:

INFO: The Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path:

Ho installato allora APR e jsvc. Devo capire bene come configurarli però.
ehm...no...
se nn ricordo male quell'avviso è normale....
Hai visto se la tua libreria JNI è caricata nella variabile di sistema PATH o alternativamente hai fatto partire tomcat con l'opzione -Djava.library.path=<dir_tua_JNI>?
Imho ti conviene aggiungerla al path ke è + semplice :p
...sempre se è questo il problema :D
ma cmq tentar non nuoce ;)

Unrue
20-12-2006, 19:18
ehm...no...
se nn ricordo male quell'avviso è normale....
Hai visto se la tua libreria JNI è caricata nella variabile di sistema PATH o alternativamente hai fatto partire tomcat con l'opzione -Djava.library.path=<dir_tua_JNI>?
Imho ti conviene aggiungerla al path ke è + semplice :p
...sempre se è questo il problema :D
ma cmq tentar non nuoce ;)

Ma per librerie JNi intendi le tomcat-native? O quelle che sono sotto la dir di jdk? E comunque l
a libreria c la carica, infatti se la tolgo mi dà "UnsatisfiedLinkError". Solo che poi non va avanti

^TiGeRShArK^
20-12-2006, 20:05
Ma per librerie JNi intendi le tomcat-native? O quelle che sono sotto la dir di jdk? E comunque l
a libreria c la carica, infatti se la tolgo mi dà "UnsatisfiedLinkError". Solo che poi non va avanti
no intendevo la tua ovviamente :p
ma visto ke togliendola ti da l'unsatisfied link error direi ke il problema nn è questo.
Le librerie JNI di tomcat servono solo x avere maggiori performance in ambiente di produzione.....
onestamente non ho idea di quale sia il problema xkè JNI l'ho usato solo x utilizzare librerie di terze parti..
non mi sono mai messo a usarlo partendo da zero....
quindi mi sa ke non so km aiutarti :p

Unrue
20-12-2006, 20:44
In realtà la libreria la carica perchè la System.loadLibrary la metto nella classe chiamante,non in quella da cui costruisco il Web Service. Il fatto è che se la metto in quella classe, quando uso javaWSDL e crea tutte le interfaccie per il WS, nella classe SoapBingingImpl, la chiamata alla libreria scompare. Boh..