¿Qué es un servicio web? Descripción mediante WSDL

Cómo define WSDL 1.1 los servicios web y cómo crear modelos Java para verificar y transformar documentos WSDL

Serie de contenido:

Acerca de esta serie de artículos

Los servicios web son una característica importante de la tecnología Java™ en la informática empresarial. En esta serie de artículos, el consultor de servicios web y XML Denis Sosnovsky habla sobre las principales estructuras y tecnologías valiosas para los desarrolladores de Java que utilizan servicios web. Sigue los artículos de la serie para estar al día de las últimas novedades en este ámbito y saber cómo aplicarlas en tus propios proyectos.

Los servicios web para aplicaciones empresariales dependen en gran medida del uso de definiciones de servicios. Las definiciones de servicio describen el acuerdo básico entre el proveedor de servicios y cualquier consumidor potencial, detallando los tipos de funciones proporcionadas por el servicio y los mensajes dentro de cada función. Los proveedores y consumidores son libres de elegir cómo implementar sus objetos de intercambio en la medida en que los mensajes reales que envían se ajusten a la definición del servicio. El uso de una definición de servicio que describe cómo se intercambian los mensajes XML es lo que distingue a los servicios web de las tecnologías de programación distribuida anteriores.

Se han propuesto varios métodos para definir servicios web, pero WSDL 1.1 sigue siendo el enfoque más utilizado. WSDL 1.1 tiene algunas deficiencias, incluida una estructura demasiado compleja que dificulta la lectura para los no iniciados. También adolece de la falta de una definición formal autorizada, lo que ha llevado a sucesivos "refinamientos" que llenan algunos de los vacíos en el documento de especificación original. Como resultado, las pilas de servicios web intentan manejar documentos WSDL 1.1 de la forma más flexible posible. Esta flexibilidad puede aumentar la confusión a la hora de comprender WSDL 1.1, ya que los desarrolladores ven una amplia gama de estructuras WSDL sin ninguna indicación de qué enfoque es preferible.

En este artículo, le mostraremos cómo analizar documentos WSDL 1.1 y veremos las primeras partes del modelo Java para validar documentos WSDL y convertirlos al formato estándar.

Análisis de WSDL 1.1

Espacios de nombres utilizados

Este artículo utiliza:

  • prefijo wsdl para representar el espacio de nombres WSDL 1.1 http://schemas.xmlsoap.org/wsdl/;
  • el prefijo SOAP para el espacio de nombres http://schemas.xmlsoap.org/wsdl/soap/ utilizado por la extensión SOAP 1.1 para WSDL 1.1;
  • Prefijo xs para el espacio de nombres http://www.w3.org/2001/XMLSchema utilizado para las definiciones de esquemas XML.

La revisión 1.1 del WSDL, publicada a principios de 2001, ha sido técnicamente reemplazada por las recomendaciones del W3C WSDL 2.0, publicadas en 2007. WSDL 2.0 ofrece una estructura más limpia que WSDL 1.1 junto con una mayor flexibilidad. Pero WSDL 2.0 sufre el problema del huevo y la gallina: WSDL 2.0 no se usa ampliamente porque no cuenta con un soporte generalizado y, debido a que no se usa ampliamente, los desarrolladores de pilas de servicios web tienen pocos incentivos para respaldarlo. A pesar de todas sus deficiencias, WSDL 1.1 es suficientemente bueno para la mayoría de los propósitos.

La especificación WSDL 1.1 original era imprecisa con respecto al número de funciones utilizadas. Debido a que el objetivo de WSDL era trabajar con definiciones de servicios SOAP, también incluía soporte para funciones SOAP (como la codificación rpc) que luego resultaron no ser deseables. La Organización de Interoperabilidad de Servicios Web (WS-I) abordó estos problemas en el Perfil de referencia (BP), que proporciona orientación práctica para servicios web que utilizan SOAP y WSDL. BP 1.0 se aprobó en 2004 y BP 1.1 se lanzó en 2006. Este artículo cubre WSDL 1.1 según las recomendaciones de WS-I BP y no aborda características obsoletas reales, como la codificación rpc para SOAP.

Se supone que la estructura de los documentos XML está especificada por definiciones de esquemas XML. La especificación WSDL 1.1 original incluía una descripción del esquema, pero el esquema no coincide con las descripciones textuales en varios aspectos. Esto se corrigió posteriormente en una versión modificada del esquema, pero el documento WSDL 1.1 no se editó para reflejar este cambio. Luego, el equipo de BP WS-I decidió realizar aún más cambios en el esquema WSDL y creó lo que se promociona como pautas de mejores prácticas para este esquema resbaladizo. Los documentos escritos para una versión de un esquema generalmente no son compatibles con otras versiones (a pesar de usar el mismo espacio de nombres), pero afortunadamente la mayoría de las herramientas de servicios web ignoran en gran medida el esquema y aceptan lo que parezca razonable. (Consulte los enlaces a muchos esquemas WSDL en la sección).

Incluso la versión BP WS-I del esquema WSDL 1.1 no hace mucho para garantizar el cumplimiento de la especificación de los documentos WSDL 1.1. El diagrama no refleja todas las limitaciones del WS-I BP, especialmente con respecto al orden de los componentes. Además, el esquema XML no puede manejar muchos tipos de restricciones fáciles de establecer en los documentos (como atributos alternativos o elementos adicionales requeridos de un esquema independiente). Por lo tanto, verificar que un documento WSDL 1.1 se ajuste a la especificación WSDL 1.1 (modificada por WS-I BP) implica mucho más que simplemente realizar la validación del esquema XML. Volveremos a este tema más adelante en este artículo. Pero primero, veamos la estructura de las descripciones de servicios WSDL 1.1.

Descripción Componentes

Los documentos WSDL 1.1 utilizan un elemento raíz fijo y con un nombre conveniente . Dentro de este elemento raíz, el espacio de nombres WSDL 1.1 define un elemento secundario "pasivo" (simplemente un enlace a documentos WSDL 1.1 individuales) y cinco elementos secundarios "activos" (que en realidad constituyen la descripción del servicio):

  • hace referencia a un documento WSDL 1.1 independiente con descripciones que se incluirán en ese documento;
  • define tipos o elementos XML utilizados para mensajería;
  • define el mensaje real en términos de tipos o elementos XML;
  • define un conjunto abstracto de operaciones realizadas por el servicio;
  • define la implementación real utilizando protocolos y formatos específicos;
  • Define el servicio como un todo, que normalmente incluye uno o más elementos. con información de acceso a elementos .

También hay un elemento , que se puede utilizar con fines de documentación como primer elemento secundario , así como el primer hijo de cualquiera de los elementos anteriores.

Una descripción completa de un servicio normalmente requiere al menos un elemento de cada uno de estos tipos, excepto , pero no es necesario que estén todos en el mismo documento. Para ensamblar un WSDL completo a partir de múltiples documentos, puede usar , que permite subdividir las descripciones para adaptarlas a las necesidades de la organización. Por ejemplo, los primeros tres elementos de la descripción ( , Y ) juntos constituyen una descripción completa de la interfaz de servicio (quizás definida por el grupo de arquitectura), por lo que tiene sentido mantenerlos separados de los elementos orientados a la implementación. Y . Todas las pilas de servicios web principales admiten la división de descripciones en múltiples documentos WSDL.

El Listado 1 muestra un ejemplo de una descripción de servicio WSDL dividida en dos documentos WSDL, de modo que los componentes de descripción de la interfaz estén contenidos en el archivo BookServerInterface.wsdl y los componentes de implementación estén contenidos en el archivo BookServerImpl.wsdl. El Listado 1 muestra BookServerInterface.wsdl.

Listado 1. BookServerInterface.wsdl
Definición de la interfaz del servicio de libros. ... ... Implementación del servicio de libros. Esto crea una biblioteca inicial de libros cuando se carga la clase, luego admite llamadas a métodos para acceder a la información de la biblioteca (incluida la adición de libros nuevos). Consigue el libro con un ISBN particular. ... Añade un nuevo libro.

