Ejemplo sencillo de web service con maven y jax-ws metro

De ChuWiki

Vamos en este ejemplo a montar un servicio web usando maven y jax-ws/metro. Veremos también cómo montar un cliente que use ese Web Service. Lo haremos de forma que ambos ejecutables (servidor y cliente) puedan arrancarse como jar sueltos, sin necesidad de tener un contenedor de aplicaciones (como tomcat) arrancado.


Creación del proyecto maven[editar]

Puesto que vamoa a hacer un jar ejecutable normal, creamos nuestro proyecto maven de forma normal para el servidor. Vamos con una ventana de ms-dos al directorio donde queramos crear el proyecto y ejecutamos

mvn archetype:create -DgroupId=com.chuidiang -DartifactId=WsServer

Por supuesto, podemos poner en vez de com.chuidiang o WsServer los nombres que más nos gusten.

Una vez creado el proyecto, editamos el fichero pom.xml para poner las dependencias de la librería jax-ws de metro. Puesto que usaremos anotaciones, conviene asegurarse que usamos una versión de java que soporte anotaciones (1.5 o superior)

   <dependencies>
      ...
      <dependency>
         <groupId>com.sun.xml.ws</groupId>
         <artifactId>jaxws-rt</artifactId>
         <version>2.2.5</version>
         <scope>compile</scope>
      </dependency>
   </dependencies>
   <build>
      <plugins>
         <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
               <source>1.6</source>
               <target>1.6</target>
               <compilerVersion>1.6</compilerVersion>
            </configuration>
         </plugin>
         ...
      </plugins>
   </build>

Una vez generado el proyecto estamos listos para trabajar con él. El comando mvn eclipse:eclipse nos generará el proyecto de eclipse que simplemente tendremos que importar (ver Integración de Maven y Eclipse)


Haciendo y arrancando el servidor[editar]

Ahora, en eclipse, y siguiendo lo que se comentó en Ejemplo sencillo de web service con jax-ws, sólo nos queda hacer una clase que haga de Web Service y un main para arrancarla.

La clase del Web Service es una clase normalita con un par de anotaciones específicas de jax-ws.

package com.chuidiang.ejemplos.ws;

import javax.jws.WebMethod;
import javax.jws.WebService;

@WebService
public class UnWebService {
   @WebMethod
   public double suma(double a, double b) {
      return a + b;
   }
}

Mientras que la clase con el main() para arrancarla es muy sencilla, siendo EndPoint otra clase específica de jax-ws.

package com.chuidiang.ejemplos.ws;

import javax.xml.ws.Endpoint;

public class Main {
   /**
    * @param args
    */
   public static void main(String[] args) {
      Endpoint
            .publish("http://localhost:8080/UnWebService", new UnWebService());
   }
}

Ahora, desde eclipse sólo tenemos que arrancar este main. Si con el navegador miramos la dirección http://localhost:8080/UnWebService veremos algo como esto

Web Services

