Servicios web en Java SE, Parte 2: Creación de servicios web SOAP

JAX-WS admite servicios web basados ​​en SOAP. La parte 2 de esta serie de cuatro partes sobre servicios web Java SE define un servicio web de conversión de unidades basado en SOAP, crea y luego verifica este servicio web localmente a través del servidor HTTP ligero predeterminado (discutido en la parte 1), interpreta el documento WSDL del servicio , y accede al servicio desde un simple cliente.

Definición de un servicio web de conversión de unidades

El servicio web de conversión de unidades, que he denominado UC, consta de cuatro funciones para convertir entre centímetros y pulgadas y entre grados Fahrenheit y grados Celsius. Aunque este ejemplo podría diseñarse como una sola clase de Java, elegí seguir las mejores prácticas al diseñarlo como una interfaz de Java y una clase de Java. El Listado 1 presenta la UCinterfaz del servicio web .

Listado 1. Interfaz de punto final de servicio del servicio web UC

package ca.javajeff.uc; import javax.jws.WebMethod; import javax.jws.WebService; @WebService public interface UC { @WebMethod double c2f(double degrees); @WebMethod double cm2in(double cm); @WebMethod double f2c(double degrees); @WebMethod double in2cm(double in); }

UCdescribe una interfaz de punto final de servicio (SEI) , que es una interfaz Java que expone las operaciones de una interfaz de servicio web en términos de métodos abstractos de Java. Los clientes se comunican con servicios web basados ​​en SOAP a través de sus SEI.

UCse declara un SEI a través de la @WebServiceanotación. Cuando se anota una interfaz o clase Java @WebService, todos los publicmétodos cuyos parámetros, valores de retorno y excepciones declaradas siguen las reglas definidas en la Sección 5 de la especificación JAX-RPC 1.1 describen las operaciones del servicio web. Debido a que sólo publiclos métodos se pueden declarar en las interfaces, la publicpalabra reservada no es necesario cuando se declara c2f(), cm2in(), f2c(), y in2cm(). Estos métodos son implícitamente public.

Cada método también está anotado @WebMethod. Aunque @WebMethodno es esencial en este ejemplo, su presencia refuerza el hecho de que el método anotado expone una operación de servicio web.

El Listado 2 presenta la UCImplclase del servicio web .

Listado 2. Bean de implementación de servicios del servicio web UC

package ca.javajeff.uc; import javax.jws.WebService; @WebService(endpointInterface = "ca.javajeff.uc.UC") public class UCImpl implements UC { @Override public double c2f(double degrees) { return degrees * 9.0 / 5.0 + 32; } @Override public double cm2in(double cm) { return cm / 2.54; } @Override public double f2c(double degrees) { return (degrees - 32) * 5.0 / 9.0; } @Override public double in2cm(double in) { return in * 2.54; } }

UCImpldescribe un Bean de implementación de servicios (SIB) , que proporciona una implementación del SEI. Esta clase se declara SIB mediante la @WebService(endpointInterface = "ca.javajeff.uc.UC")anotación. El endpointInterfaceelemento conecta este SIB a su SEI, y es necesario para evitar errores de tipo de puerto indefinidos al ejecutar la aplicación cliente que se presenta más adelante.

La implements UCcláusula no es absolutamente necesaria. Si esta cláusula no está presente, la UCinterfaz se ignora (y es redundante). Sin embargo, es una buena idea conservarlo implements UCpara que el compilador pueda verificar que los métodos de SEI se hayan implementado en el SIB.

Los encabezados del método del SIB no se anotan @WebMethodporque esta anotación se usa normalmente en el contexto del SEI. Sin embargo, si agregara un publicmétodo (que cumpla con las reglas de la Sección 5 de la especificación JAX-RPC 1.1) al SIB, y si este método no expone una operación de servicio web, anotaría el encabezado del método @WebMethod(exclude = true). Al asignar truea @WebMethod's excludeelemento, se evita que el método sea asociado a una operación.

Este servicio web está listo para ser publicado para que los clientes puedan acceder a él. El Listado 3 presenta una UCPublisheraplicación que realiza esta tarea en el contexto del servidor HTTP ligero predeterminado.

Listado 3. Publicación de UC

import javax.xml.ws.Endpoint; import ca.javajeff.uc.UCImpl; public class UCPublisher { public static void main(String[] args) { Endpoint.publish("//localhost:9901/UC", new UCImpl()); } }

