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).
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
Voici le contenu PHP :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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>
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.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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"); } ?>
Voici ma classe de test du service :
En passant comme "Virginie" ou une chaine vide à la méthode hello(string):string le résultat affiché est OK.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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()); }
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 : Sélectionner tout - Visualiser dans une fenêtre à part
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.
Partager