Conceptos básicos de Servicios Web SOAP, WSDL y XSD




¡Hola nuevamente!

El post de hoy es referente a los conceptos que debemos comprender sobre Servicios Web de tipo SOAP. Ya sea que estemos involucrados en el desarrollo de aplicaciones SOA o no, es bueno conocer de qué se trata todo esto, y si lo estamos, con mucha más razón puesto que es totalmente necesario. Incontables veces he tenido que explicar estos conceptos a personas con perfiles no técnicos y otras tantas a quienes deberían conocerlos, desafortunadamente no es tan fácil de entender sin un contexto más gráfico. Es por eso que decidí escribir sobre esto y espero lograr el objetivo. Comencemos pues con lo importante.

Un Servicio Web es un servicio de negocio programado en algún lenguaje, que envuelve cierta funcionalidad y la expone en una red de manera estandarizada, para que cualquiera conectado a esta misma red, que además soporte dichos estándares, pueda acceder a ella. Veámoslo con un ejemplo muy sencillo que ya he usado en otros post, supongamos que tenemos una aplicación interna de administración de venta de productos, y ésta involucra una aplicación web que usa servicios de negocio para realizar la consulta de productos y registrar una venta en una base de datos. Nuestro diagrama a grandes rasgos sería algo así:



Esta aplicación interna hace uso del servicio de negocio de control de productos, el cual encapsula la lógica para realizar las acciones sobre la Base de Datos. Esta solución está limitada ya que el servicio es exclusivo de esta aplicación, si quisiéramos tener otra aplicación diferente, donde se use el mismo servicio de productos, tendríamos que duplicarlo, por ende el control y el mantenimiento se complican y puede volverse un caos.


La forma lógica de resolver este problema es separar el servicio de negocio y dejarlo disponible para las dos aplicaciones. Este es justamente el concepto de un Servicio Web. Así es como quedaría el cambio.


Para poder llegar a este objetivo se tienen que realizar varios acuerdos entre las aplicaciones involucradas. Para el caso de nuestro ejemplo, es necesario que las 3 partes (aplicación 1, aplicación 2 y Servicio Web) establezcan comunicación por alguna vía, hablen el mismo idioma y puedan intercambiar información a través de mensajes. Para solventar estos requerimientos existen protocolos de comunicación estandarizados, en esta ocasión hablaré del protocolo SOAP (Simple Object Access Protocol), este protocolo es bastante robusto ya que no solo sirve para intercambiar información, si no que soporta elementos de validación  de mensajes, seguridad, se puede usar por medio de HTTP (es decir, internet), SMTP (correo electrónico), TCP (transporte de información por medio de una conexión segura cliente-servidor) y JMS (servicios de mensajería punto a punto o suscriptor-publicador), además de ser neutral a la plataforma en la que los clientes y los servicios web se encuentren, entre otras bondades.

La estructura de un mensaje SOAP se compone de un sobre o Envelope que envuelve un mensaje, dicho mensaje se divide en encabezado o Header y cuerpo o Body. En el encabezado puede viajar información relevante para el servicio web, como por ejemplo un usuario y password para autenticación, un Token de seguridad, datos específicos de negocio, etc. o simplemente puede ir vacío. En el cuerpo se envía la información de negocio requerida para realizar las operaciones o bien para especificar la respuesta del servicio.


Los mensajes SOAP se estructuran con etiquetas XML además de que interviene un lenguaje adicional para su definición, WSDL (Web Services Description Language) que se usa para generar una interfaz del Servicio Web, misma que será su punto de entrada. A éste se le conoce como Archivo wsdl o Contrato y una vez que el servicio está publicado, éste archivo estará accesible en una red por medio de un url que tiene terminación ?wsdl

Dentro del archivo wsdl se describe todo el servicio web, las operaciones que tiene disponibles, las estructuras de datos de los mensajes de cada operación, entre otras cosas que mencionaré más adelante. Aquí también se utilizan los XSD, que son los archivos que especifican los datos de los mensajes. De igual manera, los explicaré a detalle más adelante.

Para poder invocar un Servicio Web, es necesario crear un Cliente Consumidor que use el archivo wsdl, lo interprete correctamente y con toda la información que éste contiene, sea capaz de conectarse a él, invocarlo e intercambiar los mensajes en el formato esperado.

Los Servicios Web SOAP tienen la propiedad de Interoperabilidad, que significa que pueden ser invocados sin importar la plataforma o el lenguaje que se esté usando, siempre y cuando estos sean capaces de generar un Cliente Consumidor con el mismo estándar del protocolo SOAP, es por eso que la construcción del cliente varía dependiendo de la plataforma y el lenguaje de programación. Así, una aplicación Java puede consumir el mismo Servicio Web que una aplicación .NET, un sistema empaquetado (Siebel, EBS, etc) entre muchos otros.

Cuando se genera un Cliente Consumidor se realiza la importación del archivo wsdl, se descubren las operaciones expuestas en el Servicio Web y los mensajes que se requieren para cada uno, así el Cliente podrá ejecutarlos en cualquier momento en la manera tradicional, propia del lenguaje. La estructura del ejemplo anterior queda de la siguiente manera al crear los dos Clientes:


Una vez creados los Clientes, cada aplicación podrá invocar cuando lo requiera las operaciones expuestas en el Servicio Web, conectándose al Endpoint, especificado en el archivo wsdl. El Endpoint es la ubicación del Servicio Web en la red, es decir, el url donde efectivamente se está ejecutando. Así las invocaciones que realicen los Clientes son direccionadas al Endpoint del Servicio Web intercambiando mensajes SOAP y el archivo wsdl ya no es necesario.


Ahora que queda más clara la interacción de cada elemento, resta explicar las partes que conforman los archivos wsdl y xsd. La siguiente imagen muestra un archivo wsdl, vamos a descomponerlo y explicarlo. Para comenzar es necesario mencionar que estos archivos se leen de abajo hacia arriba debido a la distribución típica de los elementos y para darle lógica a cada uno, sé que es un poco extraño, pero si lo hacen de esta manera, con la práctica se les facilitará entenderlos e interpretarlos, por lo pronto voy a explicar cada sección de arriba hacia abajo y al final, como ejercicio de lo aprendido, ustedes deberán realizar la lectura correcta, de esta manera les hará más sentido.

1. La línea 1 contiene el encabezado del archivo que indica que se trata de un archivo xml con codificación de caracteres UTF-8.

2. En la línea 2 se establece que se trata de un archivo wsdl y se le asigna un nombre, en este caso Productos.

3. En la línea 3 se declara el namespace local del archivo wsdl. Un namespace es un grupo de elementos cuyos nombres son únicos, es decir, estamos indicando que tenemos un grupo de etiquetas xml en un determinado scope (en nuestro caso el archivo wsdl) y serán calificadas con el texto http://services.blogsoa.com/Productos como identificador único. Esto es necesario debido a que en xml se pueden generar elementos con los mismos nombres y es necesario diferenciarlos de alguna manera. Cabe mencionar que los namespaces por convención se declaran en forma de url, sin embargo no quiere decir que tiene que ser válido y donde algo se esté ejecutando, en realidad estos url no existen y podrían ser una simple palabra.

4. En la siguiente línea se crea el prefijo client para identificar a todos los nombres de elementos que pertenecen al namespace del wsdl definido en la línea anterior.

5. De la línea 5 a la 8 se establecen los prefijos y los namespaces que serán usados para identificar de dónde se usa el resto de las etiquetas xml del archivo. Por ejemplo el prefijo xsd hace referencia al namespace estándar de los elementos disponibles en la W3 para la definición de esquemas xsd (como nota adicional, el url de este namespace, así como el de otros que son estándar, si existe, y es una página web que describe los elementos que contiene), el prefijo prod fue definido internamente y hace referencia a los elementos que vamos a usar en nuestro archivo xsd que explicaré después, y así sucesivamente con el resto de los namespaces. Estos sirven para calificar a las etiquetas que usaremos en el archivo, si ponen atención verán que la mayoría de las etiquetas xml usadas aquí son calificadas con el prefijo wsdl: tal es el caso de <wsdl:types> esto quiere decir que la etiqueta types se encuentra declarada en un namespace llamado http://schemas.xmlsoap.org/wsdl/ ubicado en algún lugar de internet cuyo prefijo es wsdl.

6. De la línea 10 a la 14 se usa la etiqueta types, dentro de ésta se usa otra llamada schema y finalmente una llamada import. Esto significa que se realizará la importación de un archivo xsd con namespace http://elements.blogsoa.com/Productos (que previamente declaramos y le asignamos el prefijo prod) y dicho archivo xsd se encuentra físicamente ubicado en la ruta ../XSD/productos.xsd, así podremos usar las etiquetas de los elementos declarados en él. También es posible embeber el archivo xsd dentro del wsdl, dentro de esta sección en vez de importar un archivo externo, se escribe todo el esquema de datos.

7. De la línea 17 a la 22 se declaran dos elementos message. El primero llamado consultarProductosRequest y el segundo consultarProductosResponse, dentro de los mensajes se declara un elemento part, llamado parameters y hace referencia al elemento prod:consultarProductosRequest y prod:consultarProductosResponse respectivamente, esto quiere decir que se está definiendo que el mensaje de entrada para consultar productos es de tipo consultarProductosRequest, y el mensaje de respuesta es de tipo consultarProductosResponse, estos tipos están ubicados en el xsd que importamos previamente, y además, que ambos están formados por una sola parte, es decir, en una sola pieza. Si el mensaje tuviera más elementos part, diríamos que está formado por varias partes.

8. En las líneas 25 a 30 se declaran los mensajes de entrada y respuesta para la operación aplicar venta, que serán usados más adelante.

9. En las líneas 32 a 45 se declaran los elementos portType, los cuales son los más importantes en un wsdl por que hacen referencia a las operaciones del Servicio Web que son expuestas, así como los mensajes de entrada y salida que se intercambian en cada una. En nuestro ejemplo tenemos dos operaciones; consultarProductos y aplicarVenta y estos a su vez usan los mensajes que declaramos en las líneas previas.  Nótese que los mensajes y sus elementos que declaramos se llaman igual, la forma de diferenciarlos es por medio de los prefijos prod y client. El mensaje consultarProductosRequest es local al wsdl por lo que se crea con el namespace asignado al atributo targetNamespace y no es necesario calificarlo en su declaración pero sí en este caso, puesto que se está haciendo referencia a él.

10. En las siguientes líneas, de la 47 a la 71 se define el elemento binding y su configuración para cada operación del servicio. El binding representa el formato de los mensajes y los detalles específicos del protocolo de transporte que se usan en cada operación de un Servicio Web. Como se puede apreciar, el elemento soap:binding tiene dos atributos, style y transport. El primero especifica el estilo de codificación  de los mensajes, el valor puede ser document o RPC, siendo document el default. El segundo especifica el tipo de protocolo de transporte, como los que mencioné arriba, en este caso usamos HTTP. Para cada operación también se configura el atributo use para el input y el output, éste se refiere al uso del binding puede ser literal o encoded. Existen algunas diferencias entre ambos y se pueden generar 4 combinaciones en conjunto con el atributo style; RPC/Encoded, RPC/literal, Document/Encoded y Document/Literal. Ya que es un tema un poco complejo, trataré de escribir otro post con la explicación a detalle y las diferencias de cada una de estas opciones.

11. Por último, en las líneas 73 a 77 se define el elemento service. Este elemento sirve para unir todos los elementos; ports, bindings, messages, types, endpoints, etc. Los Clientes Consumidores del servicio usan este elemento como primer paso para generar la estructura del contrato. Es aquí donde se especifica el Endpoint del servicio, como ya lo mencioné, es donde se ubica físicamente el servicio.

El siguiente paso es explicar el archivo XSD que es usado en nuestro wsdl de ejemplo. En la imagen podemos ver las diferentes partes.

1. La línea 1 contiene el encabezado del archivo que indica que se trata de un archivo xml con codificación de caracteres UTF-8.

2. En la línea 2 se establece que se trata de un archivo xsd o schema.

3. La línea 3 establece el atributo elementFormDefault con valor qualified, quiere decir que todos los elementos declarados en el archivo deben estar calificados con un namespace cuando se haga referencia a ellos. Esto es funcional para realizar validaciones de esquemas de forma automática, para usar funciones XPath en estas estructuras de datos, entre otras cosas.

4. Las líneas 4, 5 y 6 definen los namespaces que se usaran de manera local en el archivo, igual que como lo hicimos en el wsdl, el valor del atributo targetNamespace se establece a http://elements.blogsoa.com/Productos y se crea el prefijo tipos.

5. En las líneas 9 y 10 se declaran dos elementos llamados consultarProductosRequest y consultarProductosResponse y se especifica que son de tipo tipos:ConsultarProductosRequest y tipos:ConsultarProductosResponse, respectivamente. Es decir, estamos creando elementos y asignándoles su tipo de dato.

6. En las líneas 13 y 14 se realiza lo mismo pero para los elementos aplicarVentaRequest y aplicarVentaResponse.

7. En las líneas 17 a 24 se define el tipo dato que usamos anteriormente para consultarProductosRequest. Es un elemento complexType llamado ConsultarProductosRequest, y se compone de varios elementos simples. Su estructura comprende:
  • Un elemento llamado codigoProducto de tipo string que no es requerido y que debe aparecer máximo una vez, esto lo sabemos por los atributos minOccurs y maxOccurs. 
  • Un elemento llamado nombreProducto de tipo string que no es requerido y que debe aparecer como máximo una vez. 
  • Un elemento llamado categoria de tipo string que no es requerido y que debe aparecer como máximo una vez. 
  • Un elemento llamado almacen de tipo string que no es requerido y que debe aparecer como máximo una vez.
Esto significa que para realizar una consulta de productos es necesario enviar un mensaje con alguno o ninguno de estos elementos.

8. En las líneas 26 a 30 se define el tipo del elemento consultarProductosResponse llamado ConsultarProductosResponse, y se compone de: 
  • Un elemento llamado listaProductos de tipo tipos:ListaProductos, que no es requerido y que debe aparecer como máximo una vez.
9. En las líneas 32 a 36 se define el tipo del elemento listaProductos llamado ListaProductos, y se compone de:
  • Un elemento llamado Producto de tipo tipos:Producto, que no es requerido y que no tiene límite de apariciones, esto lo determina el valor unbounded del atributo maxOccurs.
10. En las líneas 38 a 47 se define el tipo del elemento producto llamado Producto, y se compone de:
  • Un elemento llamado codigoProducto de tipo string que no es requerido y que debe aparecer como máximo una vez. 
  • Un elemento llamado nombreProducto de tipo string que no es requerido y que debe aparecer como máximo una vez. 
  • Un elemento llamado categoria de tipo string que no es requerido y que debe aparecer como máximo una vez. 
  • Un elemento llamado almacen de tipo string que no es requerido y que debe aparecer como máximo una vez. 
  • Un elemento llamado precio de tipo decimal que no es requerido y que debe aparecer como máximo una vez. 
  • Un elemento llamado cantidadDisponible de tipo int que no es requerido y que debe aparecer como máximo una vez.
Hasta aquí, los puntos 8, 9 y 10 componen la estructura de la respuesta de la operación de consulta de productos; una lista de productos con determinada información.

11. En las líneas 49 a 56 se define el tipo del elemento aplicarVentaRequest llamado AplicarVentaRequest, y se compone de:
  • Un elemento llamado codigoProducto de tipo string que si es requerido y que debe aparecer como máximo una vez. 
  • Un elemento llamado cantidadProducto de tipo int que si es requerido y que debe aparecer como máximo una vez. 
  • Un elemento llamado almacen de tipo string que si es requerido y que debe aparecer como máximo una vez
  • Un elemento llamado precioTotal de tipo decimal que si es requerido y que debe aparecer como máximo una vez.
12. Finalmente, en las líneas 58 a 64 se define el tipo del elemento aplicarVentaResponse llamado AplicarVentaResponse, y se compone de: 
  • Un elemento llamado código de tipo string que no es requerido y que debe aparecer como máximo una vez. 
  • Un elemento llamado descripcion de tipo string que no es requerido y que debe aparecer como máximo una vez. 
  • Un elemento llamado numeroOrden de tipo string que no es requerido y que debe aparecer como máximo una vez.
En los últimos dos puntos definimos la estructuras de datos necesarias en la entrada y salida para la operación aplicar venta de un producto.


Ahora que ya hemos comprendido la definición y las partes que forman un Servicio Web, veamos un ejemplo de los mensajes SOAP válidos para cada operación expuesta y la respuesta que obtendríamos si las ejecutamos.

Para la operación consultarProductos, un ejemplo de mensaje SOAP de entrada es:



El mensaje de respuesta que obtenemos al hacer la invocación es:



Para la operación aplicarVenta, un ejemplo de mensaje SOAP de entrada es:


 Así, el mensaje de respuesta que obtenemos al hacer la invocación es:





Con esto hemos terminado los temas del post, espero que haya quedado más claro y que se disipen las dudas.

Nos leemos la próxima vez.


Comentarios

  1. gracias, me sirvió mucho, hay alguna posibilidad de que tengas el ejemplo publico y así probar el WSDL

    ResponderEliminar
    Respuestas
    1. Hola!

      Una disculpa, no lo tengo público. Si tienes algún servidor (público en internet) donde desplegarlo, pásame los datos y con gusto lo despliego. O en su defecto, puedes desplegarlo tu mismo en cualquier servidor de aplicaciones que soporte web services, ya sea con algún IDE como Eclipse o similares (dependiendo del lenguaje de programación)

      Recibe un saludo.

      Eliminar
  2. hola, te hago una consulta. Si yo elijo transporte sb para mi proxy service. En transport del wsdl como debería setearlo?

    ResponderEliminar
  3. Muchas gracias por el post, me hizo comprender muchas cosas. Felicidades!

    ResponderEliminar
    Respuestas
    1. Gracias a ti Angel por tu comentario. Es bueno saber que ha sido de utilidad para tu estudio.

      Saludos!

      Eliminar
  4. que tal..! tendrás algún post de ejemplo BPM. Muchas gracias por tus aportes.

    ResponderEliminar
    Respuestas
    1. Hola Fredy

      No, de BPM no tengo ejemplos. Por lo general no trabajo con esa herramienta. Disculpa.

      Saludos!

      Eliminar
  5. Estupendo post, es el mejor explicado que todos los que he leído. No obstante, si fuera posible, me gustaría que pusieses un ejemplo desde el inicio de la conexión con el OPEN, SEND etc. ¡ Gracias !

    ResponderEliminar
  6. Muy útil la información y muy bien explicada, muchas gracias

    ResponderEliminar

Publicar un comentario

Entradas más populares de este blog

¿Qué es un Enterprise Service Bus y por qué usarlo?