vendredi 10 juin 2011

Déployer un Webservice avec la JSR-181 et CXF

La JSR-181 a facilité l'exposition de méthodes JAVA par webservice. Avec les outils et frameworks actuels, il n'a jamais été aussi simple de créer et d'exposer un service SOAP en JAVA. Voyons en pratique comment s'y prendre pour deployer un service SOAP en utilisant CXF, Maven, et n'importe quel serveur d'application (Jonas, JBoss, Websphere, Glassfish) ou conteneur de Servlet (Tomcat, Jetty).

La solution présentée est indépendante du serveur d'application utilisé et pourra être optimisée en fonction du serveur JEE cible.

La méthode que nous allons exposer permet de récupérer le résultat de la multiplication des nombres qui lui sont passés en paramètres :
package com.googlecode.avianey.cxf.v1;

public class Multiplier {

    public Long multiply(Long...in) {
        long result = 1l;
        for (long mult : in) {
            result *= mult;
        }
        return Long.valueOf(result);
    }

}

Quelques annotations suffisent...

Pour exposer la méthode en utilisant la JSR-181, il suffit de trois annotations :
WebService
Cette annotation permet de déclarer la classe comme webservice et et de configurer certains attributs du WSDL (portType, service et targetNamespace).
SOAPBinding
Cette annotation permet de spécifier le type d'encodage des messages SOAP encapsulés en HTTP.
WebMethod
Cette annotation permet de rendre visible une méthode de la classe. Une opération est associée à la méthode au niveau du WSDL.
package com.googlecode.avianey.cxf.v1;

import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;

@WebService(
    name = "multiplier",
    serviceName="multiplier",
    targetNamespace = "http://cxf.avianey.googlecode.com/V1")
@SOAPBinding(
    style = SOAPBinding.Style.DOCUMENT,
    use = SOAPBinding.Use.LITERAL,
    parameterStyle = SOAPBinding.ParameterStyle.WRAPPED)
public class Multiplier {

    @WebMethod( operationName = "multiply" )
    public Long multiply(Long...in) {
        long result = 1l;
        for (long mult : in) {
            result *= mult;
        }
        return Long.valueOf(result);
    }

}

...ou presque

Il nous reste à configurer CXF pour que le service soit exposé à l'adresse souhaitée. CXF s'appuyant sur Spring, il faut déclarer le ContextLoaderListener Spring au niveau du web.xml de l'application, puis paramétrer la Servlet CXF sur une URL. Veillez à bien être en Servlet Specification 2.4 au minimum, sans quoi le contexte Spring ne sera pas chargé avant l'initialisation de la Servlet CXF.

    contextConfigLocation/WEB-INF/beans.xml

    
        org.springframework.web.context.ContextLoaderListener
    



    CXFServlet
    
        org.apache.cxf.transport.servlet.CXFServlet
    
    1



    CXFServlet
    /services/*
Le fichier de configuration Spring permet de déclarer la classe Multiplier en tant que bean et de l'exposer en tant que endpoint sur une adresse précise au moyen des extensions JAX-WS.


    
    
    

    

    
    

Configuration Maven

La configuration des dépendances Maven est minimaliste :

    
        org.apache.cxf
        cxf-rt-frontend-jaxws
        ${cxf.version}
    
    
        org.apache.cxf
        cxf-rt-transports-http
        ${cxf.version}
    
    
        javax
        javaee-api
        6.0
        compile
    
Toutefois, CXF propose un plugin Maven (cxf-java2ws-plugin) permettant de générer le WSDL du service au moment de la compilation. Dans l'exemple ci dessous, le WSDL du service sera créé dans le répertoire :
  • /src/main/webapp/WEB-INF/wsdl/

    org.apache.cxf
    cxf-java2ws-plugin
    ${cxf.version}
    
        
            org.apache.cxf
            cxf-rt-frontend-jaxws
            ${cxf.version}
        
        
            org.apache.cxf
            cxf-rt-frontend-simple
            ${cxf.version}
        
    
    
        
            process-classes
            process-classes
            
                ${basedir}/src/main/webapp/WEB-INF/wsdl/multiplier.wsdl
                multiplier
                com.googlecode.avianey.cxf.v1.Multiplier
                true
                true
            
            
                java2ws
            
        
    

Déploiement sous Tomcat

Il ne reste plus qu'à démarrer notre serveur d'application. Le service est accessible à l'adresse {context-root}/{url-pattern}/{adresse} où :
  • context-root - Le contexte de la webapp
  • url-pattern - Le mapping de la Servlet CXF tel que défini dans le web.xml
  • adresse - L'adresse du endpoint telle que définie dans le fichier de configuration Spring/CXF

Liste des services exposés par CXF
Fork me on GitHub