Endpoint	Information
Service Name:	{http://ws.ejemplos.chuidiang.com/}UnWebServiceService
Port Name:	{http://ws.ejemplos.chuidiang.com/}UnWebServicePort
Address:	http://localhost:8080/UnWebService
WSDL:	        http://localhost:8080/UnWebService?wsdl
Implementation class:	com.chuidiang.ejemplos.ws.UnWebService

que es un resumen de lo que ofrece nuestro web service y en http://localhost:8080/UnWebService?wsdl tendremos disponible el wsdl de dicho web service.


Generar el wsdl[editar]

Una vez arrancado tenemos, como hemos dicho, disponible el wsdl en http://localhost:8080/UnWebService?wsdl. Podemos descargarlo y también descargar los xsd que necesitemos de urls del estilo http://localhost:8080/UnWebService?xsd=1. Para saber estas URL, debemos ir mirando dentro del wsdl a ver qué referencias de este estilo hay en nuestro localhost.

Sin embargo, podemos también generar los wsdl usando la utilidad wsgen. Hay un plugin de maven que nos permite llamar a esta utilidad http://mojo.codehaus.org/jaxws-maven-plugin/wsgen-mojo.html

En nuestro pom.xml debemos poner lo siguiente

   <build>
      <plugins>
         <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>jaxws-maven-plugin</artifactId>
            <executions>
               <execution>
                  <id>UnIdCualquiera</id>
                  <goals>
                     <goal>wsgen</goal>
                  </goals>
                  <configuration>
                     <sei>com.chuidiang.ejemplos.ws.UnWebService</sei>
                     <genWsdl>true</genWsdl>
                     <resourceDestDir>src/main/wsdl/</resourceDestDir>
                  </configuration>
               </execution>
            </executions>
         </plugin>
      </plugins>
   </build>

Hemos puesto en el tag <sei> el nombre completo de la clase que hace de web service. <genWsdl> true para que genere el wsdl, en <resourceDestDir> dónde queremos que lo deje. Si no ponemos nada, lo hará en target/jaxws....

Ahora, ejecutando mvn install, aparte de compilar y generar nuestro jar, se generarán los wsdl que quedarán en el directorio src/main/wsdl.


Creando un cliente[editar]

Vamos ahora a crear un proyecto cliente de web service con maven. Creamos un nuevo proyecto de jar normal para maven y añadimos las mismas dependencias en el pom.xml y tampoco nos olvidamos de poner una versión de java igual o superior a la 1.5

   <dependencies>
      <dependency>
         <groupId>com.sun.xml.ws</groupId>
         <artifactId>jaxws-rt</artifactId>
         <version>2.2.5</version>
         <scope>compile</scope>
      </dependency>
   </dependencies>

   <build>
      <plugins>
         <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
               <source>1.6</source>
               <target>1.6</target>
            </configuration>
         </plugin>
      </plugins>
   </build>

Creado el proyecto maven, con mvn eclipse:eclipse podemos generar nuestro proyecto eclipse e importarlo para trabajar cómodamente (ver Integración de Maven y Eclipse)

Ahora necesitamos generar automáticamente las clases que nos ayuden a hacer el cliente con wsimport. Usaremos nuevamente el mismo plugin de maven, pero esta vez con el <goal> wsimport. El "problema" es que necesitamos el wsdl. Para ello, en nuestro proyecto maven creamos la carpeta src/wsdl por defecto y ponemos ahí los wsdl y xsd generados en el paso anterior. Podemos poner los wsdl en otra carpeta de nuestro gusto, pero entonces debemos indicar en la configuración del plugin dónde esta.

Para la ejecución del plugin wsimport ponemos en el pom.xml lo siguiente

   <build>
      <plugins>
         <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>jaxws-maven-plugin</artifactId>
            <executions>
               <execution>
                  <goals>
                     <goal>wsimport</goal>
                  </goals>
               </execution>
            </executions>
            <configuration>
               <sourceDestDir>src/main/java</sourceDestDir>
               <keep>true</keep>
            </configuration>
         </plugin>
         ...
      </plugins>
      ....
    </build>

Hemos puesto un tag <sourceDestDir> para indicar dónde queremos los fuentes (por defecto irán al directorio target) y hemos marcado <keep> a true para que mantenga dichos fuentes. Si no ponemos keep a true, maven generará los fuentes, los compilará y borrará los fuentes. En cualquier caso, teniendo los .class los fuentes no son necesarios, así que por defecto keep es false y es perfectamente válido.

Ahora un mvn install generará las clases necesarias para que podamos contruir nuestro cliente de web service. El resto del código es similar al desarrollado en Ejemplo sencillo de web service con jax-ws donde UnWebService y UnWebServiceService son clases generadas por wsimport.

package com.chuidiang.ejemplos.ws;

import java.net.MalformedURLException;
import java.net.URL;

import javax.xml.namespace.QName;

import com.chuidiang.ejemplos.ws.UnWebService;
import com.chuidiang.ejemplos.ws.UnWebServiceService;

/**
 * Ejemplo simple de cliente de web service. Requiere para funcionar que el
 * servidor este arrancado.
 * 
 * @author chuidiang
 */
public class Main {

   /**
    * @param args
    * @throws MalformedURLException
    */
   public static void main(String[] args) throws MalformedURLException {
      // Obtencion del cliente
      UnWebServiceService unWebServiceService = new UnWebServiceService(
            new URL("http://dominioreal:8080/UnWebService?wsdl"),    // URL real del web service.
            new QName("http://ws.ejemplos.chuidiang.com/",           // copiado del código generado por wsimport  
                  "UnWebServiceService"));
      UnWebService unWebService = unWebServiceService.getUnWebServicePort();

      // Ya podemos usarlo
      System.out.println(unWebService.suma(11.1, 22.2));

   }
}


Enlaces externos[editar]