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.
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:
gracias, me sirvió mucho, hay alguna posibilidad de que tengas el ejemplo publico y así probar el WSDL
ResponderBorrarHola!
BorrarUna 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.
hola, te hago una consulta. Si yo elijo transporte sb para mi proxy service. En transport del wsdl como debería setearlo?
ResponderBorrarMuchas gracias por el post, me hizo comprender muchas cosas. Felicidades!
ResponderBorrarGracias a ti Angel por tu comentario. Es bueno saber que ha sido de utilidad para tu estudio.
BorrarSaludos!
que tal..! tendrás algún post de ejemplo BPM. Muchas gracias por tus aportes.
ResponderBorrarHola Fredy
BorrarNo, de BPM no tengo ejemplos. Por lo general no trabajo con esa herramienta. Disculpa.
Saludos!
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 !
ResponderBorrarMuy útil la información y muy bien explicada, muchas gracias
ResponderBorrarGracias a ti Oscar por leer y comentar.
BorrarSaludos!
Sandy! se agradece mucho el post y el cómo explicas.
ResponderBorrarQue genial que te haya quedado más claro, sigue así!
BorrarSaludos.
Es posible que me regales los archivos fuentes para basarme en ellos y probarlos mi correo es ppablo08@hotmail.com
ResponderBorrarMuy buen aporte Mil Gracias!!!!
ResponderBorrarGracias José, es un placer :D
BorrarSaludos!
genial artículo, me ayudaste mucho a comprender un poco mas la estructura de un ws.
ResponderBorrarSaludos
Excelentes noticias David! Me da mucho gusto que te sirva en tu aprendizaje.
BorrarRecibe un saludo de vuelta.
tienes algún otro articulo sobre estos documentos wsdl o xsd, o de información sobre servicios web?
BorrarPor el momento es el único artículo que tengo. Espero que encuentres un poco más de info.
BorrarSaludos!
Muy buen detalle. Saludos.
ResponderBorrarGracias Sandy por la Informacion muy bien explicado, y para los que estmos intentando aprendere ,uy util.? Saludos
ResponderBorrarQue tal, anteriormente he consumido webservice wsdl en vb.net y c#, pero ahora me han encomendado consumir el siguiente webservice: https://ws.sunat.gob.pe/ol-ad-itreconfisico-ws/ReconocimientoFisicoService.htm?wsdl
ResponderBorrarhe realizado mi referencia, pero en comparacion lo habitual que veía, ahora veo que este tiene terminacion htm?wsdl, quizas me puedas ayudar a como puede enviar los parametros que me pide y obtener la respuesta.
Hola Enrique,
BorrarPuedes descargar el archivo físico wsdl? Quizás no se trata de un web service SOAP, o quizás solo no tienes acceso. Yo intenté acceder pero no me lo permite, seguramente no es público.
Saludos