El Listado 2 muestra BookServerImpl.wsdl. Elemento al principio importa la descripción de la interfaz BookServerInterface.wsdl.

Listado 2. BookServerImpl.wsdl
Definición de implementación real del servicio de libros. ...

Además de las definiciones de elementos (y atributos) en el espacio de nombres WSDL 1.1, WSDL 1.1 también define elementos adicionales. Están diseñados para llenar celdas específicas en las descripciones de servicios WSDL 1.1 para transmitir información adicional necesaria para un tipo particular de servicio. Los únicos elementos adicionales de WSDL 1.1 que todavía se utilizan ampliamente son los enlaces para SOAP 1.1 (estos se introducen en los elementos Y ), que se definieron en la especificación WSDL 1.1 original, y para SOAP 1.2, definido por una especificación separada en 2006.

Detalles del componente

Elemento contiene todas las definiciones XML utilizadas para los mensajes, como uno o más elementos . (WSDL permite alternativas de esquemas XML para estas definiciones, pero la mayoría de las pilas solo admiten esquemas XML). Si es necesario, elementos puede usar o para incluir otros esquemas externos al WSDL (así como hacer referencia a esquemas separados dentro del mismo WSDL).

Dado que un elemento puede contener cualquier número de definiciones de esquema, no hay razón para utilizar más de un elemento en un documento WSDL . al elemento se encuentra en la parte superior de BookServerInterface.wsdl.

Además Y , todos los componentes de nivel superior de un documento WSDL reciben nombres individuales utilizando el atributo de nombre requerido. Cuando se utiliza el atributo targetNamespace en el elemento raíz documento (que suele ser mejor), los nombres de estos componentes se definen en este espacio de nombres de destino. Esto significa que al definir un nombre, es suficiente asignar la parte simple o "local" del nombre, pero las referencias a ese componente deben calificar el nombre usando un prefijo de espacio de nombres o usando un espacio de nombres predeterminado. La Figura 1 muestra los vínculos más importantes entre los componentes WSDL, con líneas continuas que representan vínculos por nombre completo y líneas de puntos que representan vínculos por nombre utilizados para la identificación sin calificación de espacio de nombres.

Figura 1. Relaciones entre los componentes WSDL

Mensajes representados por elementos. , se encuentran en el núcleo de las descripciones de servicios WSDL. Elementos son descripciones de datos XML transferidos entre el cliente y el proveedor de servicios. cada elemento contiene cero o más (normalmente uno) elementos secundarios . Cada elemento de parte requiere su propio atributo de nombre (único dentro ) y uno de los atributos de elemento o tipo que hace referencia a la definición del esquema de datos XML. Múltiples elementos se muestra en , después del elemento en BookServerInterface.wsdl.

Elementos definir una interfaz de servicio abstracta en términos de mensajes enviados y recibidos del servicio. Elementos contener cualquier número de elementos secundarios . Cada elemento hijo requiere su propio atributo de nombre (WS-I BP requiere que sea único dentro ) y contiene uno o más elementos secundarios que describen los mensajes utilizados por la operación. Los elementos secundarios son de tres tipos, correspondientes a diferentes usos:

  • : datos enviados por el cliente al proveedor de servicios como entrada a la operación;
  • : datos devueltos al cliente por el proveedor del servicio como resultado de una operación;
  • : Datos devueltos al cliente por el proveedor del servicio cuando se produce un error durante el procesamiento.

WSDL 1.1 define varios patrones de interacción entre un cliente y un proveedor de servicios, representados por varias secuencias de elementos secundarios. Y , pero no todos los modelos están lo suficientemente bien definidos como para implementarlos. BP WS-I permite sólo dos modelos: operaciones de solicitud-respuesta, donde debería y operaciones unidireccionales que contienen solo . En el caso de operaciones de solicitud-respuesta (con diferencia, el tipo más común) detrás de los elementos Y puede ir seguido de cualquier número de elementos .

cada elemento , o se refiere a una descripción de mensaje a través del atributo de mensaje requerido. Esta es una referencia calificada de espacio de nombres, por lo que generalmente requiere agregar un prefijo. Se pueden ver ejemplos en: por ejemplo, cuando un elemento utilizado en la descripción de la operación getBook. (El prefijo tns sirve como definición del elemento raíz con el mismo URI de espacio de nombres que el atributo targetNamespace).

De muchas maneras puede considerarse el equivalente lógico de una interfaz Java, por lo que los elementos son equivalentes a métodos, elementos - parámetros del método, elementos - los resultados de los métodos y los elementos - excepciones marcadas. Estas asignaciones se utilizan al generar código Java a partir de WSDL, al igual que la mayoría de las herramientas que generan WSDL a partir de código Java existente.

Comparación de SOAP 1.1 y 1.2

SOAP 1.1 se ha utilizado ampliamente para servicios web desde que se publicó la especificación en 2000. SOAP 1.2 se desarrolló con un apoyo más amplio de la industria a través del W3C y se publicó como estándar oficial del W3C en 2007. SOAP 1.2 está mejor documentado y es más limpio que SOAP 1.1, con algunos de los aspectos desagradables de 1.1 eliminados quirúrgicamente. A pesar de esta estructura limpia, para la mayoría de los servicios web hay poca diferencia práctica entre ellos. Quizás la característica más importante de SOAP 1.2 es que es la única forma oficialmente admitida de aprovechar el soporte mejorado de SOAP para archivos adjuntos de empaquetado optimizado binario XML (XOP) y el mecanismo de optimización de transmisión de mensajes SOAP (MTOM). en un bucle Servicios web Java He estado usando SOAP 1.1 hasta ahora porque algunas pilas antiguas no soportan SOAP 1.2, pero para desarrollar nuevos servicios web, 1.2 es probablemente una mejor opción.

Elementos representar una instancia de una interfaz abstracta definida , que es visible al principio de BookServerImpl.wsdl. El atributo de tipo contiene el nombre completo del tipo de puerto implementado en el enlace.

Elementos secundarios Contiene información detallada sobre cómo se implementa el tipo de puerto. Los elementos secundarios del espacio de nombres WSDL corresponden a elementos y debería usar el mismo valor de nombre – y no enlaces con aclaración del espacio de nombres, como en el caso . esta conexión se muestra mediante líneas de puntos en el nivel . La misma relación por nombre se aplica a los elementos secundarios. / / elementos . A pesar de esta reutilización de los mismos nombres de elementos, el contenido de estos elementos difiere significativamente cuando son elementos secundarios. , no el elemento .

