[Axis 2] : pb appel web services avec paramètre à null
Bonjour,
j'essaye de mettre en place un service web en PHP 5+ et de pouvoir appeler ce service web avec une application Java fonctionnant avec une JRE 6.
Débutant dans les services web, je me suis créé un petit service de test (serviceABCD). :D
Voici le contenu de mon fichier WSDL de type document/literal contenant :
- la méthode hello(String):String où le paramètre d'entrée peut-être null et doit être inférieur ou égal à 10 caractères max.
- la méthode getDicton() : String
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
| <?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions name="service" targetNamespace="serviceABCD"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:tns="serviceABCD"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
>
<!-- Définition des types personnalisés -->
<wsdl:types>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="serviceABCD">
<!-- Type vide -->
<xsd:complexType name="empty" />
<!-- Définition d un string nullable & <= 10 caractères -->
<xsd:simpleType name="stringMax10Nillable">
<xsd:restriction base="xsd:string" >
<xsd:maxLength value="10" />
<xsd:minLength value="0" />
</xsd:restriction>
</xsd:simpleType>
<xsd:element name="hello" type="tns:stringMax10Nillable" nillable="true" />
<xsd:element name="helloResponse" type="xsd:string" />
<xsd:element name="getDicton" type="tns:empty" nillable="true" />
<xsd:element name="getDictonResponse" type="xsd:string" />
</xsd:schema>
</wsdl:types>
<!-- Abstraction de plus haut niveau des paramètres -->
<wsdl:message name="helloRequest" >
<wsdl:part name="parameters" element="tns:hello" />
</wsdl:message>
<wsdl:message name="helloResponse">
<wsdl:part name="parameters" element="tns:helloResponse"/>
</wsdl:message>
<wsdl:message name="getDictonRequest">
<wsdl:part name="parameters" element="tns:getDicton" />
</wsdl:message>
<wsdl:message name="getDictonResponse">
<wsdl:part name="parameters" element="tns:getDictonResponse"/>
</wsdl:message>
<!-- PortType : contient des abstractions de haut niveau des opération du service web -->
<wsdl:portType name="IServiceABCD">
<wsdl:operation name="hello">
<wsdl:documentation>Méthode hello()..</wsdl:documentation>
<wsdl:input message="tns:helloRequest"></wsdl:input>
<wsdl:output message="tns:helloResponse"></wsdl:output>
</wsdl:operation>
<wsdl:operation name="getDicton">
<wsdl:documentation>Méthode qui retourne un beau dicton...</wsdl:documentation>
<wsdl:input message="tns:getDictonRequest"></wsdl:input>
<wsdl:output message="tns:getDictonResponse"></wsdl:output>
</wsdl:operation>
</wsdl:portType>
<!-- Binding : définit le protocole à utiliser pour invoquer le service web -->
<wsdl:binding name="BindingServiceABCD" type="tns:IServiceABCD">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="hello">
<soap:operation soapAction="serviceABCD/hello" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="getDicton">
<soap:operation soapAction="serviceABCD/getDicton" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<!-- Définition du service à proprement parler -->
<!-- Contient l URL du service -->
<wsdl:service name="ServiceABCD">
<wsdl:port name="PortServiceABCD" binding="tns:BindingServiceABCD">
<soap:address location="http://localhost/ServiceABCD/index.php" />
</wsdl:port>
</wsdl:service>
</wsdl:definitions> |
Voici le contenu PHP :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| <?php
// Si on a le paramètre wsdl, on doit afficher le wsdl
if (isset($_GET['wsdl']))
{
header("content-type: application/xml");
$file = "./service.wsdl";
$fp = fopen($file, "r");
$fluxXml = fread($fp, filesize($file));
fclose($fp);
echo $fluxXml;
exit;
}
// première étape : désactiver le cache lors de la phase de test
ini_set("soap.wsdl_cache_enabled", "0");
// on indique au serveur à quel fichier de description il est lié
$serveurSOAP = new SoapServer('./service.wsdl');
// ajouter la fonction hello au serveur
$serveurSOAP->addFunction('hello');
// ajouter la fonction getDicton au serveur
$serveurSOAP->addFunction('getDicton');
// lancer le serveur
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$serveurSOAP->handle();
} else {
echo 'désolé, je ne comprends pas les requêtes GET, veuillez seulement utiliser POST';
}
function hello($nom) {
return utf8_encode('Bonjour ' . $nom . ' !!!');
}
function getDicton() {
return utf8_encode("Per Santa Luça lo jorn creis d'un saut de puça, per Nadal d'un pé de Gal");
}
?> |
J'ai utilisé l'outil wsdl2java fournit avec la librairie Axis 2 en version 1.4.1 pour générer les classes me permettant d'invoquer le service web.
Voici ma classe de test du service :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| public static void main(String[] args) throws Exception {
ServiceABCDStub service = new ServiceABCDStub();
Hello paramBonjourHello = new Hello();
StringMax10Nillable paramBonjour = new StringMax10Nillable();
paramBonjourHello.setHello(paramBonjour);
// 1er test avec "Virginie"
paramBonjour.setStringMax10Nillable("Virginie");
System.out.println(service.hello(paramBonjourHello).getHelloResponse());
// 2ème test avec une chaine vide : ""
paramBonjour.setStringMax10Nillable("");
System.out.println(service.hello(paramBonjourHello).getHelloResponse());
// 3ème test avec une chaine nulle
paramBonjour.setStringMax10Nillable(null);
System.out.println(service.hello(paramBonjourHello).getHelloResponse());
// 4ème test avec une chaine de caractères > 10 car. : "abcdefghijk"
paramBonjour.setStringMax10Nillable("abcdefghijk");
System.out.println(service.hello(paramBonjourHello).getHelloResponse());
} |
En passant comme "Virginie" ou une chaine vide à la méthode hello(string):string le résultat affiché est OK.
Si j'envoie une chaine de caractères supérieur à 10 caractères : "abcdefghijk", une RuntimeException est soulevée, ce qui est là aussi correct.
Par contre, si j'envoie une chaine nulle à la méthode hello(string):string, j'obtiens la stack trace suivante :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| Exception in thread "main" org.apache.axis2.AxisFault: Value cannot be null !!
at org.apache.axis2.AxisFault.makeFault(AxisFault.java:430)
at org.apache.axis2.transport.http.SOAPMessageFormatter.writeTo(SOAPMessageFormatter.java:83)
at org.apache.axis2.transport.http.AxisRequestEntity.writeRequest(AxisRequestEntity.java:84)
at org.apache.commons.httpclient.methods.EntityEnclosingMethod.writeRequestBody(EntityEnclosingMethod.java:499)
at org.apache.commons.httpclient.HttpMethodBase.writeRequest(HttpMethodBase.java:2114)
at org.apache.commons.httpclient.HttpMethodBase.execute(HttpMethodBase.java:1096)
at org.apache.commons.httpclient.HttpMethodDirector.executeWithRetry(HttpMethodDirector.java:398)
at org.apache.commons.httpclient.HttpMethodDirector.executeMethod(HttpMethodDirector.java:171)
at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:397)
at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:346)
at org.apache.axis2.transport.http.AbstractHTTPSender.executeMethod(AbstractHTTPSender.java:542)
at org.apache.axis2.transport.http.HTTPSender.sendViaPost(HTTPSender.java:189)
at org.apache.axis2.transport.http.HTTPSender.send(HTTPSender.java:75)
at org.apache.axis2.transport.http.CommonsHTTPTransportSender.writeMessageWithCommons(CommonsHTTPTransportSender.java:371)
at org.apache.axis2.transport.http.CommonsHTTPTransportSender.invoke(CommonsHTTPTransportSender.java:209)
at org.apache.axis2.engine.AxisEngine.send(AxisEngine.java:448)
at org.apache.axis2.description.OutInAxisOperationClient.send(OutInAxisOperation.java:401)
at org.apache.axis2.description.OutInAxisOperationClient.executeImpl(OutInAxisOperation.java:228)
at org.apache.axis2.client.OperationClient.execute(OperationClient.java:163)
at fr.axis2.ServiceABCDStub.hello(ServiceABCDStub.java:1026)
at fr.TestServiceABCD.main(TestServiceABCD.java:26)
Caused by: org.apache.axis2.databinding.ADBException: Value cannot be null !!
at fr.axis2.ServiceABCDStub$StringMax10Nillable.serialize(ServiceABCDStub.java:7775)
at fr.axis2.ServiceABCDStub$StringMax10Nillable.serialize(ServiceABCDStub.java:7726)
at fr.axis2.ServiceABCDStub$Hello.serialize(ServiceABCDStub.java:3780)
at fr.axis2.ServiceABCDStub$Hello.serialize(ServiceABCDStub.java:3743)
at fr.axis2.ServiceABCDStub$Hello$1.serialize(ServiceABCDStub.java:3731)
at org.apache.axis2.databinding.ADBDataSource.serialize(ADBDataSource.java:93)
at org.apache.axiom.om.impl.llom.OMSourcedElementImpl.internalSerializeAndConsume(OMSourcedElementImpl.java:664)
at org.apache.axiom.om.impl.llom.OMElementImpl.internalSerialize(OMElementImpl.java:918)
at org.apache.axiom.om.impl.llom.OMElementImpl.internalSerializeAndConsume(OMElementImpl.java:947)
at org.apache.axiom.soap.impl.llom.SOAPEnvelopeImpl.serializeInternally(SOAPEnvelopeImpl.java:240)
at org.apache.axiom.soap.impl.llom.SOAPEnvelopeImpl.internalSerialize(SOAPEnvelopeImpl.java:228)
at org.apache.axiom.om.impl.llom.OMElementImpl.internalSerializeAndConsume(OMElementImpl.java:947)
at org.apache.axiom.om.impl.llom.OMNodeImpl.serializeAndConsume(OMNodeImpl.java:471)
at org.apache.axis2.transport.http.SOAPMessageFormatter.writeTo(SOAPMessageFormatter.java:79)
... 19 more |
Dans le document WSDL, j'ai pourtant bien spécifié nullable="true" pour le paramètre d'entrée.
Avez-vous une idée ?
J'ai également essayé de désactiver la validation des données via un paramètre de l'outil wsdl2java mais là non plus, sans succès.
Comment écrit-on que la valeur d'un paramètre est facultative dans un document WSDL ?
Qu'est-ce qui ne va pas dans ma démarche ?
Merci beaucoup de m'aider.
F.