Generación y consumo de Web Services JAX-WS


Generación del cliente del Servicio Web:  

En la implementación de un servicio web se debe tener presente que la generación del cliente y su consumo es parte fundamental. A continuación se describe el proceso de generación correcta de clientes Java para el consumo de servicios web.

El cliente de los servicios web puede ser generado a través de la utilidad proporcionada por Java llamada wsimport. Hay otros medios para generar este cliente como por ejemplo a través de Eclipse o Ant, sin embargo el cliente generado a través de Eclipse crea dependencias de librerías y genera varias clases de las cuales muchas de ellas no se utilizan en el consumo del servicio.
El cliente generado a través de la utilidad wsimport es mas limpio (es decir sólo contiene las clases necesarias para utilizar el servicio), es flexible y lo más importante, no genera dependencia con librerías diferentes a las estándares.
La ejecución por comandos de la utilidad wsimport es de la siguiente forma:


wsimport -keep -d ubicacionArchivosBinarios -s ubicacionArchivosFuentes direccionWSDL

Por ejemplo la ejecución del siguiente comando es válida:


wsimport -keep -d C:\workspace\ServiceEJBBeanClient\bin -s C:\workspace\ServiceEJBBeanClient\src “http://localhost:8888/WebService/ServiceEJBBean?wsdl”

parsing WSDL...
generating code...
compiling code...


En donde:
ubicacionArchivosBinarios = C:\workspace\ServiceEJBBeanClient\bin, esta ubicación es el directorio en donde estaran los archivos .class o compilados del cliente.
ubicacionArchivosFuentes = C:\workspace\ServiceEJBBeanClient\src, esta ubicación es el directorio en donde estaran los archivos .java o fuentes del cliente.
direccionWSDL = “http://localhost:8888/WebService/ServiceEJBBean?wsdl” Es la dirección en donde se encuentra desplegado el wsdl del servicio, inicialmente puede corresponder a una dirección de un ambiente de pruebas ya que posteriormente esta dirección es configurable por ser dinámica en el localizador.
Figura 1.0

A partir de las fuentes y compilados se genera un proyecto Java en Eclipse para generar el .jar ya que el wsimport no posee opciones para generar el jar directamente (al menos yo no las he encontrado).
Una vez generado el cliente se adiciona como librería al proyecto que consumirá el servicio.
Service Locator para consumo del Servicio Web:
Teniendo en cuenta que la ubicación del archivo wsdl del servicio web es dinámica, se construye una clase que consume un servicio web a partir de una dirección dinámica del wsdl y a partir del tipo de clase del servicio. Esta también sobreescribe la ubicación por defecto del wsdl quemada al momento de generar el cliente.
Esta clase se fundamenta en el patrón Service Locator e implementa el método findService que recibe como parámetros el tipo de clase del servicio (i.e ServiceEJBBeanService.class) y la dirección de ubicación del archivo de definición del servicio (i.e. http://localhost:8888/WebService/ServiceEJBBean?wsdl).

El código del localizador del servicio es el siguiente:



package com.service.web.manager;



import java.lang.reflect.Constructor;

import java.lang.reflect.InvocationTargetException;

import java.net.MalformedURLException;

import java.net.URL;

import java.util.Collections;

import java.util.HashMap;

import java.util.Map;

import org.apache.commons.beanutils.MethodUtils;

import org.apache.commons.logging.Log;

import org.apache.commons.logging.LogFactory;

import co.microtinto.web.exception.WSServiceLocatorException;

import javax.xml.namespace.QName;

/**

* WSServiceLocator.

* Service Locator para servicios web

* @author Yair Ivan Carreño Lizarazo

*

*/

public class WSServiceLocator {



    private static Log log = LogFactory.getLog(WSServiceLocator.class);

    private static WSServiceLocator instance;

    private static final String GET_SERVICE_NAME = "getServiceName";

    @SuppressWarnings("unchecked")

    private static Map serviceMap;



    static {

        try {

            instance = new WSServiceLocator();

        } catch (WSServiceLocatorException e) {

            log.error("WSManagerLocatorException: ");

        }

    }



    @SuppressWarnings("unchecked")

    private WSServiceLocator() throws WSServiceLocatorException {

        serviceMap = Collections.synchronizedMap(new HashMap());

    }



    /**

     * @return instance

     */

    public static synchronized WSServiceLocator getInstance() {

        return instance;

    }



    /**

     * @param <T>

     * @param service

     * @param endPoint

     * @return objectService

     */

    @SuppressWarnings("unchecked")

    public synchronized <T> T findService(Class<? extends T> service,

            String endPoint) {



        T objectService = null;

        if (serviceMap.containsKey(service)) {

            objectService = (T) serviceMap.get(service);

        } else {

            objectService = createService(service, endPoint);

            serviceMap.put(objectService, endPoint);

        }

        return objectService;

    }



    /**

     * @param <T>

     * @param service

     * @param endPoint

     * @return objectServiceWeb

     */

    @SuppressWarnings("unchecked")

    private static synchronized <T> T createService(Class<? extends T> service,

            String endPoint) {



        StringBuffer serviceName = new StringBuffer();

        T objectService = null;

        T objectServiceWeb = null;

        serviceName.append(GET_SERVICE_NAME);



        try {

            URL url = new URL(endPoint);

            T serviceClass = (T) Class.forName(service.getName()).newInstance();

            objectService = (T) MethodUtils.invokeExactMethod(serviceClass,

                    serviceName.toString(), null);

            Constructor constructor = service.getConstructor(new Class[] {

                    URL.class, QName.class });

            objectServiceWeb = (T) constructor.newInstance(new Object[] { url,

                    (QName) objectService });

        } catch (InstantiationException e) {

            log.error("InstantiationException" + e.getMessage());

        } catch (IllegalAccessException e) {

            log.error("IllegalAccessException" + e.getMessage());

        } catch (ClassNotFoundException e) {

            log.error("ClassNotFoundException" + e.getMessage());

        } catch (NoSuchMethodException e) {

            log.error("NoSuchMethodException" + e.getMessage());

        } catch (InvocationTargetException e) {

            log.error("InvocationTargetException" + e.getMessage());

        } catch (MalformedURLException e) {

            log.error("MalformedURLException" + e.getMessage());

        }

        return objectServiceWeb;

    }

}


Un posible cliente consumidor del servicio sería el siguiente:


public class ConsumerBean {

  

    private Log log = LogFactory.getLog(ConsumerBean.class);

    private static final String endPoint = "http://127.0.0.1:8888/WebService/ServiceEJBBean?wsdl";

  

    public String execute() {

        log.info("Ini ConsumerBean");

        ServiceEJBBeanService service =

                                        WSServiceLocator.getInstance().findService(ServiceEJBBeanService.class, endPoint);

        log.info("wsdl servicio: " + service.getWSDLDocumentLocation().toString());

        ServiceEJBBean port = service.getServiceEJBBeanPort();

        port.method();

        log.info("End ConsumerBean");

     return "";

    }

}


En donde la operación del servicio solicitada es method().
El proyecto Open Source lo encuentras en https://code.google.com/p/wsservicelocator/ bajo la licencia Apache License 2.0.

Thanks for your comment