Las extensiones definidas por WSDL entran en juego en . elemento hijo utilizado en una definición de servicio SOAP (el único tipo de servicio permitido por WS-I BP, aunque WSDL 1.1 también permite enlaces HTTP). Este artículo utiliza el atributo de transporte requerido para especificar el tipo de transporte utilizado por el enlace. (HTTP, como se ve en el valor http://schemas.xmlsoap.org/soap/http en , es la única opción permitida por WS-I BP). El atributo de estilo opcional le permite elegir entre los estilos rpc y de documento. para representar datos XML (el valor más común de documento corresponde a mensajes que utilizan elementos de definición de esquema en lugar de tipo).

Dentro de cada elemento hijo elemento elemento se puede utilizar para especificar el valor de una SOAPAction con el fin de identificar solicitudes para llamar a esa operación (y potencialmente también para anular la elección de documento o estilo rpc especificado por el elemento , aunque BP WS-I prohíbe dicho uso). Cada elemento hijo / / contiene otro elemento adicional, que siempre es un elemento (lo que indica que los datos del mensaje se envían en el cuerpo del mensaje SOAP; los datos e incluso los errores también se pueden enviar en los encabezados SOAP, aunque no lo recomiendo) para o , o su equivalente , usado con .

El último componente de la descripción del servicio WSDL es el elemento , que consta de un grupo de elementos . cada elemento asocia la dirección de acceso con . La dirección de acceso está contenida en un elemento adicional anidado .

Trabajar con WSDL

No es sorprendente que con todas las variaciones en los esquemas y reglas para los documentos WSDL 1.1, muchos documentos no sigan las mejores prácticas de BP WS-I. El respaldo de muchas desviaciones de las mejores prácticas en todas las pilas de servicios web ha ayudado a perpetuar el uso de diseños obsoletos o incorrectos, lo que ha llevado a la propagación de malas prácticas en toda la industria. Y definitivamente no soy inmune a esta infección: mientras miraba los documentos WSDL que proporcioné como ejemplos de código para esta serie, me sorprendió descubrir que ninguno de ellos era completamente correcto.

Entonces, cuando decidí escribir este artículo, pensé que sería bueno incluir una herramienta que le permita comparar los documentos WSDL con las mejores prácticas. Parecería que esto está a sólo un paso de convertir documentos WSDL al formato correcto, siempre que el WSDL original esté libre de errores. Pero hubo mucho más trabajo del que había planeado originalmente e incluiré información completa sobre este modelo en los próximos dos artículos de esta serie.

Se han creado muchos modelos diferentes para trabajar con documentos WSDL en Java, incluido el ampliamente utilizado Lenguaje de descripción de servicios web para Java Toolkit (WSDL4J), que es una implementación de referencia de JSR 110 (consulte la sección). Ninguno de estos modelos se ajusta a lo que me propuse hacer, debido a la doble naturaleza del problema: primero, leer documentos WSDL en cualquier forma semiinteligente e informar errores y desviaciones de las mejores prácticas, y segundo, escribir WSDL sin errores. documentos reformateados en una forma consistente con recomendaciones prácticas. WSDL4J, por ejemplo, no conserva el orden de los elementos de entrada para que se puedan informar problemas de orden, y no maneja definiciones de esquemas, por lo que no puede usarse directamente para verificar referencias de elementos. . Así que tuve que elegir entre un planteamiento del problema más realista y escribir mi propio modelo. Naturalmente, decidí escribir mi propio modelo.

Modelo WSDL

Validación y Verificación

En este artículo utilizo el término verificación para referirse a la verificación de la validez de un documento WSDL, porque el término alternativo validación, comúnmente utilizado para documentos XML, significa comparar documentos con una definición de esquema.

Anteriormente, implementé parcialmente un modelo WSDL para usarlo con el enlace de datos JiBX como parte del proyecto JiBX/WS. Este modelo es solo de salida e incluye una cantidad relativamente pequeña de clases que, en algunos casos, agregan datos de elementos anidados de una estructura XML WSDL ( combinado con un elemento hijo , , Y adentro en combinación con el elemento o etc.). Esta estructura de clases compacta facilitó la creación del subconjunto de documentos WSDL compatibles con el marco, pero cuando comencé a considerar la creación de una herramienta de verificación y reestructuración basada en este modelo, me di cuenta de que el modelo para admitir la entrada de WSDL posiblemente mal estructurado Necesita estar más cerca de la presentación XML.

Otra opción es generar código a partir del esquema WS-I BP para WSDL 1.1. Después de ver esto, me di cuenta de que simplemente usar las clases generadas directamente generaría confusión, ya que el diseño incluye tipos redundantes, así como algunas construcciones incómodas que se utilizan para representar diferentes modelos de mensajería (algunos de los cuales luego fueron prohibidos por el WS- Texto I BP) .

Así que terminé compilando las clases a mano, aunque el resultado fue casi el mismo que si hubiera comenzado con el código generado a partir del esquema y simplemente redujera la duplicación y la complejidad innecesarias. El enlace de datos JiBX admite múltiples enlaces a las mismas clases, por lo que pude crear un enlace de entrada para manejar toda la gama de variaciones permitidas por cualquier versión de WSDL 1.1, aunque configurar el enlace de salida para la salida WSDL solo fue una forma de mejores prácticas.

El Listado 3 muestra la parte de la clase Definiciones correspondiente al elemento raíz. .

Listado 3. Clase de definiciones (parcial)
Las definiciones de clases públicas extienden ElementBase ( /** Lista de elementos secundarios en el orden esperado. */ enumeración estática AddState (inválido, importaciones, tipos, mensaje, tipo de puerto, enlace, servicio); /** Lista de nombres de atributos permitidos. */ pública estática final StringArray s_allowedAttributes = new StringArray(new String ( "name", "targetNamespace" )); /** Validación del contexto a utilizar */ private ValidationContext. m_validationContext; /** Estado actual (usado para verificar el orden en el que */ /** se agregan los niños). */ privado AddState m_state; /** El nombre de esta definición. */ cadena privada m_name; /** Espacio de nombres WSDL de destino. */ cadena privada m_targetNamespace; /** Lista de todos los elementos secundarios importados. */ Lista privada m_imports = nueva lista de matrices (); /** Lista de todos los tipos de elementos secundarios. */ Lista privada m_types = nueva lista de matrices (); /** Lista de todos los mensajes de elementos secundarios. */ Lista privada m_messages = nueva lista de matrices (); /** Lista de todos los elementos secundarios de portType. */ Lista privada M_portTypes = nueva ArrayList (); /** Lista de todos los enlaces de elementos secundarios. */ Lista privada m_bindings = nueva lista de matrices (); ();< m_state.ordinal()) { // отчет о дочерних элементах вне ожидаемого порядка m_validationContext.addWarning ("Child element of wsdl:definitions out of order", comp); m_state = AddState.invalid; } } } ... /** * Добавление немаршаллизированного дочернего элемента wsdl:message. * Здесь же сообщение индексируется по имени для доступа с целью валидации. * * @param child */ public void addMessage(Message child) { checkAdd(AddState.message, child); m_messages.add(child); addName(child.getName(), child, m_nameMessageMap); } ...

... /** * Comprueba los estados de transición entre diferentes tipos de elementos secundarios. * Si los elementos no están en el orden esperado, * el primer elemento fuera del orden esperado se marca para el informe.

* @param state nuevo agregar estado * @param comp componente de elemento */ private void checkAdd(AddState state, ElementBase comp) ( if (m_state != state) ( if (m_state == null || (m_state != AddState.invalid && state.ordinal() > m_state.ordinal())) ( // pasar a otro tipo de elementos secundarios m_state = state; ) else if (state.ordinal()

La organización de los datos de los elementos secundarios muestra cómo el modelo admite tanto el formulario de entrada general como el formulario de salida de acuerdo con las mejores prácticas. En lugar de una lista única de hijos de todos los tipos, se utilizan listas separadas para cada tipo. El enlace de entrada JiBX trata los elementos secundarios como un conjunto desordenado y llama a un definidor específico del tipo de elemento cada vez que un elemento secundario está fuera de lugar. En lugar de reemplazar cualquiera de los valores anteriores, el configurador agrega la instancia a la lista escrita, como se ve en el definidor addMessage() que se usa en elementos secundarios. . Cada configurador también ejecuta una verificación de estado para detectar elementos desordenados. Se permiten atributos y elementos adicionales en cualquier elemento WSDL (generalmente todos los atributos o elementos que no utilizan el espacio de nombres WSDL 1.1). Ejemplos de dichos elementos adicionales son las configuraciones de WS-Policy integradas en los documentos WSDL de artículos anteriores de esta serie, así como enlaces a políticas reales. Es mejor que estos elementos adicionales precedan a cualquier elemento secundario del espacio de nombres WSDL 1.1, y así es como se manejan en el enlace de salida. El enlace de entrada maneja elementos y atributos adicionales utilizando código de clase base de las clases de elementos WSDL que no se muestran en y permite que los elementos sigan en cualquier orden (generando una advertencia si siguen a un elemento del espacio de nombres WSDL 1.1).

El modelo maneja elementos conocidos mediante enlaces separados para cada espacio de nombres adicional, cada uno con su propio conjunto de clases. Analizaré el manejo de estos elementos adicionales con más detalle en el próximo número.

Se realiza alguna verificación básica de los datos WSDL a medida que se agregan objetos no ordenados correspondientes a elementos a la estructura de árbol del documento WSDL, como se muestra en el código addMessage() al final de . Este código utiliza el método checkAdd() para verificar el orden de los elementos secundarios y el método addName() para verificar que se presenta un nombre válido (el texto coincide con el tipo de esquema NCName y el valor es único dentro del tipo de elemento) y asigna el nombre al objeto. Pero esto es sólo comprobar la información más básica de un elemento individual; Se requiere un código de verificación adicional para verificar otras propiedades de cada elemento y las relaciones entre elementos.

JiBX le permite llamar a controladores de extensiones personalizados como parte del proceso de organización y organización. Para ejecutar la lógica de verificación, el modelo WSDL utiliza uno de estos controladores adicionales, el método post-set. El método post-set se llama después de que el objeto asociado haya terminado de desclasificarse, por lo que suele ser una buena manera de realizar comprobaciones de tipo de verificación de objetos. En el caso de la verificación WSDL, el enfoque más simple es realizar toda la verificación de objetos desde un único método post-set en el elemento raíz. . Este enfoque evita el problema de hacer referencia directa a los componentes del documento WSDL cuando los componentes no aparecen en el orden esperado.

Otros complementos

Este artículo proporciona los conceptos básicos de la estructura y el uso de WSDL y una introducción al modelo de datos Java para WSDL, que está diseñado para respaldar la verificación de documentos WSDL y su transformación en un formato de mejores prácticas.

El próximo artículo continuará con este tema analizando los problemas que se encuentran comúnmente al escribir aserciones de WS-Policy y WS-SecurityPolicy. También examinará más de cerca el modelo WSDL y el proceso de verificación, incluida la ampliación del modelo para incluir aserciones WS-Policy/WS-SecurityPolicy integradas en el WSDL.

Página 2 de 3

Descripción usando WSDL

SOAP funciona muy bien si se sabe todo sobre el servicio web. Sin embargo, este no es siempre el caso. El medio para describir la interfaz para acceder a un servicio web es el lenguaje WSDL (lenguaje de descripción de servicios web). Este estándar fue desarrollado conjuntamente por IBM, Microsoft y webMethods. Cada una de estas tres empresas tenía su propio enfoque para desarrollar un estándar para describir servicios web: IBM creó NASSL, Microsoft desarrolló SCL y webMethods ideó WIDL.

El resultado de su colaboración fue la versión 1.1 del lenguaje WSDL. Respecto al W3C, cabe destacar que, al igual que con SOAP, el consorcio del W3C basándose en la versión 1.1 desarrolló WSDL 1.2, que ahora es una recomendación del W3C. La descripción WSDL de un servicio web contiene toda la información necesaria para utilizar el servicio, incluidos los métodos disponibles y sus parámetros. Esta información está contenida en los cinco elementos siguientes:

  • - protocolos compatibles.
  • - Mensajes de servicio web (solicitud, respuesta).
  • Todos los métodos disponibles.
  • - URI de servicio.
  • - tipos de datos utilizados.

Toda esta información se almacena en el elemento raíz de la descripción WSDL. La siguiente lista muestra un ejemplo de una descripción WSDL de un servicio web.

Descripción WSDL del servicio web

Sí... no puedes resolverlo sin un vaso, pero este es uno de los archivos WSDL más simples (!). Desafortunadamente, uno de los inconvenientes de la extensión SOAP para PHP 5 es que, a diferencia de otras implementaciones SOAP, no genera automáticamente descripciones WSDL (al menos no todavía). Seguramente este fallo será corregido en futuras versiones de PHP.

¡Por cierto!

Para generar automáticamente la descripción WSDL, puede utilizar implementaciones alternativas del protocolo SOAP en PHP:

Búsqueda de directorio mediante UDDI

Ahora que sabemos cómo obtener información sobre un servicio web y cómo consultarlo, necesitamos aprender cómo encontrar dicho servicio. Para ello existe algo similar a las Páginas Amarillas, es decir, los registros UBR (Universal Business Registries), directorios de servicios web.

Existen varios registros de este tipo, incluidos los de IBM, Microsoft, NTT-Com y SAP. Estos registros sincronizan sus datos, por lo que puedes utilizar cualquiera de ellos. La versión actual del estándar UDDI es UDDI 3.0, aunque la mayoría de las implementaciones utilizan la versión 2. Los desarrolladores de este estándar incluyen empresas gigantes como HP, Intel, Microsoft y Sun.

Para interactuar con UBR hay dos tipos de API: API de consulta y API de publicación. Interfaz La API de consulta (Solicitud) es para solicitar servicios en registros UBR y la interfaz La API de publicación permite a los desarrolladores registrar sus servicios. Parece que es sólo cuestión de tiempo antes de que el contenido de los registros se llene de spam :)

¡Por cierto!

Existen registros de prueba diseñados para probar los registros de servicios antes de colocarlos en los registros "reales".

Así es como se ve una solicitud de servicio web:

ordenarPorNombreAsc ordenarPorFechaDesc %guid%

En el ejemplo anterior, puede ver que la solicitud UDDI está encapsulada en un mensaje SOAP, por lo que parece bastante familiar. La respuesta a la solicitud también es un documento SOAP, que se muestra a continuación:

Visita guiada a los servicios web Servicios web de muestra para libro de visitas guiadas Visita Guiada Servicio de Cotización de Bolsa

Instalación

Instalar la extensión SOAP para PHP5 es bastante fácil. En Windows, este módulo se encuentra en el subdirectorio ext del directorio de instalación de PHP. Para usarlo, necesitas agregar la siguiente línea al archivo php.ini: extensión=php_soap.dll Para funcionar, este módulo requiere que esté incluido en PHP 5 por defecto, al menos en la versión de Windows.

El título del tema es realmente una pregunta, porque... Yo mismo no sé qué es y por primera vez intentaré trabajar con ello en el marco de este artículo. Lo único que puedo garantizar es que el código que se presenta a continuación funcionará, pero mis frases serán solo suposiciones y conjeturas sobre cómo entiendo todo esto yo mismo. Entonces, vámonos...

Introducción

Necesitamos comenzar con por qué se creó el concepto de servicios web. Cuando apareció este concepto en el mundo, ya existían tecnologías que permitían que las aplicaciones interactuaran a distancia, donde un programa podía llamar a algún método en otro programa, que podía ejecutarse en una computadora ubicada en otra ciudad o incluso país. Todo esto se abrevia como RPC (Llamada a procedimiento remoto). Los ejemplos incluyen tecnologías CORBA y, para Java, RMI (invocación de método remoto). Y todo parece ir bien en ellos, especialmente en CORBA, porque... Puedes trabajar con él en cualquier lenguaje de programación, pero todavía faltaba algo. Creo que la desventaja de CORBA es que funciona a través de algunos de sus propios protocolos de red en lugar de un simple HTTP, que atravesará cualquier firewall. La idea del servicio web era crear un RPC que se insertaría en paquetes HTTP. Así comenzó el desarrollo de la norma. Cuáles son los conceptos básicos de esta norma:
  1. JABÓN. Antes de llamar a un procedimiento remoto, debe describir esta llamada en un archivo XML en formato SOAP. SOAP es simplemente uno de los muchos códigos XML que se utilizan en los servicios web. Todo lo que queremos enviar a algún lugar a través de HTTP primero se convierte en una descripción XML SOAP, luego se coloca en un paquete HTTP y se envía a otra computadora en la red a través de TCP/IP.
  2. WSDL. Hay un servicio web, es decir. un programa cuyos métodos se pueden llamar de forma remota. Pero el estándar requiere que este programa vaya acompañado de una descripción que diga que "sí, tienes razón: este es realmente un servicio web y puedes llamar a tales o cuales métodos desde él". Esta descripción está representada por otro archivo XML, que tiene un formato diferente, concretamente WSDL. Aquellos. WSDL es sólo un archivo XML que describe un servicio web y nada más.
¿Por qué preguntas tan brevemente? ¿No puedes ser más específico? Probablemente sea posible, pero para hacerlo tendrás que recurrir a libros como T. Mashnin, "Java Web Services". Allí, a lo largo de las primeras 200 páginas, se encuentra una descripción detallada de cada etiqueta de los estándares SOAP y WSDL. ¿Vale la pena hacerlo? En mi opinión no, porque... todo esto se crea automáticamente en Java, y solo necesitas escribir el contenido de los métodos que se supone que deben llamarse de forma remota. Entonces, apareció una API como JAX-RPC en Java. Si alguien no lo sabe, cuando dice que Java tiene tal o cual API, significa que hay un paquete con un conjunto de clases que encapsulan la tecnología en cuestión. JAX-RPC evolucionó con el tiempo de una versión a otra y finalmente se convirtió en JAX-WS. Obviamente, WS significa WebService y uno podría pensar que esto es simplemente un cambio de nombre de RPC como palabra de moda popular en estos días. Esto no es cierto, porque Ahora los servicios web se han alejado de la idea original y le permiten no solo llamar a métodos remotos, sino también simplemente enviar mensajes de documentos en formato SOAP. Todavía no sé por qué es necesario; es poco probable que la respuesta aquí sea "por si acaso es necesario". A mí mismo me gustaría aprender de camaradas más experimentados. Y por último, apareció JAX-RS para los llamados servicios web RESTful, pero este es el tema de un artículo aparte. La introducción puede terminar aquí, porque... A continuación aprenderemos a trabajar con JAX-WS.

Enfoque general

En los servicios web siempre hay un cliente y un servidor. El servidor es nuestro servicio web y a veces se le llama punto final (como en el punto final al que llegan los mensajes SOAP del cliente). Necesitamos hacer lo siguiente:
  1. Describe la interfaz de nuestro servicio web.
  2. Implementar esta interfaz
  3. Lanzar nuestro servicio web
  4. Escriba un cliente y llame de forma remota al método de servicio web deseado
Puede iniciar un servicio web de diferentes maneras: describir una clase con el método principal e iniciar el servicio web directamente como un servidor, o implementarlo en un servidor como Tomcat o cualquier otro. En el segundo caso, nosotros mismos no iniciamos un nuevo servidor ni abrimos otro puerto en la computadora, sino que simplemente le decimos al contenedor de servlets Tomcat que “hemos escrito clases de servicios web aquí, publíquelas para que todos los que se comuniquen con usted puedan utilice nuestro servicio web." Independientemente del método de lanzamiento del servicio web, tendremos el mismo cliente.

Servidor

Lancemos IDEA y creemos un nuevo proyecto. Crear nuevo proyecto. Indiquemos el nombre HolaWebService y presione el botón Próximo, luego botón Finalizar. en una carpeta src creemos un paquete ru.javarush.ws. En este paquete crearemos la interfaz HelloWebService: paquete ru. javarush. ws; // estas son anotaciones, es decir una forma de marcar nuestras clases y métodos, // en relación con la tecnología de servicios web importar javax. jws. Método Web; importar javax. jws. Servicio web; importar javax. jws. jabón. Encuadernación SOAP; // decimos que nuestra interfaz funcionará como un servicio web@ServicioWeb // decimos que el servicio web se utilizará para llamar a métodos@SOAPBinding (estilo = SOAPBinding. Estilo. RPC) interfaz pública HelloWebService ( // decimos que este método se puede llamar de forma remota@WebMethod public String getHelloString(nombre de cadena); ) En este código, las clases WebService y WebMethod son las llamadas anotaciones y no hacen nada más que marcar nuestra interfaz y su método como un servicio web. Lo mismo se aplica a la clase SOAPBinding. La única diferencia es que SOAPBinding es una anotación con parámetros. En este caso, el parámetro de estilo se utiliza con un valor que indica que el servicio web no funcionará a través de mensajes de documentos, sino como un RPC clásico, es decir. para llamar a un método. Implementemos nuestra lógica de interfaz y creemos una clase HelloWebServiceImpl en nuestro paquete. Por cierto, observo que finalizar una clase con Impl es una convención en Java, según la cual la implementación de interfaces se designa así (Impl - de la palabra implementación, es decir, implementación). Esto no es un requisito y usted es libre de nombrar la clase como quiera, pero los buenos modales lo requieren: paquete ru. javarush. ws; // la misma anotación que cuando se describe la interfaz, importar javax. jws. Servicio web; // pero aquí se usa con el parámetro endpointInterface,) la clase pública HelloWebServiceImpl implementa HelloWebService ( @Override public String getHelloString (nombre de cadena) ( // solo devuelve el saludo devolver "Hola, " + nombre + "!" ; src) ) Lancemos nuestro servicio web como un servidor independiente, es decir. sin la participación de ningún Tomcat ni servidores de aplicaciones (este es un tema para una discusión aparte). Para hacer esto, en la estructura del proyecto en la carpeta Creemos un paquete ru.javarush.endpoint, y en él crearemos una clase HelloWebServicePublisher con un método principal: paquete ru. javarush. punto final;// clase para ejecutar un servidor web con servicios web importar javax. xml. ws. punto final;// clase de nuestro servicio web importar ru. javarush. ws. HolaWebServiceImpl; clase pública HelloWebServicePublisher (public static void main (String... args) ( // inicia el servidor web en el puerto 1986// y a la dirección especificada en el primer argumento, // inicia el servicio web pasado en el segundo argumento Punto final. publicar( "http://localhost:1986/wss/hola", nuevo HelloWebServiceImpl () );

) ) Ahora ejecutemos esta clase haciendo clic

Mayús+F10 src. No aparecerá nada en la consola, pero el servidor se está ejecutando. Puede verificar esto escribiendo la línea http://localhost:1986/wss/hello?wsdl en su navegador. La página que se abre, por un lado, demuestra que tenemos un servidor web (http://) ejecutándose en el puerto 1986 de nuestro ordenador (localhost) y, por otro lado, muestra una descripción WSDL de nuestro servicio web. Si detiene la aplicación, la descripción dejará de estar disponible, al igual que el servicio web en sí, por lo que no haremos esto, sino que pasaremos a escribir el cliente. Cliente En la carpeta del proyecto Creemos un paquete ru.javarush.client y en él la clase HelloWebServiceClient con el método principal: paquete ru. javarush. cliente; // necesario para obtener la descripción wsdl y a través de ella// llegar al propio servicio web importar java. neto. URL; // esta excepción ocurrirá cuando se trabaje con un objeto URL importar java. neto. Excepción de URL con formato incorrecto; // clases para analizar xml con descripción wsdl// y alcanza la etiqueta de servicio que contiene importar javax. xml. espacio de nombres. QNombre; importar javax. xml. ws. Servicio; // interfaz de nuestro servicio web (necesitamos más)) ; importar ru. javarush. ws. HolaWebService; // mira el primer argumento en el atributo targetNamespace // mira el segundo argumento en el atributo de nombre QName qname = nuevo QName ("http://ws.site/", "HelloWebServiceImplService"); // Ahora podemos acceder a la etiqueta de servicio en la descripción de wsdl, Servicio servicio = Servicio. crear (url, nombreq); // y luego hasta la etiqueta de puerto anidada en él, de modo que // obtener un enlace a un objeto de servicio web remoto de nosotros HolaWebService hola = servicio. getPort(HelloWebService.clase); // ¡Hurra! Ahora puedes llamar al método remoto. Sistema. afuera. println (hola. getHelloString ("JavaRush"));

) ) Di el máximo de comentarios sobre el código en el listado. No tengo nada que agregar, así que ejecutemos (Shift+F10). Deberíamos ver el texto en la consola: ¡Hola, JavaRush! Si no lo vio, probablemente olvidó iniciar el servicio web.

