Cliente SOAP con CXF

De vez en cuando reviso las estadísticas del blog y las entradas sobre Web Services son las que más visitas registran. Hola Mundo CXF necesitaba una entrada complementaria, que fuese la creación de un cliente que consumiese dicho servicio web. En esta entrada abordo esa creación.
Desde el año largo que ha pasado desde la anterior entrada ha aumentado mi cariño por Spring y las anotaciones. Partiendo del proyecto de esa entrada he modificado algo, por ejemplo he modificado el frontend del servicio, ya no utilizo el "simple server" en el beans.xml, paso a utilizar jaxws.
    <jaxws:endpoint id="server" implementor="es.sinjava.ws.impl.CrudImpl"
        address="/services" />
La combinación de maven-Spring-CXF nos va a permitir una brevedad y "elegancia" sin igual, permitiendonos consumir servicios SOAP de una forma transparente.
Nuestro destino es crear una librería que empaquete lo necesario para consumir un servicio web. Lo cual es una forma magnífica de facilitar el trabajo a los que se deban integrar con nosotros.
Toda la magia es crear un jar a la vez que se crea el war del servicio web. Para ello añadimos en el apartado build del pom el plugin apropiado:
<plugin>                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>2.3.1</version>
                <executions>
                    <execution>
                        <id>ws</id>
                        <phase>package</phase>
                        <goals>
                            <goal>jar</goal>
                        </goals>
                        <configuration>
                            <archive>
                                <addMavenDescriptor>false</addMavenDescriptor>
                            </archive>
                            <classifier>ws</classifier>
                            <includes>
                                <include>**/es/sinjava/model/*</include>
                                <include>**/es/sinjava/ws/*</include>
                            </includes>           
                        </configuration>
                    </execution>
                </executions>
   </plugin>
Lo que le estamos indicando es que cree un jar con el interfaz del servicio web y el modelo de datos. Que en nuestro sencillo proyecto coincide con alguno de los objetos que se mueven a través del servicio web.
Una vez hecho esto nos queda publicar el archivo jar a través del repositorio local. Para lo cual hacemos "mvn install" y lo tendremos disponible para el resto de desarrollos.
Como consumidor la opcion rápida es crear una clase con un main.  Pero por acercarme un poquito más a un caso real he creado un proyecto struts2-spring para realizar las llamadas al web services. CXF utiliza por debajo Spring y la integración con Spring es absoluta.
 He creado el proyecto cliente con maven. Lo cierto es que el proyecto distaba mucho de gustarme tal cual se generaba y ha habido que ajustarlo bastante.Esencialmente lo que he hecho ha sido "anotarlo" para hacerlo a mi gusto. Utilizo Spring para la factoria de action, pero en vez de xml utilizo anotaciones, sobre los propios "Action" de struts2  y en el application context quedan las referencias justas y la instanciación del web Services. Para mi es el equilibrio justo entre navegar entre xml y la comodidad de las anotaciones.
Como tampoco se trata la entrada de struts2 no profundizaré en ello. Al final pondré para descarga el proyecto.
Lo importante del proyecto es la forma de consumir el servicio web.
Añadimos al pom la dependencia del jar creado e instalado en el repo local en el proyecto anterior.
        <dependency>
            <groupId>es.sinjava</groupId>
            <artifactId>crudcxf</artifactId>
            <version>1.0.0</version>
            <classifier>ws</classifier>
        </dependency>  
 
Si descomprimes el jar verás que contiene unicamente el interfaz y la clase "User".
Como el cliente es un proyecto de Spring  necesitamos una linea únicamente:
<jaxws:client id="crudServices" serviceClass="es.sinjava.ws.Crud"
        address="http://localhost:8080/crudcxf/services" />
Creamos un cliente (bean) con un interfaz y le indicamos el "endpoint". Breve y sencillo.
En la clase que lo llama tenemos definido:
@Autowired
    private Crud crudServices;
y esa es toda la magia.
Desde el correspondiente método solo tengo que llamar a:
Long idUser= crudServices.createUser(userIn)
Como si crudServices fuese un servicio local, cuando en realidad lo que está haciendo es llamar a un servicio web. Más transparencia es imposible.
Como siempre, creo que lo mejor es ver el proyecto que te lo puedes descargar aquí. El comprimido tiene dos carpetas una con el servidor y otra con el cliente. Se despliegan las dos en el tomcat sin ninguna dependencia extra.
 Sólo he implementado una opción, la de crear usuarios, accesible desde el interfaz de la aplicación en "Otro usuario".. El web services implementa cuatro métodos.
En esta ocasión nosotros creábamos el servicio web y queríamos facilitar la integración. En otros ocasiones sólo dispondremos del wsdl del servicio web y tendremos que conectarnos a él. caso que estudiaremos en la siguiente entrada del blog.

Es posible que en los próximos dias reedite esta entrada....