Desarrollo de un cliente dinámico mediante las API de JAX-WS
JAX-WS (API de Java™ para servicios web XML) proporciona soporte para la invocación dinámica de operaciones de punto final de servicio.
Acerca de esta tarea
JAX-WS proporciona una nueva API de cliente Dispatch dinámico que es más genérica y ofrece más flexibilidad que la interfaz existente de invocación dinámica (DII) basada en JAX-RPC (API de Java para RPC basado en XML). La interfaz de cliente Dispatch, javax.xml.ws.Dispatch, es un cliente orientado a la mensajería XML cuyo uso está indicado para desarrolladores avanzados de XML que prefieren trabajar en el nivel XML utilizando construcciones XML. Para escribir un cliente Dispatch, debe tener experiencia con las API de cliente Dispatch, los tipos de objeto soportados y conocimientos de las representaciones de mensaje para el archivo WSDL (Web Services Description Language) asociado.
La API Dispatch puede enviar datos en la modalidad PAYLOAD o MESSAGE. Cuando se utiliza la modalidad PAYLOAD, el cliente Dispatch sólo es responsable de proporcionar los contenidos de <soap:Body> y JAX-WS incluye la carga útil de entrada en un elemento <soap:Envelope>. Cuando se utiliza la modalidad MESSAGE, el cliente Dispatch es responsable de proporcionar todo el sobre SOAP.
- javax.xml.transform.Source: Utilice los objetos Source para permitir a los clientes utilizar las API XML directamente. Puede utilizar los objetos Source con enlaces SOAP y HTTP.
- Objetos JAXB: utilice objetos JAXB para que los clientes puedan utilizar objetos JAXB generados a partir de un esquema XML para crear y manipular XML con aplicaciones JAX-WS. Los objetos JAXB sólo se pueden utilizar con enlaces SOAP y HTTP.
- javax.xml.soap.SOAPMessage: Utilice los objetos SOAPMessage para que los clientes puedan trabajar con mensajes SOAP. Sólo puede utilizar los objetos SOAPMessage con los enlaces SOAP de la versión 1.1 o 1.2.
- javax.activation.DataSource: Utilice los objetos DataSource para que los clientes puedan trabajar con mensajes MIME (Multipurpose Internet Mail Extension). Utilice DataSource sólo con enlaces HTTP.
Procedimiento
Resultados
Los puertos dinámicos de JAX-WS, que son los que se añaden utilizando el método de servicio addPort, podrían tener requisitos de memoria adicionales a partir de la Versión 8.0 de WebSphere Application Server. En releases anteriores, una única instancia de un puerto dinámico podría compartirse entre varias instancias de servicio. En la versión 8.x, ahora los puertos dinámicos tienen como ámbito la instancia del servicio que los ha añadido. Si un cliente JAX-WS tiene varias instancias de servicio que hacen referencia a un puerto dinámico del mismo nombre, esas instancias ya no se comparten. Esto puede potencialmente aumentar los requisitos de memoria para ese cliente. La memoria utilizada por los puertos dinámicos se libera cuando la instancia de servicio queda fuera del ámbito. Sin embargo, si surgen problemas relacionados con el mayor uso de memoria, es posible revertir el comportamiento de modo que los puertos dinámicos se vuelvan a compartir entre las instancias de servicio. Para ello, establezca la propiedad del sistema jaxws.share.dynamic.ports.enable en el valor true. Sin embargo, tenga en cuenta que al hacerlo pueden aparecer otros problemas, como por ejemplo la aplicación incorrecta de conexiones de conjuntos de políticas en los puertos dinámicos compartidos. Si establece este distintivo en true y aparecen algunos de estos problemas, deberá eliminar el valor del distintivo.
En releases anteriores, si la aplicación de Cliente de Asignación no proporcionaba una Acción SOAP, no se enviaba la Acción SOAP correcta en el mensaje de salida. En su lugar, la acción SOAP se establecía en una operación anónima. A partir de WebSphere Application Server Versión 8, si la acción SOAP no es proporcionada por la aplicación de cliente Dispatch, el entorno de ejecución de JAX-WS analiza el mensaje de salida. Determina la operación que se invoca y utiliza esa información para determinar el valor adecuado para la acción SOAP. La resolución de la operación del mensaje de salida se basa en el cuerpo SOAP y en la codificación de mensajes, como por ejemplo Doc/lit/bare o Doc/lit/wrapped. Dado que este análisis puede ser costoso, se puede establecer una propiedad. Para inhabilitar siempre el análisis, establezca la propiedad a nivel de sistema. Para inhabilitar el análisis según cada mensaje, establezca la propiedad en el contexto de mensaje de solicitud de JAX-WS. La propiedad se define como una constante org.apache.axis2.jaxws.Constants.DISPATCH_CLIENT_OUTBOUND_RESOLUTION con un valor de serie de jaxws.dispatch.outbound.operation.resolution.enable. El valor predeterminado de la propiedad es nulo, lo que se interpreta como la serie true, que habilita la resolución de la operación de salida. Establecer la propiedad en false inhabilita la resolución de la operación de salida. Si se inhabilita el análisis, la acción SOAP en el mensaje de salida se establece en una operación anónima como en los releases anteriores. Si el cliente proporciona una acción SOAP a través de las propiedades javax.xml.ws.BindingProvider de JAX-WS, SOAPACTION_USE_PROPERTY y SOAPACTION_URI_PROPERTY, se utilizará dicha acción SOAP. Por tanto, el análisis del mensaje de salida no se realiza sea cual sea el valor de la propiedad. Establecer explícitamente una acción SOAP por parte del cliente se considera una buena práctica, especialmente para el rendimiento del proveedor de servicios. Esta práctica impide que se analice el mensaje de entrada y que se dirija a la operación de punto final correcta.
Ejemplo
String endpointUrl = ...;
QName serviceName = new QName("http://com/ibm/was/wssample/echo/",
"EchoService");
QName portName = new QName("http://com/ibm/was/wssample/echo/",
"EchoServicePort");
/** Crear un servicio y añadirle, como mínimo, un puerto. **/
Service service = Service.create(serviceName);
service.addPort(portName, SOAPBinding.SOAP11HTTP_BINDING, endpointUrl);
/** Crear una instancia Dispatch desde un servicio.**/
Dispatch<SOAPMessage> dispatch = service.createDispatch(portName,
SOAPMessage.class, Service.Mode.MESSAGE);
/** Crear una solicitud SOAPMessage. **/
// componer un mensaje de solicitud
MessageFactory mf = MessageFactory.newInstance(SOAPConstants.SOAP_1_1_PROTOCOL);
// Crear un mensaje. Este ejemplo trabaja con SOAPPART.
SOAPMessage request = mf.createMessage();
SOAPPart part = request.getSOAPPart();
// Obtener los elementos SOAPEnvelope y de cabecera y cuerpo.
SOAPEnvelope env = part.getEnvelope();
SOAPHeader header = env.getHeader();
SOAPBody body = env.getBody();
// Construir la carga de datos del mensaje.
SOAPElement operation = body.addChildElement("invoke", "ns1",
"http://com/ibm/was/wssample/echo/");
SOAPElement value = operation.addChildElement("arg0");
value.addTextNode("ping");
request.saveChanges();
/** Invocar el punto final de servicio. **/
SOAPMessage response = dispatch.invoke(request);
/** Procesar la respuesta. **/