Conclusión Este tema proporcionó una breve excursión a los servicios web. Una vez más, diré que gran parte de lo que escribí son mis suposiciones sobre cómo funciona y, por lo tanto, no debes confiar demasiado en mí. Agradecería que personas con conocimientos me corrigieran, porque así aprenderé algo.

UPD.

Lenguaje de descripción de servicios web (WSDL)

En los últimos ejemplos es posible que haya visto algunos fragmentos de código WSDL. Recuerde que WSDL es una gramática basada en XML diseñada para describir cómo los clientes externos pueden interactuar con los métodos web disponibles en una URL determinada bajo cada protocolo de comunicación admitido. En muchos sentidos, un documento WSDL puede considerarse como un "contrato" entre el cliente del servicio web y el propio servicio web. Este es otro metalenguaje. Específicamente, WSDL se utiliza para describir las siguientes características de cualquier método web disponible:

Nombre del método web XML;

Número, tipo y orden de los parámetros (si los hubiera);

Tipo de devolución (si se proporciona);

Condiciones de llamada HTTP GET, HTTP POST y SOAP.

En la mayoría de los casos, los documentos WSDL los genera automáticamente el servidor web correspondiente. Recuerde que cuando agrega el sufijo ?wsdl a una URL que apunta a un archivo *.asmx, el servidor web genera un documento WSDL para el servicio web XML especificado.