La publicación del servicio web implica realizar una única llamada al método de EndPointclase de la Endpoint publish(String address, Object implementor)clase. El addressparámetro identifica el URI asignado al servicio web. Elegí publicar este servicio web en el host local especificando localhost(equivalente a la dirección IP 127.0.0.1) y el número de puerto 9901(que probablemente esté disponible). Además, he elegido arbitrariamente /UCcomo ruta de publicación. El implementorparámetro identifica una instancia de UCSIB.

El publish()método crea y publica un punto final para el implementorobjeto especificado en el dado addressy utiliza las implementoranotaciones de para crear documentos de lenguaje de definición de servicios web (WSDL) y esquema XML. Hace que la implementación de JAX-WS cree y configure la infraestructura de servidor necesaria basándose en alguna configuración predeterminada. Además, este método hace que la aplicación se ejecute de forma indefinida. (En máquinas con Windows, presione las teclas Ctrl y C simultáneamente para finalizar la aplicación).

Construyendo y verificando el servicio web

No es difícil construir el servicio web UC previamente definido. Primero, necesita crear una estructura de directorio adecuada que contenga los archivos apropiados. Realice esta tarea realizando los siguientes pasos:

  1. Dentro del directorio actual, cree un cadirectorio. Dentro ca, crea un javajeffdirectorio. Finalmente, dentro javajeff, cree un ucdirectorio.
  2. Copie el Listado 1 a un UC.javaarchivo fuente y almacene este archivo en formato ca/javajeff/uc.
  3. Copie el Listado 2 en un UCImpl.javaarchivo fuente y almacene este archivo en formato ca/javajeff/uc.
  4. Copie el Listado 3 en un UCPublisher.javaarchivo fuente y almacene este archivo en el directorio actual, que contiene el cadirectorio.

La siguiente tarea es compilar estos archivos fuente. Suponiendo que no ha cambiado de directorio, ejecute el siguiente comando para compilar estos archivos fuente en Java SE 9 (omitir --add-modules java.xml.wsen Java SE 6, 7 u 8):

javac --add-modules java.xml.ws UCPublisher.java

Si estos archivos de origen se compilan correctamente, ejecute el siguiente comando para ejecutar esta aplicación en Java 9 (omitir --add-modules java.xml.wsen Java SE 6, 7 u 8):

java --add-modules java.xml.ws UCPublisher

Mientras se ejecuta la aplicación, utilice un navegador web para verificar que este servicio web se esté ejecutando correctamente y para acceder a su documento WSDL. Inicie su navegador web favorito e ingrese la siguiente línea en la barra de direcciones:

//localhost:9901/UC

La Figura 1 muestra la página web resultante en el navegador web Google Chrome.

Figura 1. La página web de UC proporciona información detallada sobre el servicio web publicado

La Figura 1 presenta el servicio calificado del punto final del servicio web y los nombres de los puertos. (Observe que el nombre del paquete se ha invertido, en uc.javajeff.calugar de ca.javajeff.uc). Un cliente usa estos nombres para acceder al servicio.

La Figura 1 también presenta el URI de dirección del servicio web, la ubicación del documento WSDL del servicio web (el URI del servicio web con el sufijo de la ?wsdlcadena de consulta) y el nombre calificado por paquete de la clase de implementación del servicio web.

Interpretación del documento WSDL del servicio web

La ubicación del documento WSDL del servicio web UC se presenta como un enlace. Haga clic en este enlace para ver el documento WSDL, cuyo contenido se presenta en el Listado 4.

Listado 4. Documento WSDL de UC

Un documento WSDL es un documento XML con un definitionselemento raíz, lo que hace que un documento WSDL no sea más que un conjunto de definiciones. Este elemento incluye varios xmlnsatributos para identificar varios espacios de nombres estándar, junto con targetNameSpacey nameatributos:

  • El targetNamespaceatributo crea un espacio de nombres para todos los c2felementos definidos por el usuario en el documento WSDL (como el elemento definido a través del messageelemento con este nombre). Este espacio de nombres se utiliza para distinguir entre los elementos definidos por el usuario del documento WSDL actual y los elementos definidos por el usuario de los documentos WSDL importados, que se identifican mediante el importelemento WSDL . De manera similar, el targetNamespaceatributo que aparece en un schemaelemento de archivo basado en esquema XML crea un espacio de nombres para sus elementos de tipo simple definidos por el usuario, elementos de atributo y elementos de tipo complejo.
  • El nameatributo identifica el servicio web y se usa solo para documentar el servicio.

Anidado dentro definitionsson types, message, portType, binding, y serviceelementos: