jueves, 28 de julio de 2011

Cambiar la URL de conexión y establecer timeout a un Web Service JAX-WS

En el artículo anterior explicaba cómo realizar un cliente de Web Service JAX-WS con maven. Las herramientas de JAX-WS generan la url de conexión (endpoint) a partir de la url definida en el WSDL. Sin embargo, desplegar nuestro cliente en un entorno de producción final requerirá que realicemos una programación un poco más afinada y parametrizada permitiendo cambiar la url de conexión (típicamente hacia el servicio de producción final) y establecer timeouts.

Establecer los timeouts es extremadamente recomendable para prevenir que nuestra aplicación se quede "pegada" al servicio y eventualmente pueda bloquearse toda nuestra aplicación al quedarnos sin threads libres, ya que los tiempos máximos de espera suelen estar indefinidos por defecto.

Para especificar todo esto no es necesario regenerar el cliente. La práctica habitual es parametrizar los valores de URL, timeout de conexión y timeout de lectura (request timeout) usando algún fichero de configuración o similar, recuperarlos y especificarlos en nuestro proxy cliente.

A continuación dejo un snippet de código típico de ejemplo:


import javax.xml.ws.BindingProvider;
import com.sun.xml.ws.client.BindingProviderProperties;
...
int requestTimeout = 5000;
int connectTimeout = 500;
String nuevaUrl = "http://www.cestel.es/jdialer/dataProvider";

Jdialer jdialer = new Jdialer();
BindingProvider bp = (BindingProvider) jdialer.getDataproviderPort();
bp.getRequestContext().put(BindingProviderProperties.REQUEST_TIMEOUT,
		requestTimeout);
bp.getRequestContext().put(BindingProviderProperties.CONNECT_TIMEOUT,
		connectTimeout);
bp.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY,
				nuevaUrl);

16 comentarios :

  1. Hola, muchas gracias por tu artículo, sabes como hacerlo para un cliente JAXB?. Saludos

    ResponderEliminar
    Respuestas
    1. Hola:
      Gracias. ¿JAXB? No te entiendo. JAXB es un framework para mapeo entre XML y clases java. No veo dónde aplica un timeout ahí. De hecho JAX-WS usa JAXB para la serialización/deserialización (marshall/unmarshall) de los objetos Java en SOAP-XML. Tengo un artículo acerca de combinar XPath con JAXB, igual te interesa.
      Saludos.

      Eliminar
  2. Hola Samuel, muchas gracias por responder mi duda. Tengo un servicio SOA al cual le genero el cliente con JAXB con el siguiente comando: wsimport -d
    De ahi genero un jar que importo en mi proyecto.
    Yo necesito establecer un timeout para que si el servicio no envía una respuesta en un dicho tiempo, el flujo pueda continuar.

    Saludos

    ResponderEliminar
    Respuestas
    1. Precísamente "wsimport" es una herramienta de JAX-WS (no JAXB) y este artículo trata exactamente de cómo establecer el timeout en un cliente JAX-WS. "wsimport" te crea clases "stub": una clase para cada "service" y cada "port" declarado en el fichero WSDL (mantiene los nombres del WSDL). Las clases asociadas a los disponen de un método por cada una de las operaciones ("operation") incluidas en el correspondiente. Puedes hacer casting de la clase port que necesitas a "BindingProvider" y establecer las propiedades que comento en el artículo.

      En definitiva la solución que buscas, la tienes justo delante: ¡es este artículo!

      Espero que esto te haya aclarado tu duda.

      Eliminar
    2. Encontré la solución en tu artículo, pero sobre todo gracias a tu ayuda.
      Muchas gracias por compartir tu conocimiento.
      Saludos Samuel.

      W.G.

      Eliminar
  3. wsimport -d nombre_del_directorio wsdl_del_servicio

    ResponderEliminar
  4. Hola aqui les dejo la solucion para la generacion de un Cliente WS (proxy), con JAXWS...

    %JAXWS_HOME%/bin/wsimport ..\WebContent\wsdl\GestionDatosUsuarioWSService.wsdl -s . -verbose

    REQUERIMIENTO:
    - Tener el JAXWS en tu PC y referenciado en variables de entorno.
    - Ejecutarlo en la ruta de tu APP (dentro de SRC).
    - Acomodar la ruta del WSDL.

    Saludos.

    ResponderEliminar
  5. Y si quieres generar el WS en base al WSDL:

    I.- UBICARSE DESDE LA RUTA 'RAIZ' DEL PROYECTO EN DOS:
    - FORMA#1: wsimport WebContent\WEB-INF\wsdl\music.wsdl -s src -verbose
    - FORMA#2: %JAXWS_HOME%/bin/wsimport WebContent\WEB-INF\wsdl\music.wsdl -s src -verbose

    II.- UBICARSE DESDE LA RUTA 'SRC' DEL PROYECTO EN DOS:
    - FORMA#1: wsimport ..\WebContent\WEB-INF\wsdl\music.wsdl -s . -verbose
    - FORMA#2: %JAXWS_HOME%/bin/wsimport ..\WebContent\WEB-INF\wsdl\WEB-INF\music.wsdl -s . -verbose


    Por otro lado tu articulo me ayudo en el manejo del TimeOut que no habia manejado hasta le momento.

    Saludos

    ResponderEliminar
    Respuestas
    1. Gracias por tu aporte.
      Si te das una vuelta por el blog, comprobarás que ese tema ya ha sido tratado en el artículo JAX-WS Web Services con Maven. Yo prefiero concentrar todas las tareas de construcción en la propia herramienta de construcción (Maven), en lugar de tener que lanzar varios comandos por separado para generar un empaquetado. Así, cualquiera que se descargue el proyecto de un repositorio de código puede generar un empaquetado completo de un golpe con un simple "mvn package". Además, Maven te independiza de las herramientas de desarrollo (IDE's) y del Sistema Operativo.

      Un cordial saludo.

      Eliminar
    2. como lograste manejar el time out estoy tratando de manejar pero no se donde referencia la clase jdialer me puedes ayudar con esto por fa

      Eliminar
  6. oie loco donde esta implementada la clase Jdialer saludos

    ResponderEliminar
    Respuestas
    1. Hola "Anónimo":
      El código expuesto es, obviamente, un ejemplo. En mi caso, la clase Jdialer es la clase Proxy (o Stub) generado de mi ejemplo. En tu caso, tendrás una clase equivalente en función del WSDL con uno o más métodos getXXXXXXPort() (cambiese la XXXXXXX por el nombre de tu servicio, no es literal tampoco ;-)

      Saludos.

      Eliminar
  7. Este comentario ha sido eliminado por el autor.

    ResponderEliminar
  8. Hola disculpa en mi caso no tengo una clase proxy que implemente al wsdl, mi cliente lo creo en Java estoy usando restful la URL la obtengo de una bd donde tengo segistradas las url de los servicios web que estoy publicando como obtengo el puerto por que por lo que veo en esta parte de tu codigo obtienes el puerto? //BindingProvider bp = (BindingProvider) jdialer.getDataproviderPort();//necesito ayuda para implementar el timeout en mi cliente

    ResponderEliminar
    Respuestas
    1. Hola Yessica:
      Este articulo es relativo al API JAX-WS (para SOAP Web Services). Si estás usando RESTful Web Services, dependerá del API o Toolkit que uses. Por ejemplo, si usas Jersey Client API, puedes cambiar la URL (puerto incluído) a través de la clase "Client".

      Puedes encontrar más información en:
      http://jersey.java.net/
      http://crunchify.com/how-to-create-restful-java-client-with-jersey-client-example/

      Saludos.

      Eliminar
  9. Hola Samuel, use wsimport para generar mis clases, pero al colocar el timeout no lo toma, si imprimo el contenido del map que tiene el binding provider no aparecen las propiedades asociadas al timeout.

    Por favor me puedes ayudar

    Saludos

    Andrés

    Activity_Service activityWS = initActivityWS();

    ActivityQuery activityQuery = transformCreateActivityQuery(activityId);

    ListOfActivityQuery listActivityQuery = new ListOfActivityQuery();
    listActivityQuery.setActivity(activityQuery);

    ActivityQueryPageInput activityQueryPageInput = new ActivityQueryPageInput();
    activityQueryPageInput.setListOfActivity(listActivityQuery);

    BindingProvider bp = (BindingProvider) activityWS.getActivity();

    bp.getRequestContext().put(BindingProviderProperties.REQUEST_TIMEOUT,
    100);
    bp.getRequestContext().put(BindingProviderProperties.CONNECT_TIMEOUT,
    100);

    ResponderEliminar

Related Posts Plugin for WordPress, Blogger...
cookieassistant.com