Partie 1 : Développement Bottom-Up (Code First)
2. Création de la classe Test.java
Fichier src/mypackage/Test.java :
package mypackage;
import javax.jws.WebService;
import javax.jws.WebMethod;
@WebService
public class Test {
@WebMethod
public String echoBonjour(String name) {
return "Bonjour " + name + ". Service Bottom-UP";
}
}6. Explication de la commande wsgen
La commande wsgen génère les artefacts JAX-WS nécessaires au déploiement du service web :
- Analyse de la classe
mypackage.Testannotée avec@WebService - Génération des classes wrapper pour les messages SOAP (requête/réponse)
- Création des classes de marshalling/unmarshalling JAXB
- Production des fichiers nécessaires à l’invocation du service
7. Classes générées
Dans le répertoire build/mypackage/jaxws/ :
EchoBonjour.class: Wrapper pour la requêteEchoBonjourResponse.class: Wrapper pour la réponse
Dans le répertoire src/mypackage/jaxws/ :
EchoBonjour.java: Classe représentant les paramètres d’entrée de la méthodeEchoBonjourResponse.java: Classe représentant la valeur de retour
EchoBonjour.java
package mypackage.jaxws;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
@XmlRootElement(name = "echoBonjour", namespace = "http://mypackage/")
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "echoBonjour", namespace = "http://mypackage/")
public class EchoBonjour {
@XmlElement(name = "arg0", namespace = "")
private String arg0;
public String getArg0() {
return this.arg0;
}
public void setArg0(String arg0) {
this.arg0 = arg0;
}
}Encapsule le paramètre d’entrée de la méthode echoBonjour pour le transport SOAP.
EchoBonjourResponse.java
package mypackage.jaxws;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
@XmlRootElement(name = "echoBonjourResponse", namespace = "http://mypackage/")
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "echoBonjourResponse", namespace = "http://mypackage/")
public class EchoBonjourResponse {
@XmlElement(name = "return", namespace = "")
private String _return;
public String getReturn() {
return this._return;
}
public void setReturn(String _return) {
this._return = _return;
}
}Encapsule la valeur de retour de la méthode pour la réponse SOAP.
11. Vérification du déploiement
Connexion à la console d’administration WildFly (http://localhost:9990/console) et navigation vers Deployments.
Le service myprojectTEST.war apparaît avec le statut Enabled.
a. Messages définit :
<message name="echoBonjour">
<part name="parameters" element="tns:echoBonjour"/>
</message>
<message name="echoBonjourResponse">
<part name="parameters" element="tns:echoBonjourResponse"/>
</message>b. Méthodes disponibles :
<portType name="Test">
<operation name="echoBonjour">
<input message="tns:echoBonjour"/>
<output message="tns:echoBonjourResponse"/>
</operation>
</portType>c. Protocole réseau :
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>d. Style d’interaction :
Le binding indique style="document"
e. Adresse du service :
<soap:address location="http://localhost:8080/myprojectTEST/Test"/>12. Test avec SOAP UI
Création d’un nouveau projet SOAP dans SOAP UI avec le WSDL :
Requête de test :
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:myp="http://mypackage/">
<soapenv:Header/>
<soapenv:Body>
<myp:echoBonjour>
<arg0>Claude</arg0>
</myp:echoBonjour>
</soapenv:Body>
</soapenv:Envelope>Réponse obtenue :
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<ns2:echoBonjourResponse xmlns:ns2="http://mypackage/">
<return>Bonjour Claude. Service Bottom-UP</return>
</ns2:echoBonjourResponse>
</S:Body>
</S:Envelope>13. -wsdl
L’option -wsdl demande à wsgen de générer également le fichier WSDL.
14. Artefacts générés
En plus des classes précédentes, les fichiers suivants sont créés dans build/ :
TestService.wsdl: Description WSDL complète du serviceTestService_schema1.xsd: Schéma XML décrivant les types de données utilisés
Partie 2 : Développement Top-Down (Contract First)
3. Examen du fichier Test2Service.wsdl
Le WSDL définit deux opérations dans le portType Test2 :
<operation name="addition">
<input message="tns:addition"/>
<output message="tns:additionResponse"/>
</operation>
<operation name="sayhello">
<input message="tns:sayhello"/>
<output message="tns:sayhelloResponse"/>
</operation>addition: Addition de deux entiers (arg0, arg1) → retourne un entiersayhello: Salutation avec un nom (arg0 string) → retourne une chaîne
Test2Service_schema1.xsd
Le schéma définit les types complexes pour chaque opération :
addition: contient deux élémentsarg0etarg1de typexs:intadditionResponse: contient un élémentreturnde typexs:intsayhello: contient un élémentarg0de typexs:stringsayhelloResponse: contient un élémentreturnde typexs:string
5. wsimport
La commande wsimport lit le fichier WSDL et génère :
- L’interface du service représentant le portType
- Les classes JAXB pour les types de données du schéma
- Les classes wrapper pour les messages SOAP
- La classe Service pour obtenir les stubs clients
- L’interface du port pour l’invocation du service
6. Classes Java générées
Dans src/mypackage/ :
Interfaces et classes de service :
Test2.java: Interface définissant les méthodes du serviceTest2Service.java: Classe Service pour obtenir le portTest2Port.java: Interface du port (similaire à Test2)
Classes JAXB pour les types :
Addition.java: Classe représentant la requête d’additionAdditionResponse.java: Classe représentant la réponse d’additionSayhello.java: Classe représentant la requête sayhelloSayhelloResponse.java: Classe représentant la réponse sayhelloObjectFactory.java: Factory JAXBpackage-info.java: Informations du package
Test2.java
package mypackage;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.ws.RequestWrapper;
import javax.xml.ws.ResponseWrapper;
@WebService(name = "Test2", targetNamespace = "http://mypackage/")
@XmlSeeAlso({
ObjectFactory.class
})
public interface Test2 {
@WebMethod
@WebResult(targetNamespace = "")
@RequestWrapper(localName = "addition", targetNamespace = "http://mypackage/",
className = "mypackage.Addition")
@ResponseWrapper(localName = "additionResponse", targetNamespace = "http://mypackage/",
className = "mypackage.AdditionResponse")
public int addition(
@WebParam(name = "arg0", targetNamespace = "")
int arg0,
@WebParam(name = "arg1", targetNamespace = "")
int arg1);
@WebMethod
@WebResult(targetNamespace = "")
@RequestWrapper(localName = "sayhello", targetNamespace = "http://mypackage/",
className = "mypackage.Sayhello")
@ResponseWrapper(localName = "sayhelloResponse", targetNamespace = "http://mypackage/",
className = "mypackage.SayhelloResponse")
public String sayhello(
@WebParam(name = "arg0", targetNamespace = "")
String arg0);
}C’est une interface Java qui définit le contrat du service.
7. Implémentation du service
Remplacement de Test2.java par l’implémentation concrète :
package mypackage;
import javax.jws.WebService;
import javax.jws.WebMethod;
@WebService
public class Test2 {
private final String message = "Hello, ";
@WebMethod
public String sayhello(String name) {
return message + name + " --- Test 2 top-down déploiement en ligne de commande";
}
@WebMethod(operationName="addition")
public int add(int a, int b) {
return (a + b);
}
}9. Déploiement
Le fichier Test2Service.war.deployed est créé, confirmant le déploiement.
10. Consultation du WSDL
Accès via la console d’administration ou directement :
http://localhost:8080/Test2Service/Test2?wsdl
Le WSDL affiché correspond au contrat défini initialement, avec les deux opérations addition et sayhello.
11. Test avec SOAP UI
Création d’un projet SOAP UI avec le WSDL :
http://localhost:8080/Test2Service/Test2?wsdl
Test de l’opération sayhello :
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:myp="http://mypackage/">
<soapenv:Header/>
<soapenv:Body>
<myp:sayhello>
<arg0>World</arg0>
</myp:sayhello>
</soapenv:Body>
</soapenv:Envelope>Réponse :
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<ns2:sayhelloResponse xmlns:ns2="http://mypackage/">
<return>Hello, World --- Test 2 top-down déploiement en ligne de commande</return>
</ns2:sayhelloResponse>
</S:Body>
</S:Envelope>Test de l’opération addition :
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:myp="http://mypackage/">
<soapenv:Header/>
<soapenv:Body>
<myp:addition>
<arg0>15</arg0>
<arg1>27</arg1>
</myp:addition>
</soapenv:Body>
</soapenv:Envelope>Réponse :
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<ns2:additionResponse xmlns:ns2="http://mypackage/">
<return>42</return>
</ns2:additionResponse>
</S:Body>
</S:Envelope>Les deux opérations fonctionnent parfaitement !