Pero si IIS genera automáticamente el documento WSDL para un servicio web XML determinado, ¿por qué entonces se necesita un conocimiento profundo de la sintaxis de los datos WSDL generados? La respuesta generalmente depende de cómo las aplicaciones externas utilizarán su servicio. Para los servicios web XML destinados a uso "interno", el WSDL generado por el servidor web suele ser suficiente.

Mientras tanto. Es completamente posible comenzar a desarrollar un servicio web XML creando un documento WSDL manualmente (como se discutió anteriormente). La idea principal de iniciar el desarrollo creando un documento WSDL está relacionada con problemas de compatibilidad. Recuerde que antes de la especificación WSI, era común que diferentes herramientas de creación de servicios web generaran descripciones WSDL incompatibles. Si comienza el desarrollo con código WSDL, puede crear el documento según sea necesario.

Como puede imaginar, iniciar un servicio web XML mediante la creación de un documento WSDL requiere un muy buen conocimiento de la gramática WSDL, que no se analiza en el contexto de este capítulo. Pero veremos la estructura básica de un documento WSDL. Una vez que comprenda los conceptos básicos, podrá apreciar la utilidad de la utilidad de línea de comandos wsdl.exe.

Comentario. La información más reciente sobre WSDL se puede encontrar en http://www.w3.org/tr/wsdl.

Definición de un documento WSDL

El documento WSDL real se abre y cierra mediante el elemento raíz ‹definiciones›. El descriptor de apertura normalmente define varios atributos xmlns. Definen espacios de nombres XML que definen varios subelementos. Como mínimo, el elemento ‹definitions› debe indicar el espacio de nombres donde se definen los elementos WSDL (http://schemas.xmlsoap.org/wsdl). Para que sea útil, el descriptor de apertura ‹definiciones› también debe especificar los espacios de nombres XML que definen tipos de datos WSDL simples, tipos de esquemas XML, elementos SOAP y el espacio de nombres de destino. Por ejemplo, así es como se ve la sección ‹definiciones› de nuestro servicio web de calculadora.

‹wsdl:definiciones xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"

xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/"

xmlns:soapec="http://schemas.xmlsoap.org/soap/encoding/"

xmlns-mime="http://schemas.xmlsoap.org/wsdl/mime/"

xmlns:tns="http://www.IntertechTraining.com/"

xmlns:s="http://www.w3.org/2001/XMLSchema"

xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"

xmlns:http="http://schemes.xmlsoap.org/wsdl/http/"

targetNamespace="http://www.IntertechTraining.com/"

xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"›

‹/wsdl:definiciones›

En el contexto del elemento raíz, puedes encontrar cinco subelementos. La apariencia general del documento WSDL debería ser algo como esto.

‹?xml versión="1.0" codificación="utf-8"?›

‹wsdl:definiciones…›

‹wsdl:tipos›

‹!-- Lista de tipos disponibles para este servicio web --›

‹wsdl:/tipos›

‹wsdl:mensaje›

‹!-- Formato de mensaje --›

‹wsdl:/mensaje›

‹wsdl:tipo de puerto›

‹!-- Información del puerto --›

‹wsdl:/tipopuerto›

‹wsdl:encuadernación›

‹!-- Información vinculante --›

‹wsdl:/enlace›

‹wsdl:servicio›

‹!-– Información sobre el servicio web XML en sí:-›

‹wsdl:/servicio›

‹wsdl:/definiciones›

Como era de esperar, cada uno de estos subelementos contendrá elementos y atributos adicionales que aclaran aún más la descripción de las capacidades disponibles. Veamos los nodos válidos más importantes uno por uno.

Elemento ‹tipos›

Primero veremos el elemento ‹tipos›, que contiene descripciones de todos los tipos de datos que ofrece el servicio web. Es posible que sepa que el propio XML define una serie de tipos de datos "centrales", todos los cuales están definidos dentro del espacio de nombres XML http://www.w3.org/2001/XMLSchema (que debe especificarse en el contexto de la raíz elemento ‹definiciones›). Tomemos, por ejemplo, el método Subtract() de nuestro servicio web de calculadora, que tiene dos parámetros de entrada de números enteros. En términos de WSDL, el tipo de Common Language Runtime System.Int32 se describe en el contexto del elemento ‹complexType›.

‹s:nombre del elemento= "Restar"›

‹s:secuencia›

‹s:elemento minOccurs=" 1 "maxOcurre=" 1 "nombre=" incógnita"tipo=" s:int" /›

‹s:elemento minOccurs="" 1 "maxOcurre=" 1 "nombre=" y"tipo=" s:int" /›

‹/s:secuencia›

‹/s:tipocomplejo›

‹/s:elemento›

El número entero devuelto por el método Subtract() también se describe dentro del elemento ‹tipos›.

‹s:nombre del elemento= " RestarRespuesta"›

‹s:tipocomplejo›

‹s:secuencia›

‹s:elemento minOccurs=" 1 "maxOcurre=" 1 "nombre=" RestarResultado"tipo=" s:int"/›

‹/s:secuencia›

‹ /s:tipocomplejo›

‹/s:elemento›

Si tiene un método web que devuelve o recibe tipos de datos personalizados, también aparecerán en el contexto del elemento ‹complexType›. Veremos los detalles de cómo hacer que los tipos de datos .NET personalizados estén disponibles utilizando el método Web más adelante. Para este ejemplo, digamos que define un método web que devuelve una estructura denominada Punto.

Punto de estructura pública (

nombre del punto de cadena pública;

La descripción WSDL para esta "estructura compleja" se vería así.

‹s:complexType nombre=" Punto"›

‹s:secuencia›

‹s:elemento minOccurs=" 1 "maxOcurre=" 1 "nombre=" incógnita"tipo=" s:int" /›

‹s:elemento minOccurs=" 1 "" maxOcurre=" 1 "nombre=" y"tipo=" s:int" /›

‹s:elemento minOccurs=" 0 "maxOcurre=" 1 "nombre=" puntoNombre"tipo=" s: cuerda" /›

‹/s:secuencia›

‹/s:tipocomplejo›

elemento ‹mensaje›

El elemento ‹mensaje› se utiliza para definir el formato para intercambiar solicitudes y respuestas para un método web determinado. Debido a que un único servicio web permite pasar múltiples mensajes entre un remitente y un destinatario, un solo documento WSDL puede definir múltiples elementos de mensaje. Normalmente, estas definiciones utilizan los tipos especificados dentro del elemento ‹tipos›.

Independientemente del número de elementos ‹mensaje› definidos en el documento WSDL, normalmente están "presentes" en pares. La primera definición representa el formato de entrada de un mensaje y la segunda definición representa el formato de salida del mismo mensaje. Por ejemplo, el método Subtract() del servicio web CalculatorWebService define los siguientes elementos ‹mensaje›.

‹wsdl:nombre del mensaje=" RestarJabónEn"›

‹wsdl:nombre de pieza="parámetros" elemento="tns:Restar" /›

‹/wsdl:mensaje›

‹wsdl: nombre del mensaje=" RestarSoapOut"›

‹wsdl:nombre de pieza="parámetros" elemento="tns:SubtractResponse" /›

‹/wsdl:mensaje›

Aquí sólo se ve la comunicación SOAP del servicio correspondiente. Como se analizó al principio de este capítulo, los servicios web XML se pueden invocar mediante SOAP o los métodos HTTP GET y POST. Pero si habilita la comunicación HTTP POST (que se explica más adelante), el WSDL generado debería mostrar los siguientes datos de ‹mensaje›.

‹wsdl: nombre del mensaje=" RestarHttpPostIn"›

‹nombre de la pieza="n1" tipo="s:cadena" /›

‹nombre de la pieza="n2" tipo="s:cadena" /›

‹wsdl:/mensaje›

‹wsdl:nombre del mensaje=" RestarHttpPostOut"›

‹nombre de la pieza="Cuerpo" elemento="s0:int" /›

‹wsdl:/mensaje›

Los elementos del ‹mensaje› no son muy útiles por sí solos. Sin embargo, otras partes del documento WSDL hacen referencia a estas definiciones de mensajes.

Comentario. No todos los métodos web requieren tanto una solicitud como una respuesta. Si el método Web es "unidireccional", sólo requiere el elemento ‹mensaje› de la solicitud. Puede designar un método web como unidireccional utilizando el atributo.

elemento ‹portType›

El elemento ‹portType› define las diversas conexiones que pueden ocurrir entre el cliente y el servidor, y cada una de estas relaciones está representada por un elemento ‹operación› anidado. Es fácil adivinar que las operaciones más típicas aquí deberían ser SOAP, HTTP GET y HTTP POST. Sin embargo, hay otras operaciones. Por ejemplo, una operación unidireccional permite a un cliente enviar un mensaje a un servidor web determinado pero no recibir una respuesta (esto es similar a llamar a un método sin esperar un valor de retorno). Una operación de solicitud-respuesta permite al servidor enviar una solicitud mientras el cliente responde (lo que puede considerarse una extensión de la operación de solicitud-respuesta).

Para ilustrar el formato del subelemento opcional ‹operación›, considere la definición WSDL para el método Subtract().

‹nombre del tipo de puerto wsdl= "CalculadoraWebServiceSoap"›

‹wsdl:nombre de operación=" Sustraer"›

‹wsdl:mensaje de entrada=" tns:RestarSoapIn" /›

‹wsdl:mensaje de salida=" tns:RestarSoapOut" /›

‹ /wsdl:operación›

‹wsdl:/tipopuerto›

Observe cómo los elementos ‹entrada› y ‹salida› se refieren al nombre del mensaje correspondiente definido dentro del elemento ‹mensaje›. Si el método Subtract() tuviera HTTP POST habilitado, vería el siguiente elemento ‹operación› adicional.

‹wsdl:portType nombre="CalculatorWebServiceHttpPost"›

‹wsdl:mensaje de entrada=" s0:RestarHttpPostIn" /›

‹wsdl:mensaje de salida= " s0:RestarHttpPostOut" /›

‹ wsdl:/operación›

‹wsdl:/tipopuerto›

Finalmente, tenga en cuenta que si un método web determinado se describe utilizando la propiedad Descripción, el elemento ‹operación› contendrá un elemento ‹documentación› anidado.

El elemento ‹vinculante›

Este elemento especifica el formato exacto del intercambio GET, POST y SOAP. Este es el más detallado de todos los elementos contenidos dentro del contexto del elemento raíz ‹definición›. Por ejemplo, aquí hay una definición de elemento ‹vinculante› que describe cómo una persona que llama puede interactuar con el método web MyMethod(). utilizando jabón.

‹wsdl:binding name="СalculatorWebServiceSoap12" type=" tns:CalculadoraWebServiceSoap"›

‹soap12:transporte vinculante=" http://schemas.xmlsoap.org/soap/http" /›

‹wsdl:nombre de la operación= " Sustraer"›

‹soap12:operación SoapAction=" http://www.IntertechTraining.com/Subtract" estilo="documento" /›

‹wsdl:entrada›

‹soap12:uso corporal=" literal" /›

‹/wsdl:entrada›

‹wsdl:salida›

‹soap12:uso corporal=" literal" /›

‹/wsdl:salida›

‹/wsdl:operación›

‹/wsdl:encuadernación›

elemento ‹servicio›

Por último, tenemos el elemento ‹servicio›, que especifica las características del propio servicio Web (por ejemplo, su URL). La tarea principal de este elemento es describir el conjunto de puertos abiertos por este servidor web. Para lograr esto, el elemento ‹services› puede utilizar cualquier número de elementos ‹port› anidados (no debe confundirse con el elemento ‹portType›). Así es como se ve el elemento ‹servicio› para CalculatorWebService.

‹wsdl:nombre del servicio= "CalculadoraWebService"›

‹wsdl:documentación xmlns:wsdl ="http://schemas.xmlsoap.org/wsdl/"›

Maravilloso servicio de calculadora web

‹/wsdl:documentación›

‹wsdl:nombre del puerto= "CalculadoraWebServiceSoap" vinculante = "tns:CalculadoraWebServiceSoap"

‹jabón:ubicación de la dirección= "http://localhost:1109/CalculatorWebService/Service.asmx"/›

‹/wsdl:puerto›

‹wsdl:puerto nombre="CalculadoraWebServiceSoap12" vinculante=" tns:CalculadoraWebServiceSoap12"›

‹soap12:ubicación de la dirección= "http://localhost:1109/CalculatorWebService/Service.asmx"/›

‹/wsdl:puerto›

‹/wsdl:servicio›

Entonces, como puede ver, el código WSDL que devuelve automáticamente el servidor ITS no es muy complejo, pero dado que WSDL es una gramática basada en XML, el código es bastante detallado. Sin embargo, ahora debería comprender mejor la función de WSDL, así que veamos un poco más de cerca los protocolos de comunicación de servicios web XML.

Comentario. Recuerde que el espacio de nombres System.Web.Services.Description contiene muchos tipos que le permiten leer y manipular mediante programación código WSDL sin formato (compruébelo usted mismo si está interesado).

Una vez me dieron la tarea de iniciar el desarrollo de servicios web y me dieron las fuentes de un proyecto simple sin ninguna explicación. El proyecto, por supuesto, no se puso en marcha. Tampoco tenía idea de qué era Spring y cómo funcionaba. Tampoco pude encontrar artículos adecuados sobre el desarrollo de servicios web utilizando Spring, ni en ruso ni en inglés. Tuve que resolverlo yo mismo, pero resultó que no daba tanto miedo.
Y recientemente decidí ver qué nuevas funciones se han agregado a Spring desde entonces y actualizar los servicios antiguos, lo que como resultado me impulsó a escribir este artículo.

Este artículo es una guía para desarrollar un servicio web simple utilizando el protocolo SOAP usando Spring-WS.

Y así, escribiremos el servicio más simple que acepte el nombre de usuario y envíe un saludo y la hora actual en el servidor.

¿Qué necesitamos?
  • IDE. Estoy usando Eclipse.
Preparándose para el trabajo
Creemos un nuevo proyecto de aplicación web. En Eclipse es: "Archivo => Nuevo => Proyecto web dinámico".
Llamé al proyecto: HelloService.
A continuación, copie las bibliotecas de Spring, XMLBean, wsdl4j, commons-logging al directorio del proyecto WEB-INF/lib.
Si lo deseas, puedes añadirlos a las bibliotecas del servidor para no cargarlos con cada aplicación.
Crear un esquema WSDL
Básicamente, un esquema WSDL está diseñado para describir un servicio.
Por supuesto, no lo crearemos manualmente. El esquema se generará automáticamente usando Spring, pero hablaremos de eso más adelante.
Definición de datos de entrada y salida
Datos de entrada:
  • Nombre de cadena.
Producción:
  • Saludo de cadena;
  • La hora es la hora actual.
Crear una descripción de los datos de entrada y salida.
En el directorio WEB-INF, cree el archivo HelloService.xsd. Este archivo será necesario para generar el esquema WSDL y crear las clases Java correspondientes.
Texto del archivo:

Atributo espacio de nombres de destino– espacio de nombres utilizado. Aquellos. Todos los objetos creados se ubicarán en el paquete org.example.helloService.
Elementos Solicitud de servicio Y Respuesta de servicio describir los datos de entrada y salida (solicitud/respuesta) respectivamente.
Atributos minOcurre Y maxOcurre determinar el número de repeticiones de un componente determinado dentro de un elemento. Si estos parámetros no se especifican, de forma predeterminada se consideran iguales a 1. Para un componente opcional, debe especificar minOccurs=0. Con un número ilimitado de componentes: maxOccurs=unbounded.
Puede leer más sobre los esquemas XML.
Creando JavaBeans
Según el esquema creado, crearemos clases Java. Para hacer esto, cree un archivo build.xml:

Parámetro WS_HOME debe apuntar al directorio donde se encuentra XMLBeans.
HolaServicio.xsd– camino al circuito creado.
lib\holaservicio.jar– biblioteca java creada.

A continuación, ejecute Ant-build (espero que ya lo haya instalado).
En Eclipse puedes ejecutarlo así: RMB en el archivo build.xml => Ejecutar como => Ant Build.
Si a través de la línea de comando:
hormiga -buildfile build.xml
Bueno, estamos esperando que se complete la construcción. Después de eso, podemos verificar en el directorio del proyecto WEB-INF\lib la presencia de la biblioteca correspondiente (helloservice.jar).

Implementación del servicio
Crear una interfaz y una clase de servicio.
Interfaz de servicio: HelloService.java:
paquete org.ejemplo; importar java.util.Calendar; interfaz pública HelloService (cadena pública getHello (nombre de cadena) lanza una excepción; calendario público getCurrentTime();)
Implementación del servicio: HelloServiceImpl.java:
paquete org.ejemplo; importar java.util.Calendar; importar org.springframework.stereotype.Service; @Service la clase pública HelloServiceImpl implementa HelloService ( public String getHello(String name) lanza una excepción ( return "Hola, " + nombre + "!"; ) public Calendar getCurrentTime() ( return Calendar.getInstance(); ) )
Este código, creo, no necesita comentarios. Lo único que puede generar preguntas para las personas que no han encontrado Spring antes es la anotación @ Service, pero les contaré sobre esto un poco más adelante.
Punto final
Punto final: una clase que será responsable de procesar las solicitudes entrantes (una especie de punto de entrada).

Cree el archivo HelloServiceEndpoint.java:
paquete org.ejemplo; importar org.springframework.beans.factory.annotation.Autowired; importar org.springframework.ws.server.endpoint.annotation.Endpoint; importar org.springframework.ws.server.endpoint.annotation.PayloadRoot; importar org.ejemplo.helloService.ServiceRequestDocument; importar org.ejemplo.helloService.ServiceRequestDocument.ServiceRequest; importar org.ejemplo.helloService.ServiceResponseDocument; importar org.example.helloService.ServiceResponseDocument.ServiceResponse; @Endpoint clase pública HelloServiceEndpoint( privado estático final String namespaceUri = "http://www.example.org/HelloService"; HelloService privado helloService; @Autowired public void HelloService (HelloService helloService) ( this.helloService = helloService; ) @PayloadRoot( localPart = "ServiceRequest", namespace = namespaceUri) public ServiceResponseDocument getService(ServiceRequestDocument request) lanza una excepción ( ServiceRequestDocument reqDoc = request; ServiceRequest req = reqDoc.getServiceRequest(); ServiceResponseDocument respDoc = ServiceResponseDocument.Factory.newInstance(); ServiceResponse resp = respDoc. addNewServiceResponse(); String nombre de usuario(); String helloMessage = testNewService.getHello(userName);
¿Qué se ha hecho aquí?
Anotación @Punto final simplemente determina que esta clase procesará las solicitudes entrantes.
espacio de nombresUri– el mismo espacio de nombres especificado al crear el esquema xml.

Ahora retrocedamos un poco y recordemos la anotación. @Servicio. Sin entrar en detalles para no sobrecargar al lector con información innecesaria, esta anotación le dice a Spring que cree el objeto apropiado y la anotación. @autocableado sirve para la inyección (sustitución automática) del objeto correspondiente. Por supuesto, al crear aplicaciones simples, no tiene sentido usar estas anotaciones, pero aun así decidí no excluirlas en este ejemplo.

El resto, nuevamente, todo debería quedar claro. Tenga en cuenta que ServiceRequest, ServiceResponse, etc. – estas son exactamente las clases que se crearon en función de nuestro esquema xml.

Configuración del servicio de primavera
El final se acerca ahora.
Cree el archivo service-ws-servlet.xml.

sws: impulsado por anotaciones– esto solo significa que se utilizan anotaciones en este proyecto.
A contexto: escaneo de componentes indica el paquete en el que se buscarán las anotaciones, y la búsqueda también se realizará en subpaquetes.

Los dos contenedores siguientes siempre permanecerán sin cambios. Su esencia es recibir y convertir una solicitud de Xml en un objeto Java y realizar una conversión inversa adicional.

sws:dinamico-wsdl es responsable de la generación automática de un documento WSDL basado en el esquema XML creado.
ubicación indica la ruta al esquema.
ubicaciónUri– la dirección (relativa al contenedor) donde estará disponible el esquema WSDL.
En mi caso el WSDL está disponible en la siguiente dirección:
localhost/HelloService/HelloService.wsdl

Descriptor de implementación
Y finalmente, lo último.
En el directorio WEB-INF cambiamos o creamos el archivo web.xml.
Holaservicio Holaservicio servicio-ws org.springframework.ws.transport.http.MessageDispatcherServlet transformWsdlUbicaciones verdadero servicio-ws /*
No describiré más este archivo; la mayoría de la gente ya debería conocerlo. Para proyectos simples, esencialmente no debería cambiar. Solo vale la pena señalar que el nombre del servlet (nombre-servlet) debe coincidir con el nombre del archivo de configuración del servicio Spring. servicio-ws-servlet.xml.
Comprobación de funcionalidad
La primera señal de funcionamiento correcto es el esquema WSDL creado.
Para comprobarlo, simplemente vaya a la dirección de este esquema (http://localhost/HelloService/HelloService.wsdl) y mire: el archivo xml debería mostrarse allí. Si no se muestra nada o aparece algún error, vuelve a leer atentamente todo el artículo y busca qué hicimos mal.

Para realizar más pruebas necesitamos SOAPUI (tengo la versión 3.0.1).
Instálalo y ejecútalo.
Cree un nuevo proyecto: Archivo => Nuevo proyecto SOAPUI. En el campo WSDL/WADL inicial, inserte un enlace al esquema WSDL (http://localhost/HelloService/HelloService.wsdl).
En el proyecto creado, abra la solicitud requerida.

Ingrese el nombre en el campo Nombre y haga clic en el botón “Enviar solicitud”


Como resultado, recibimos una respuesta del servidor con un saludo y la hora actual.


Si algo sale mal, vuelva a leer este artículo.

¿Qué sigue?
Bueno, el siguiente paso es escribir un cliente para este servicio web. Pero esto ya es material para otro artículo, que puede escribirse más adelante si este material le interesa a alguien.


Arriba