webservice

Impémentation JAX-WS

Késako

JAX-WS remplace JAX-RPC à partir de JEE 5. Ce changement de nom reflète la changement de philosophie des développements Web Services en Java, passant d’un modèle «RPC» à un modèle «document»

A partir de J2SE 5, le langage intègre des annotations permettant de simplifier le développement de Web Services.

Ces annotations correspondent à la JSR 224 et à la JSR 181.

La version intégré à JEE 5 est JAX-WS 2.0 L’implémentation de référence de la norme est un sous-projet OpenSource qui fait partie du projet «Metro».

Metro lui-même est un sous projet de GlassFish le serveur d’application OpenSource de Sun.

Encodage des messages

Messages de type RPC

Messages XML destinés à représenter, indépendamment du langage de programmation, l’invocation d’un service, ainsi que son résultat éventuel.

La structure générale de la requête et de la réponse est imposée par la spécification. Cette dernière aborde aussi les problèmes d’encodage des paramètres, notamment des tableaux et des graphes d’objets : RPC / encoded.

Ce modèle de messages est le plus simple des deux, mais aussi le plus contraignant.

Messages de type Document

La spécification SOAP n’impose, dans ce cas, aucune contrainte sur la structure de ces messages. Le sens des données XML véhiculées est laissé à l’appréciation des applications participant à l’échange.

Ce modèle de messages offre plus de liberté, mais peut être à l’origine de problèmes d’interopérabilité.

NotaBene

  • Notez bien que dans les 2 cas, la structure des messages XML échangés est complètement décrite par le document WSDL. Dans le 1er cas, le serveur est obligé de respecter certaines règles. Dans le 2ème cas, il peut décrire n’importe quelle structure XML.
  • Le modèle de messages de type RPC est tombé en désuétude
  • Dans SOAP 1.2, seul le support du modèle Document est obligatoire
  • On constate une évolution similaire en Java avec la dernière API: JAX-WS 2.0
  • Quant à .Net, il préconise depuis le début l’utilisation des messages de type Document.
  • Gare donc aux problèmes d’interopérabilité entre les anciennes applications qui s’appuient sur le modèle RPC et certains nouveaux outils qui ne supportent que le modèle Document.
  • Pour invoquer un Web Service, les plates-formes s’appuient donc aujourd’hui sur le modèle Document.
  • Mais, comme la structure des messages XML est libre, comment par exemple repérer dans le document XML le nom du service invoqué?
  • En fait, pour résoudre ce problème, les plates-formes utilisent généralement le modèle Document/literal wrapped. Ce modèle impose quelques contraintes. Notamment le fait que la balise racine du message XML transporté corresponde au nom de l’opération invoquée.

Description des annotations JSR 181 (WS MetaData)

Annotation
@WebService Marque une classe comme WS
@WebMethod Expose une méthode comme une opération SOAP
@Oneway Marque une action comme sans retour. Ne s’applique qu’à une méthode sans paramètre de sortie
@SOAPBinding Permet de spécifier l’encodage du message (RPC ou Document)
@WebParam Permet de spécifier le mapping entre un paramètre de la méthode java et un élément du message XML
@WebResult Permet de spécifier le mapping entre la valeur de retour de la méthode java et un élément du message XML
@HandlerChain Permet de préciser un fichier de configuration pour la factorisation des gestionnaires
@BindingType Précise le type de bind du service (protocole)
@RequestWrapper Permet à JAXB de mapper les éléments XML de la requête avec les éléments java associés
@ResponseWrapper Permet à JAXB de mapper les éléments XML de la réponse avec les éléments java associés
@ServiceMode Permet l’accès au message complet ou au payload
@WebFault Permet de gérer le mapping entre une exception Java et une Fault SOAP

Serveur

Interface

@WebService(name="Convertisseur",
            serviceName="ConvertisseurService",
            targetNamespace="peut.etre.different") 
}

Implementation

WebService(endpointInterface="fr.lgr.exemple.ws.Convertisseur")
public class ConvertisseurImpl implements Convertisseur {

    @WebMethod
    public double getEuro(double franc) throws ConvertisseurException {
        //toDo
    }

}

Exception

@WebFault 
public class ConvertisseurException extends RemoteException {
}

Client

@WebServiceClient(name = "ConvertisseurImplService", 
                  targetNamespace = "http://impl.ws.exemple.lgr.fr/", 
                  wsdlLocation = "http://localhost:9080/convertisseur-web/mesWebServices/Convertisseur?wsdl")
public class ConvertisseurImplService
    extends Service
{
    //todo
}
@WebService(name = "Convertisseur", 
            targetNamespace = "peut.etre.different")
@XmlSeeAlso({ ObjectFactory.class })
public interface Convertisseur {


    @WebMethod
    @WebResult(targetNamespace = "")
    @RequestWrapper(localName = "getEuro",
                    targetNamespace = "peut.etre.different", 
                    className = "fr.lgr.exemple.ws.client.generated.GetEuro")
    @ResponseWrapper(localName = "getEuroResponse", 
                     targetNamespace = "peut.etre.different", className = "fr.lgr.exemple.ws.client.generated.GetEuroResponse")
    public double getEuro(
        @WebParam(name = "arg0", targetNamespace = "")
        double arg0);

Mise en place

Tomcat ne bénéficiant pas nativement des fonctionnalités Jax-ws il faut donc modifier son application pour y ajouter cette fonctionnalité

Mode opératoire :

  • Copier les éléments présents dans le répertoire lib de votre installation de jax-ws dans le répertoire lib de votre application
  • Ajouter la déclaration de la servlet dans votre application
  • Créer le fichier sun-jaxws.xml décrivant vos services

web.xml

<servlet>
    <servlet-name>jaxws-servlet</servlet-name>
    <servlet-class>com.sun.xml.ws.transport.http.servlet.WSServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>jaxws-servlet</servlet-name>
    <url-pattern>/ReponseService</url-pattern>
</servlet-mapping>
<listener>
    <listener-class>com.sun.xml.ws.transport.http.servlet.WSServletContextListener</listener-class>
</listener>

sun-jaxws

<endpoints>
    <endpoint name="ReponseService" 
              implementation="td4.Reponse"
              url-pattern="/ReponseService">
    </endpoint>
</endpoints>

Références

  1. Jax-ws
  2. Glassfish
  3. Metro