¿Qué es el protocolo del jabón? Envío de objetos complejos. Leer una lista de empleados

Brett McLaughlin Traducción de Ilya Chekmenev

SOAP es el Protocolo simple de acceso a objetos. Si nunca has oído hablar de él antes, entonces debes vivir en algún desierto, lejos de la civilización. Se ha convertido en la última moda en programación web, y parte integral de los servicios web que con tanto fanatismo se utilizan en la última generación de desarrollo web. Si ha oído hablar de .NET de Microsoft, o de la "revolución" peer-to-peer, entonces ha oído hablar de las tecnologías basadas en SOAP (incluso si no sabe qué es). no hay uno sino dos implementaciones de SOAP, de Apache y de Microsoft, que tienen miles de páginas en su sitio de soporte técnico de MSDN (http://msdn.microsoft.com/).

En este artículo te diré qué es SOAP y por qué es una parte tan importante en la evolución del paradigma de la programación web. Esto lo ayudará a omitir los aspectos básicos y comenzar a trabajar directamente con el kit de herramientas SOAP. Luego ofrezco una descripción general rápida de los proyectos SOAP existentes y me sumerjo en la implementación de Apache. Este artículo no pretende recrear la imagen completa de SOAP, mi libro "Java & XML 2nd Edition" llena muchos vacíos. Las respuestas a muchas de las preguntas que surgieron después de leer este artículo las encontrarás en el libro.

Introducción

Primero necesitas entender qué es SOAP. Puede leer la opinión completa (y bastante extensa) del W3C en http://www.w3.org/TR/SOAP. Luego, habiendo entendido y descartado todas las cáscaras, comprenderá que SOAP es solo un protocolo. Es un protocolo simple (no es necesario escribir uno nuevo para usarlo) basado en la idea de que en algún punto de una arquitectura distribuida existe la necesidad de intercambiar información. Además, para sistemas donde existe la posibilidad de sobrecargas y dificultades en el procesamiento de procesos, este protocolo es muy ventajoso porque es liviano y requiere una cantidad mínima de recursos. Finalmente, permite que todas las operaciones se realicen a través de HTTP, lo que permite eludir cosas complicadas como los firewalls y protegerse de escuchar en sockets con una cantidad impensable de puertos. Lo principal es que te des cuenta de esto, y todo lo demás son detalles.

Por supuesto, le gustaría saber estos detalles, y no los ignoraré. Hay tres componentes básicos en la especificación SOAP: el sobre SOAP, un conjunto de reglas de cifrado y los medios de interacción entre una solicitud y una respuesta. Pensemos en un mensaje SOAP como una carta normal. ¿Todavía recuerdas esas cosas antiguas en sobres con un sello postal y una dirección escrita en el anverso? Esta analogía ayuda a visualizar más claramente el concepto de SOAP como un "envoltorio". La figura 12-1 muestra los procesos SOAP en forma de esta analogía.

Figura 12-1. Proceso de mensajes SOAP

Tenga en cuenta esta imagen y veamos los tres componentes de la especificación SOAP. Hablaré brevemente de cada uno de ellos, dando ejemplos que mejor representan este concepto. Estos tres componentes clave hacen que SOAP sea tan importante y significativo. El manejo de errores, el soporte para varios cifrados, la serialización de parámetros y el hecho de que SOAP funciona sobre HTTP en la mayoría de los casos lo hacen más atractivo que otras soluciones de protocolo distribuido. SOAP proporciona un alto grado de interoperabilidad con otras aplicaciones, que he cubierto con más detalle en mi libro. Por ahora, quiero centrarme en los elementos centrales de SOAP.

Sobre

El sobre SOAP es similar a un sobre de correo ordinario. Contiene información sobre el mensaje que se cifrará en la sección SOAP principal, incluida información sobre el destinatario y el remitente, así como información sobre el mensaje en sí. Por ejemplo, un encabezado de sobre SOAP podría indicar cómo se debe procesar el mensaje. Antes de que una aplicación comience a procesar un mensaje, analiza la información sobre el mensaje, incluso si puede incluso procesar el mensaje. A diferencia de la situación con llamadas XML-RPC estándar (¿recuerdas? Mensajes XML-RPC, encriptación, etc., todo se combina en un solo fragmento XML), con SOAP, el procesamiento real ocurre para averiguar algo sobre el mensaje. Un mensaje SOAP típico también puede incluir un estilo de cifrado para ayudar al destinatario a procesar el mensaje. El ejemplo 12-1 muestra un sobre SOAP que termina con una especificación de codificación.

Ejemplo 12-1: Sobre SOAP

Caja de jabón http://www-106.ibm.com/developerworks/library/x-soapbx1.html

Como puede ver, el cifrado se establece dentro del sobre, lo que permite que la aplicación determine (utilizando el valor del atributo encodingStyle) si puede leer el mensaje entrante ubicado en el elemento Cuerpo. Asegúrese de que el espacio de nombres del sobre SOAP sea correcto, o los servidores SOAP que reciben su mensaje arrojarán un error de discrepancia de versión y no podrá interactuar con ellos.

Cifrado

El segundo elemento importante de SOAP es la capacidad de cifrar tipos de datos personalizados. En RPC (y XML-RPC), el cifrado solo se puede realizar en tipos de datos predefinidos compatibles con el kit de herramientas XML-RPC que descargó. Cifrar otros tipos de datos requiere que usted mismo modifique el servidor RPC y el cliente. Con SOAP, se puede usar un esquema XML con bastante facilidad para especificar nuevos tipos de datos (usando el tipocomplejo, discutido en el Capítulo 2 de mi libro), y estos nuevos tipos se pueden representar en XML como parte de la sección principal de SOAP. Gracias a la integración del esquema XML, puede cifrar cualquier tipo de datos en un mensaje SOAP describiéndolos lógicamente en un esquema XML.

Llamar

La mejor manera de comprender cómo funciona una llamada SOAP es compararla con algo con lo que esté familiarizado, como XML-RPC. Si recuerda, la llamada XML-RPC se parece al fragmento de código que se muestra en el Ejemplo 12-2.

Ejemplo 12-2. Llamada a XML-RPC

// Especificación del controlador XML (analizador) para usar XmlRpc.setDriver("org.apache.xerces.parsers.SAXParser"); // Especificar el servidor para conectarse a XmlRpcClient client = new XmlRpcClient("http://rpc.middleearth.com"); // Crear parámetros Vector params = new Vector(); params.addElement(númeroVuelo); params.addElement(numSeats); params.addElement(tipo de tarjeta de credito); params.addElement(creditCardNum); // Consulta Boolean boletos comprados = (Boolean) client.execute ("ticketCounter.buyTickets", params); // Manejo de la respuesta

yo creé el programa mas simple para la reserva de billetes de avión. Ahora observe el Ejemplo 12-3, que demuestra una llamada SOAP.

Ejemplo 12-3. Llamar a SOAP

// Crear parámetros Vector params = new Vector(); params.addElement(nuevo Parámetro("NúmeroVuelo", Integer.class, NúmeroVuelo, nulo)); params.addElement(nuevo Parámetro("numSeats", Integer.class, numSeats, null)); params.addElement(nuevo Parámetro("creditCardType", String.class, creditCardType, null)); params.addElement(nuevo Parámetro("creditCardNumber", Long.class, creditCardNum, null)); // Crear un objeto de llamada Llama llama= nueva llamada (); call.setTargetObjectURI("urn:xmltoday-airline-tickets"); call.setMethodName("comprarBoletos"); call.setEncodingStyleURI(Constantes.NS_URI_SOAP_ENC); llamar a setParams(parámetros); // Respuesta de llamada res = call.invoke(nueva URL("http://rpc.middleearth.com"), ""); // Manejo de la respuesta

Como puede ver, la llamada en sí, representada por el objeto llamar, residente en la memoria. Le permite establecer el destino de la llamada, el método de llamada, el estilo de cifrado, las opciones y muchas otras opciones que no se muestran en este ejemplo. Este es un mecanismo más flexible que el método XML-RPC, que le permite establecer explícitamente un conjunto de varias opciones que están implícitamente definidas en XML-RPC. Más adelante en este artículo, aprenderá más sobre el proceso de llamada, incluido cómo SOAP maneja las solicitudes no válidas, la jerarquía de errores y, por supuesto, los resultados devueltos de la llamada.

Después de una introducción tan breve, ya sabes lo suficiente como para interesarte por esta cosa tan divertida. Ahora déjame presentarte la implementación de SOAP que voy a usar. Explicaré las razones por las que lo elegí y veré algunos ejemplos de código.

Configuración

Ahora que ha cubierto los conceptos básicos del concepto, es hora de la parte divertida: la programación. Para hacer esto, necesita un proyecto o producto conveniente, que sea más fácil de encontrar de lo que parece a primera vista. Si necesita un proyecto Java que proporcione capacidades SOAP, no busque más. Hay dos grupos de productos: comerciales y gratuitos. Como en mi libro, evitaré mencionar productos comerciales. Esto no es en absoluto porque sean malos (al contrario, algunos son excelentes), sino porque me gustaría que cualquier lector pudiera probar alguno de los ejemplos dados. Esto se debe a la disponibilidad que muchos productos comerciales no tienen. Debe pagar para usarlos, o usarlos temporalmente por un período de tiempo limitado después de la descarga.

Por lo tanto, nos acercamos sin problemas a los proyectos de código abierto. De esta área, solo puedo nombrar un producto: Apache SOAP. Se encuentra en http://xml.apache.org/soap y proporciona un conjunto de herramientas SOAP para Java. En el momento de escribir este artículo, la versión 2.2 está disponible y puede descargarla desde el sitio web de Apache. Es esta versión la que usaré en los ejemplos de este artículo.

Otras alternativas

Antes de continuar con la instalación y configuración de Apache SOAP, responderé algunas preguntas que pueden haber pasado por su mente. Creo que he dejado lo suficientemente claro por qué no uso productos comerciales. Sin embargo, puede pensar en otros proyectos de código abierto o relacionados que le gustaría usar, y se sorprende de que no los haya comentado.

¿Qué hay de IBM SOAP4J?

La primera en la lista de alternativas es una implementación de IBM: SOAP4J. El trabajo de IBM formó la base del proyecto Apache SOAP, al igual que XML4J de IBM se convirtió en lo que ahora se conoce como el proyecto de analizador XML Apache Xerces. Se espera que la implementación de IBM sea rediseñada, fusionándose con Apache SOAP. Más o menos lo mismo sucedió con XML4J de IBM: ahora solo proporciona empaquetado en Xerces. Esto solo enfatiza las tendencias: los grandes fabricantes a menudo admiten y usan proyectos OpenSource, en este caso ambos proyectos (Apache e IBM) usan la misma base de código.

¿Está Microsoft fuera del juego?

Claro que no. Microsoft y su implementación de SOAP, así como toda la rama .NET (más sobre eso en mi libro), son importantes. En realidad, quería pasar la mayor parte de mi tiempo mirando la implementación SOAP de Microsoft en detalle, pero solo admite objetos COM y no admite Java. Por estas razones, tal descripción no podría incluirse en un artículo sobre Java y XML. Sin embargo, Microsoft (a pesar de todas las quejas que nosotros, como desarrolladores, tenemos contra esta empresa) ha realizado un trabajo importante en el campo de los servicios web, y cometerá un error si lo descarta sin dudarlo, guiado solo por emociones crudas. Si necesita trabajar con componentes COM o Visual Basic, le recomiendo que intente usar el kit de herramientas Microsoft SOAP disponible en http://msdn.microsoft.com/library/default.asp?url=/nhp/Default. asp ?contentid=28000523 junto con muchos otros recursos SOAP.

¿Qué es el eje?

Aquellos de ustedes que siguen a Apache deben haber oído hablar de Apache Axis. Axis es el kit de herramientas SOAP de próxima generación, también en desarrollo bajo los auspicios de Apache XML. SOAP (una especificación, no una implementación específica), que ha evolucionado rápida y radicalmente últimamente, es muy difícil de seguir. También es bastante difícil tratar de crear una versión de SOAP que cumpla completamente con los requisitos actuales que cambian a lo largo del desarrollo. Como resultado, Versión actual Apache SOAP ofrece una solución, limitada por su diseño. Al decidir que no valía la pena intentar rediseñar por completo la herramienta existente, los desarrolladores de Apache se dispusieron a crear un proyecto basado en el nuevo código. Así nació Axis. El nombre de SOAP también cambió, primero de SOAP a XP y luego a XMLP. Luego, el nombre de la especificación se eliminó del nombre del nuevo SOAP y nació el nombre "Axis". Pero ahora parece que el W3C está volviendo al nombre de la especificación SOAP (versión 1.2 o 2.0), por lo que las cosas aún pueden cambiar y habrá aún más confusión.

Piense en IBM SOAP4J como la arquitectura1 del kit de herramientas SOAP. ¿Qué pasa con Apache SOAP (discutido en este artículo) como arquitectura?2. Y Axis representa arquitectura?3, arquitectura de próxima generación. Este proyecto usa SAX mientras que Apache SOAP está basado en DOM. Además, Axis, a diferencia de Apache SOAP, ofrece un enfoque más amigable para la interacción con el usuario. Después de enumerar estas ventajas, probablemente se sorprenderá de por qué no elegí Axis como tema de estudio. Sería un poco prematuro. Actualmente, solo se está preparando para su lanzamiento la versión 0.51 de Axis. Todavía no es beta, ni siquiera alfa. Me encantaría cubrir las nuevas características de Axis, pero no hay forma de que pueda convencer a su gerencia de usar software de código abierto pre-alfa para las necesidades de su sistema más importante. Así que decidí centrarme en algo que eres real puedes usar ya Hoy- Apache SOAP. Creo que para cuando se publique la versión final de Apache Axis, actualizaré este material en la próxima edición de mi libro. Hasta entonces, concentrémonos en la solución que ya está disponible.

Instalación

Hay dos formas de configuración de SOAP. El primero es lanzar un cliente SOAP, usando la API SOAP para comunicarse con un servidor que pueda recibir mensajes SOAP. La segunda forma es iniciar un servidor SOAP que pueda recibir mensajes de un cliente SOAP. En esta sección, he descrito ambos procedimientos.

Cliente

Para usar el cliente SOAP, primero debe descargar Apache SOAP, disponible en http://xml.apache.org/dist/soap. Descargué la versión 2.2 en formato binario (del subdirectorio versión-2.2). Luego debe descomprimir el contenido del archivo en un directorio de su computadora. En mi caso fue el directorio javaxml2 (c:\javaxml2 en mi computadora con Windows /javaxml2 en mi computadora Mac OS X). Como resultado, los archivos se descomprimieron en /javaxml2/soap-2_2. También deberá descargar el paquete JavaMail disponible en el servidor de Sun http://java.sun.com/products/javamail/. Será necesario que admita el protocolo de transferencia SMTP utilizado por Apache SOAP. Luego descargue Java Beans Activation Framework (JAF), también disponible desde el servidor Sun http://java.sun.com/products/beans/glasgow/jaf.html. Basado en el supuesto de que ya tiene Xerces u otro analizador XML instalado y listo para usar.

Nota: Asegúrese de que su analizador XML sea compatible con JAXP y utilice el espacio de nombres correcto. Lo más probable es que su analizador cumpla con estos requisitos. Si tiene problemas, es mejor volver a usar Xerces.

Nota: Usar Últimas Versiones Xerces. La versión 1.4 y superior servirá. Hay una serie de errores cuando se trabaja con SOAP y Xerces 1.3(.1), por lo que le aconsejo que no utilice esta combinación.

Descomprima los paquetes de JavaMail y JAF y luego incluya sus archivos jar en su classpath, así como en la biblioteca. tarro.de.jabon. Cada uno de estos archivos jar debe estar ubicado en el directorio raíz del programa correspondiente o en un subdirectorio /lib. Al completar su variable ruta de clases debería verse algo como esto:

$ echo $CLASSPATH /javaxml2/soap-2_2/lib/soap.jar:/javaxml2/lib/xerces.jar: /javaxml2/javamail-1.2/mail.jar:/javaxml2/jaf-1.0.1/activation.jar

Para Windows se verá así:

c:\>echo %CLASSPATH% c:\javaxml2\soap-2_2\lib\soap.jar;c:\javaxml2\lib\xerces.jar; c:\javaxml2\javamail-1.2\mail.jar;c:\javaxml2\jaf-1.0.1\activation.jar

Y finalmente agregar el directorio. javaxml2/soap-2_2/ en tus ruta de clases para ejecutar los ejemplos de SOAP. He descrito la configuración de varios de los ejemplos en este capítulo.

Servidor

Para crear un conjunto de componentes del lado del servidor compatible con SOAP, primero necesita un motor de servlet. Como en capítulos anteriores, utilicé Apache Tomcat (disponible en http://jakarta.apache.org/) como ejemplo para este capítulo. Deberá agregar todo lo que el cliente necesita para ruta de clases servidor. La forma más fácil de hacer esto es restablecer tarro.de.jabon, activación.jar Y correo.jar, así como su analizador, al directorio de bibliotecas de su motor de servlet. Para Tomcat, este es el directorio /lib, que contiene bibliotecas para la carga automática. Si desea proporcionar soporte para secuencias de comandos (que no se analizan en este capítulo, pero se encuentran en los ejemplos de Apache SOAP), debe poner bsf.jar(disponible en http://oss.software.ibm.com/developerworks/projects/bsf) y js.jar(disponible en http://www.mozilla.org/rhino/) al mismo directorio.

Nota: Si está utilizando Xerces con Tomcat, deberá repetir el truco que describí en el Capítulo 10. Renombrar analizador.jar V z_parser.jar, A jaxp.jar V z_jaxp.jar asegurarse de xerces.jar y la versión incluida de JAXP se carga antes que cualquier otro analizador o implementación de JAXP.

Luego, vuelva a cargar su motor de servlet y estará listo para escribir componentes de servidor SOAP.

Servlet de enrutador y cliente de administración

Además de las operaciones básicas, Apache SOAP incluye un servlet de enrutador y un cliente de administración. Incluso si no tiene la intención de usarlos, le recomiendo que los instale para probar que SOAP está instalado correctamente. Este proceso depende del motor de servlet que esté utilizando, por lo que me limitaré a describir el proceso de instalación de Tomcat. Las instrucciones de instalación para otros motores de servlet se pueden encontrar en http://xml.apache.org/soap/docs/index.html.

La instalación bajo Tomcat es muy simple: solo tome el archivo jabón.guerra del directorio jabón-2_2/webapps y colóquelo en un directorio $TOMCAT_HOME/aplicaciones web- ¡y eso es! Para verificar la instalación, ingrese la dirección en el navegador http://localhost:8080/soap/servlet/rpcrouter. Debería recibir una respuesta similar a la que se muestra en la Figura 12-2.

Figura 12-2. Servlet RPC del enrutador

Aunque el mensaje parece un mensaje de error, indica que todo funciona correctamente. Debería obtener la misma respuesta apuntando su navegador a la dirección del cliente de administración: http://localhost:8080/soap/servlet/enrutador de mensajes.

Para completar la prueba del servidor y del cliente, asegúrese de haber seguido todas las instrucciones por completo. Luego ejecute la siguiente clase de Java como se muestra a continuación para mantener la URL de su servlet para el servlet del enrutador RPC:

C:\>java org.apache.soap.server.ServiceManagerClient http://localhost:8080/soap/servlet/rpcrouter list Servicios implementados:

Debería obtener una lista vacía de servicios como se muestra arriba. Si recibe algún mensaje, consulte la larga lista de posibles errores disponible en http://xml.apache.org/soap/docs/trouble/index.html. Esta es la lista más completa de problemas que puede encontrar. Si obtiene una lista vacía, la configuración está completa y está listo para comenzar a ver los ejemplos de este capítulo.

Empecemos

Hay tres pasos principales para escribir cualquier sistema basado en SOAP. Habiendo enumerado, me detendré brevemente en cada uno de ellos:

  • Elección entre mensajes SOAP-RPC y SOAP;
  • Escribir o acceder a un servicio SOAP;
  • Escribir o acceder a un cliente SOAP.

El primer paso es elegir si usará SOAP para llamadas RPC (donde el procedimiento remoto se ejecuta en el servidor) o mensajes (donde el cliente simplemente envía información al servidor). Discuto estos procesos en detalle a continuación. Una vez que haya tomado esta decisión, deberá acceder o crear su propio servicio. Por supuesto, dado que todos somos profesionales de Java, este capítulo trata sobre cómo crear uno propio. Y finalmente, necesita escribir un cliente para este servicio, ¡eso es todo!

¿RPC o Mensajería?

Su primera tarea no tiene nada que ver con la programación y es más una tarea de diseño. Debe elegir si utilizará el servicio RPC o los mensajes. Asumiremos que está muy familiarizado con RPC (por ejemplo, leyendo uno de los capítulos de mi libro). El cliente ejecuta un procedimiento remoto en el servidor y luego recibe una respuesta. En este escenario, SOAP actúa como un rico sistema XML-RPC que proporciona un mejor manejo de errores y transferencia de tipos de datos complejos a través de la red. Ya está familiarizado con este concepto, y dado que es más fácil escribir sistemas RPC en SOAP, comenzaré con ellos. Este artículo describe cómo crear un servicio RPC, un cliente RPC y poner el sistema en acción.

Otra forma en que funciona SOAP se basa en la mensajería. En lugar de realizar trámites a distancia, solo se utiliza para compartir información. Como puede adivinar, esta es una herramienta poderosa que no requiere que el cliente conozca los métodos individuales de ningún servidor. También hace que la simulación de sistemas remotos esté más aislada al permitir que los paquetes de datos (paquetes en sentido figurado, no en el sentido de red) se transmitan a otros sistemas. Al mismo tiempo, otros sistemas no necesitan saber sobre las operaciones que se realizaron con estos datos. Este estilo es más complejo que la programación RPC, por lo que no lo mencionaré aquí. Lo encontrará en mi libro, junto con otros detalles de interacción de empresa a empresa. Para comenzar, familiarícese con la programación SOAP-RPC.

Como la mayoría de los problemas de diseño, esta decisión depende totalmente de usted. Analice su aplicación e intente determinar para qué necesita usar SOAP. Si tiene un servidor y un conjunto de clientes que realizan funciones comerciales específicas bajo demanda, entonces RPC es más adecuado para usted. EN sistemas complejos donde la comunicación es algo más que realizar funciones comerciales específicas bajo demanda, se prefieren los mensajes SOAP.

servicio RPC

Ahora que los trámites han terminado, es hora de actuar. Como sabe, en RPC necesita clases cuyos métodos se ejecutarán de forma remota.

Fragmentos de código

Comenzaré mirando los fragmentos de código del servidor. Estos fragmentos son clases con métodos que se ejecutan en clientes RPC. Usé código de mi libro como ejemplos. En lugar de usar clases simples, elegí un ejemplo más complejo para demostrar las posibilidades de SOAP de la manera más clara posible. Entonces, usé la clase CD como ejemplo. Primero definimos el elemento mapa para cada tipo de parámetro no estándar. por atributo encodingStyle, al menos en Apache SOAP 2.2. debe especificar el valor http://schemas.xmlsoap.org/soap/encoding/ . Esta es actualmente la única codificación admitida. Debe especificar el espacio de nombres para el tipo definido por el usuario, seguido del nombre de la clase seguido del prefijo del espacio de nombres para ese tipo. En nuestro caso, para estos fines, utilicé un espacio de nombres ficticio y un prefijo simple " X". Entonces usando el atributo tipojava, establezca el nombre real de la clase Java (en este caso, javaxml2.cd). Y, finalmente, curalesil con atributos java2XMLClassName Y xml2JavaClassName. Definen una clase que convierte de Java a XML y viceversa. Usé la increíblemente útil clase BeanSerializer, también incluida con Apache SOAP. Si su parámetro personalizado está en formato JavaBean, este serializador y deserializador le ahorrará la molestia de escribir el suyo propio. Necesita una clase con un constructor predeterminado (recuerde, le di a la clase de CD un constructor simple y sin parámetros) y publique todos los datos de esa clase usando métodos conjuntoXXX Y obtenerXXX. Desde la clase CD cumple perfectamente todos estos requisitos, BeanSerializador funciona perfecto

Nota: Que clase CD cumple con los requisitos BeanSerializador. no importa mucho La mayoría de las clases se convierten fácilmente a este formato. Por lo tanto, le aconsejo que evite escribir sus propios serializadores y deserializadores. esto es superfluo dolor de cabeza(nada complicado, pero demasiado minucioso) y le recomiendo que guarde sus esfuerzos y use la conversión de beans en sus parámetros de usuario. En muchos casos, las conversiones de beans solo requieren que tenga un constructor predeterminado (sin parámetros) en su clase.

Ahora vamos a recrear frasco archivar y volver a alojar nuestro servicio:

(gandalf)/javaxml2/Ch12$ java org.apache.soap.server.ServiceManagerClient http://localhost:8080/soap/servlet/rpcrouter xml/CDCatalogDD.xml

Atención: Si deja su motor de servlet en ejecución y vuelve a hospedar el servicio al mismo tiempo, deberá reiniciar el motor de servlet para activar las nuevas clases para el servicio SOAP y volver a hospedar el servicio.

Ahora todo lo que queda es modificar el cliente para usar las nuevas clases y métodos. El ejemplo 12-10 contiene una versión modificada de la clase de cliente CDAdder. Cambios hechos a versión previa, resaltado.

Ejemplo 12-10: clase CDAdder actualizada

paquete javaxml2; importar java.net.URL; importar java.util.Vector; importar org.apache.soap.Constants; importar org.apache.soap.Fault; importar org.apache.soap.SOAPException; importar org.apache.soap.encoding.SOAPMappingRegistry; importar org.apache.soap.encoding.soapenc.BeanSerializer; importar org.apache.soap.rpc.Call; importar org.apache.soap.rpc.Parameter; importar org.apache.soap.rpc.Response; importar org.apache.soap.util.xml.QName; CDAdder de clase pública ( public void add(URL url, String title, String artist, String label) lanza SOAPException ( System.out.println("Añadir CD con título "" + título + "" por artista "" + artista + "" estudio " + etiqueta); CD cd = nuevo CD (título, artista, etiqueta); // Crear un objeto de llamada Call Call call = new Call(); call.setSOAPMappingRegistry(registro); call.setTargetObjectURI("urna:cd-catálogo"); call.setMethodName("addCD"); call.setEncodingStyleURI(Constantes.NS_URI_SOAP_ENC); // Configuración de parámetros Vector params = new Vector(); params.addElement(nuevo Parámetro("cd", CD.class, cd, null)); llamar a setParams(parámetros); // Manejar Invocar llamada Respuesta de respuesta; respuesta = llamada.invocar(url, ""); if (!response.generatedFault()) ( System.out.println("La adición del CD se completó con éxito."); ) else ( Fault Fault = response.getFault(); System.out.println(Error: " + Fault.getFaultString ()); ) ) public static void main(String args) ( if (args.length != 4) ( System.out.println("Plantilla: java javaxml2.CDAdder " + "\"[Título del CD]\" \"[Nombre del artista]\ " \"[Estudio de CD]\""); volver; ) try ( // URL del servidor SOAP para conectarse a URL url = nueva URL (argumentos); // Obtener valores para el nuevo CD String title = args; Artista de cuerdas = argumentos; Etiqueta de cadena = argumentos; // Agrega el CD CDAdder sumador = new CDAdder(); adder.add(url, título, artista, etiqueta); ) catch (Excepción e) ( e.printStackTrace(); ) ) )

El único cambio realmente interesante tiene que ver con el mapeo de clases. CD:

// Asigne este tipo para que pueda usarse con SOAP SOAPMappingRegistry registro = new SOAPMappingRegistry(); BeanSerializer serializador = new BeanSerializer(); registro.mapTypes(Constants.NS_URI_SOAP_ENC, new QName("urn:cd-catalog-demo", "cd"), CD.class, serializer, serializer);

Así es como se puede codificar y transmitir un parámetro de usuario a través de la red. Ya he dicho cómo la clase BeanSerializador se puede utilizar para procesar parámetros en formato JavaBean, como una clase CD. Usé un descriptor de implementación para especificarlos en el servidor, pero ahora necesito decirle al cliente que use este serializador y deserializador. Esta función la realiza la clase SOAPmappingRegistro. Método tipos de mapa () toma la cadena encriptada (nuevamente, es mejor usar la constante NS_URI_SOAP_ENC) e información sobre el tipo de parámetro para el que se debe utilizar una serialización especial. QName se especifica primero. Esta es la razón por la que se utilizó el espacio de nombres extraño en el descriptor de ubicación. Debe especificar el mismo URN aquí, así como el nombre local del elemento (para este ejemplo, "CD"), luego el objeto Java clase clase a ser serializada ( cd.clase) y finalmente una instancia de la clase a serializar y deserializar. Para este ejemplo, en ambos casos aparecerá la instancia BeanSerializador. Después de ingresar todas estas configuraciones en el registro, informe al objeto al respecto llamar utilizando el método setSOAPMapping-Registro().

Puede ejecutar esta clase como se muestra antes agregando un CD y todo debería funcionar como se esperaba:

C:\javaxml2\build>java javaxml2.CDAdder http://localhost:8080/soap/servlet/rpcrouter "Tony Rice" "Manzanita" "Sugar Hill" Adición de CD titulado "Tony Rice" por "Manzanita" por Sugar Hill Studio Adición exitosa de CD.

Salí de la modificación de clases. Lista de CD para ti. Todo está hecho de acuerdo con el mismo patrón. Para ponerte a prueba, puedes consultar los archivos de ejemplo de mi libro, que ya contienen estas clases actualizadas.

Nota: Puede decidir eso porque la clase Lista de CD no interactúa directamente con el objeto CD(devuelto por método lista() el tipo importa Tabla de picadillo) entonces no necesita hacer ningún cambio. Sin embargo, la clase de retorno Tabla de picadillo contiene instancias de objetos CD. Si SOAP no sabe cómo deserializarlos, el cliente emitirá un mensaje de error. En este caso, para resolver el problema, debe especificar en el objeto llamar instancia SOAPmappingRegistro.

Manejo eficiente de errores

Ahora que ha visto los objetos de usuario, ha realizado llamadas RPC, etc., permítame hablar de un tema menos interesante: el manejo de errores. En cualquier transacción de red, pueden ocurrir muchas fallas. El servicio no se inicia, hay un error en la operación del servidor, no se encuentra un objeto, faltan clases y muchos otros problemas. Hasta ahora solo he usado el método falla.getString() para generar mensajes de error. Pero este método puede no ser siempre útil. Para verlo en acción, descoméntalo en el constructor. CDCatálogo:

CDCatálogo público() ( //catálogo = nueva tabla hash(); // Crear directorio addCD(nuevo CD("Nickel Creek", "Nickel Creek", "Sugar Hill")); addCD(nuevo CD("Let it Fall", "Sean Watkins", "Sugar Hill")); addCD(nuevo CD("Límites aéreos", "Michael Hedges", "Windham Hill")); addCD(nuevo CD("Taproot", "Michael Hedges", "Windham Hill")); )

Vuelva a compilarlo, reinicie el motor de servlet y vuelva a alojarlo. Esto resultará en una excepción. Excepción de puntero nulo cuando el constructor de clase intenta agregar CD a no inicializado Tabla de picadillo. Al iniciar el cliente, aparecerá un mensaje de error, pero no será muy informativo:

(gandalf)/javaxml2/build$ java javaxml2.CDLister http://localhost:8080/soap/servlet/rpcrouter Ver el directorio del CD actual. Error: no se puede resolver el objeto de destino: nulo

Este no es el tipo de información que puede ayudar a detectar y corregir un error. Sin embargo, el marco hace un buen trabajo al manejar los errores. Te acuerdas DOMFaultListener, que estableces como el valor del elemento fallaOyente? Es hora de que entre en el juego. Devolver objeto en caso de error Falla contiene DOM (Modelo de objeto de documento) org.w3c.dom.Elemento con información detallada sobre el error. Primero, agregue una declaración de importación a su código fuente java.util.Iterator:

importar java.net.URL; importar java.util.enumeration; importar java.util.Hashtable; importar java.util.Iterator; importar java.util.Vector; importar org.apache.soap.Constantes; importar org.apache.soap.Fault; importar org.apache.soap.SOAPException; importar org.apache.soap.encoding.SOAPMappingRegistry; importar org.apache.soap.encoding.soapenc.BeanSerializer; importar org.apache.soap.rpc.Call; importar org.apache.soap.rpc.Parameter; importar org.apache.soap.rpc.Response; importar org.apache.soap.util.xml.QName;

Ahora hagamos cambios para manejar los errores en el método list():

if (!response.generatedFault()) ( Parámetro returnValue = respuesta.getReturnValue(); Hashtable catalog = (Hashtable)returnValue.getValue(); Enumeración e = catalog.keys(); while (e.hasMoreElements()) ( String título = (String)e.nextElement(); CD cd = (CD)catalog.get(title); System.out.println(" "" + cd.getTitle() + "" artista " + cd.getArtist() + " estudios " + cd.getLabel()); ) ) else ( Fallo fallo = respuesta.getFault(); System.out.println("Error: " + fallo.getFaultString()); Entradas de vectores = fallo.getDetailEntries(); for (Iterador i = entradas.iterador(); i.hasNext();) ( org.w3c.dom.Element entrada = (org.w3c.dom.Element)i.next(); System.out.println(entrada .getFirstChild().getNodeValue()); ) )

Usando el método obtenerEntradasDetalles() accede al servicio SOAP respaldado y al servidor de datos sin procesar, con información sobre el problema. El código los vuelve a procesar (por lo general, solo hay un elemento, pero requiere mucha atención) e intercepta el DOM elemento Los contenidos en cada entrada. Esencialmente, aquí está el XML con el que está trabajando:

SOAP-ENV:Servidor.BadTargetObjectURI No se puede resolver el destino: nulo ¡Esto es lo que queremos!

En otras palabras, el objeto Fault le da acceso a la parte del sobre SOAP que contiene errores. Además, Apache SOAP proporciona un seguimiento de la pila de Java cuando se producen errores, proporcionando información detallada necesaria para corregirlos. Interceptar un elemento stackTrace e imprimiendo el valor del nodo Texto desde este elemento, su cliente puede imprimir el seguimiento de la pila del servidor. Después de compilar estos cambios y reiniciar el cliente, obtendrá el siguiente resultado:

C:\javaxml2\build>java javaxml2.CDLister http://localhost:8080/soap/servlet/rpcr external Ver el directorio del CD actual. Error: no se puede resolver el destino: java.lang.NullPointerException nulo en javaxml2.CDCatalog.addCD(CDCatalog.java:24) en javaxml2.CDCatalog. (CDCatalog.java:14) a java.lang.Class.newInstance0(Método nativo) a java.lang.Class.newInstance(Class.java:237)

No es mucho mejor, pero al menos puede ver el dato de que se ha producido una excepción. Excepción de puntero nulo e incluso averiguar los números de línea en las clases de servidor que tienen este problema. El resultado de estos últimos cambios le ha dado una representación visual del problema de manejo de errores. Ahora debe verificar las clases de su servidor en busca de errores. Sí, casi lo olvido, antes de eso, no olvides volver a cambiar tu clase. CDCatálogo¡para deshacerse de los errores que introdujimos intencionalmente para mayor claridad!

  1. Se habla mucho de ejecutar SOAP sobre otros protocolos como SMTP (o incluso Jabber). Hasta el momento, el estándar SOAP no proporciona esto, pero dichas características pueden agregarse en el futuro. Por lo tanto, no se sorprenda si se encuentra con discusiones activas sobre este tema.
  • tutorial

¡Hola a todos!
Dio la casualidad de que recientemente me he involucrado en el desarrollo de servicios web. Pero hoy el tema no es sobre mí, sino sobre cómo podemos escribir nuestro propio Servicio Web XML basado en el protocolo SOAP 1.2.

Espero que después de leer el tema, usted será capaz de:

  • escribir su propia implementación de servidor de una aplicación web;
  • escribir su propia implementación de cliente de una aplicación web;
  • escriba su propia descripción del servicio web (WSDL);
  • enviar matrices del mismo tipo de datos al servidor por parte del cliente.
Como puedes suponer, toda la magia se hará con usando PHP y clases SoapClient y SoapServer integradas. Como conejo, tendremos un servicio de envío de mensajes sms.

1 enunciado del problema

1.1 Fronteras

Al principio, propongo tratar el resultado que lograremos al final del tema. Como se anunció anteriormente, escribiremos un servicio para enviar mensajes sms y, más precisamente, recibiremos mensajes de diferentes fuentes utilizando el protocolo SOAP. Después de eso, consideraremos en qué forma llegan al servidor. Desafortunadamente, el proceso de poner en cola los mensajes para su posterior envío al proveedor está más allá del alcance de esta publicación por muchas razones.

1.2 ¿Qué datos se cambiarán?

¡Muy bien, tenemos los límites! El siguiente paso que debe hacerse es decidir qué datos intercambiaremos entre el servidor y el cliente. Sobre este tema, propongo no ser más sabio por mucho tiempo e inmediatamente responder las preguntas principales:
  • ¿Qué datos mínimos se deben enviar al servidor para enviar un mensaje SMS a un suscriptor?
  • ¿Cuál es la cantidad mínima de datos que se debe enviar desde el servidor para satisfacer las necesidades del cliente?
Algo me dice que para ello es necesario enviar lo siguiente: En principio, estas dos características son suficientes para enviar, pero inmediatamente me parece que un sms con saludos de cumpleaños te llega a las 3 de la mañana, ¡o a las 4! ¡En este momento, estaré muy agradecido con todos por no olvidarse de mí! Por lo tanto, también enviaremos al servidor y
  • la fecha en que se envió el mensaje SMS.
Lo siguiente que me gustaría enviar al servidor es
  • Tipo de mensaje.
Este parámetro no es obligatorio, pero nos puede resultar muy útil si necesitamos decirle rápidamente al jefe a cuántos de nuestros clientes hemos “encantado” con nuestras novedades, y además sacar unas bonitas estadísticas al respecto.

¡Y sin embargo, olvidé algo! Si reflexionamos un poco más, vale la pena señalar que el cliente puede enviar un mensaje SMS al servidor a la vez, o un número determinado de ellos. En otras palabras, en un paquete de datos puede haber desde uno hasta infinidad de mensajes.

Como resultado, conseguimos que para enviar un mensaje SMS necesitamos los siguientes datos:

  • Número de teléfono móvil,
  • mensaje de texto,
  • el momento de enviar un mensaje SMS a un suscriptor,
  • Tipo de mensaje.

Respondimos la primera pregunta, ahora es necesario responder la segunda pregunta. Y tal vez me permitiré hacer un poco de trampa. Por tanto, desde el servidor enviaremos únicamente datos booleanos, cuyo valor tiene el siguiente significado:

  • VERDADERO: el paquete llegó correctamente al servidor, pasó la autenticación y se puso en cola para enviarlo al proveedor de sms
  • FALSO - en todos los demás casos

¡Esto concluye la descripción del enunciado del problema! Y finalmente, vayamos a la parte más interesante: ¡descubriremos qué tipo de bestia extravagante es este SOAP!

2 ¿Qué es SOAP?

En general, inicialmente no planeé escribir nada sobre lo que es SOAP y quería limitarme a enlaces al sitio w3.org con las especificaciones necesarias, así como enlaces a Wikipedia. Pero al final decidí escribir una breve referencia sobre este protocolo.

Y comenzaré mi historia con el hecho de que este protocolo de intercambio de datos pertenece a un subconjunto de protocolos basados ​​en el llamado paradigma RPC (Remote Procedure Call), cuya antípoda es REST (Representational State Transfer, transferencia de estado representativo). Puede leer más sobre esto en Wikipedia, los enlaces a los artículos se encuentran al final del tema. A partir de estos artículos, debemos comprender lo siguiente: “El enfoque RPC le permite utilizar una pequeña cantidad de recursos de red con una gran cantidad de métodos y un protocolo complejo. Con un enfoque REST, la cantidad de métodos y la complejidad del protocolo están severamente limitadas, lo que puede generar una gran cantidad de recursos individuales”. Es decir, en relación con nosotros, esto significa que en el sitio en el caso del enfoque RPC siempre habrá una entrada (enlace) al servicio y qué procedimiento llamar para procesar los datos entrantes que pasamos junto con los datos, mientras que con el enfoque REST en nuestro sitio tiene muchas entradas (enlaces), cada una de las cuales acepta y procesa solo ciertos datos. Si alguien que lee sabe cómo explicar la diferencia en estos enfoques aún más fácilmente, ¡asegúrese de escribir en los comentarios!

Lo siguiente que debemos saber sobre SOAP es que este protocolo usa el mismo XML como transporte, lo cual, por un lado, es muy bueno, porque. nuestro arsenal incluye de inmediato todo el poder de la pila de tecnologías basadas en este lenguaje de marcado, a saber, XML-Schema, un lenguaje para describir la estructura de un documento XML (¡gracias a Wikipedia!), que permite la validación automática de los datos recibidos por el servidor de clientes

Y así, ahora sabemos que SOAP es el protocolo utilizado para implementar la llamada a procedimiento remoto y utiliza XML como transporte. Si lee el artículo en Wikipedia, a partir de ahí también puede aprender que se puede usar sobre cualquier protocolo de capa de aplicación, y no solo emparejado con HTTP (lamentablemente, en este tema solo consideraremos SOAP sobre HTTP). ¿Y sabes lo que más me gusta de todo esto? Si no hay conjeturas, entonces te daré una pista: ¡SOAP!... ¿No hay conjeturas de todos modos?... ¿Definitivamente leíste el artículo en Wikipedia?... En general, no te torturaré más. Por lo tanto, pasaré inmediatamente a la respuesta: "SOAP (del inglés. Simple Object Access Protocol - a simple protocolo acceso a objetos; hasta la especificación 1.2)". ¡Lo más destacado de esta línea está en cursiva! No sé qué conclusiones sacó de todo esto, pero veo lo siguiente: dado que este protocolo de ninguna manera puede llamarse "simple" (y aparentemente incluso w3 está de acuerdo con esto), luego, desde la versión 1.2, ha dejado de ser descifrado en absoluto! Y se hizo conocido como SOAP, simplemente SOAP y punto.

Bueno, está bien, disculpe, patinó un poco hacia un lado. Como escribí anteriormente, XML se utiliza como transporte y los paquetes que se ejecutan entre el cliente y el servidor se denominan sobres SOAP. Si consideramos la estructura generalizada del sobre, entonces le parecerá muy familiar, porque se asemeja a la estructura de una página HTML. Tiene una sección principal - Envolver, que incluye secciones encabezamiento Y Cuerpo, o Falla. EN Cuerpo se transmiten datos y es un apartado obligatorio del sobre, mientras que encabezamiento es opcional. EN encabezamiento se puede transmitir la autorización, o cualquier otro dato que no esté directamente relacionado con los datos de entrada de los procedimientos del servicio web. Pro Falla no hay nada especial que contar, excepto que llega al cliente desde el servidor en caso de errores.

Aquí es donde termina mi historia general sobre el protocolo SOAP (veremos los sobres en sí mismos y su estructura con más detalle cuando nuestro cliente y servidor finalmente aprendan cómo ejecutarlos entre sí) y comienza una nueva: sobre un compañero SOAP. llamado WSDL (servicios web Lenguaje de descripción). Sí, sí, esto es lo que nos asusta a la mayoría del intento de tomar e implementar nuestra propia API en este protocolo. Como resultado, normalmente reinventamos nuestra rueda con JSON como medio de transporte. Entonces, ¿qué es WSDL? WSDL es un lenguaje para describir servicios web y acceder a ellos, basado en lenguaje XML(c)Wikipedia. Si a partir de esta definición no te queda claro todo el significado sagrado de esta tecnología, ¡intentaré describirlo con mis propias palabras!

El WSDL está diseñado para permitir que nuestros clientes se comuniquen normalmente con el servidor. Para ello, en el archivo con extensión “*.wsdl” se describe la siguiente información:

  • Qué espacios de nombres se usaron,
  • Qué esquemas de datos se utilizaron,
  • Qué tipos de mensajes espera el servicio web de los clientes,
  • Qué datos pertenecen a qué procedimientos de servicios web,
  • Qué procedimientos contiene el servicio web,
  • Cómo debe el cliente llamar a los procedimientos del servicio web,
  • A qué dirección deben enviarse las llamadas de los clientes.
Como se vio, archivo dado y está todo el servicio web. ¡Al especificar la dirección del archivo WSDL en el cliente, sabremos todo sobre cualquier servicio web! Como resultado, no necesitamos saber absolutamente nada sobre dónde se encuentra el servicio web en sí. ¡Basta con conocer la ubicación de su archivo WSDL! Pronto descubriremos que SOAP no da tanto miedo como se pinta (c) proverbio ruso.

3 Introducción al esquema XML

Ahora sabemos mucho sobre qué es SOAP, qué contiene y tenemos una descripción general de qué tipo de tecnología lo rodea. Dado que, en primer lugar, SOAP es un método de interacción entre un cliente y un servidor, y el lenguaje de marcado XML se utiliza como transporte para ello, en esta sección comprenderemos un poco cómo se produce la validación automática de datos a través de esquemas XML.

La tarea principal del esquema es describir la estructura de los datos que vamos a procesar. Todos los datos en los esquemas XML se dividen en simple(escalar) y complejo(estructuras) tipos. Los tipos simples incluyen tipos tales como:

  • línea,
  • número,
  • booleano,
  • fecha de.
Algo muy simple que no tiene extensiones en su interior. Su antípoda son tipos complejos complejos. El ejemplo más simple de un tipo complejo que viene a la mente de todos son los objetos. Por ejemplo, un libro. El libro consta de propiedades: autor, Nombre, precio, Número ISBN etc. Y estas propiedades, a su vez, pueden ser tanto de tipos simples como complejos. Y la tarea del esquema XML es describirlo.

¡Propongo no ir muy lejos y escribir un esquema XML para nuestro mensaje sms! A continuación se muestra la descripción xml del mensaje sms:

71239876543 Mensaje de prueba 2013-07-20T12:00:00 12
Nuestro esquema de tipo complejo se verá así:


Esta entrada dice lo siguiente: tenemos una variable " mensaje" tipo " mensaje" y hay un tipo complejo llamado " mensaje", que consta de un conjunto secuencial de elementos" teléfono" tipo cadena, « texto" tipo cadena, « fecha" tipo fecha y hora, « tipo" tipo decimal. Estos tipos son simples y ya están definidos en la definición del esquema. ¡Felicidades! ¡Acabamos de escribir nuestro primer esquema XML!

Creo que el significado de los elementos " elemento" Y " tipocomplejo» todo quedó más o menos claro para usted, por lo que no nos centraremos más en ellos y cambiaremos inmediatamente al elemento del compositor « secuencia". Cuando usamos el elemento compositor " secuencia» le informamos que los elementos incluidos en el mismo deben estar siempre en la secuencia indicada en el esquema, y ​​además todos ellos son obligatorios. ¡Pero no te desesperes! Hay dos elementos de composición más en esquemas XML: elección" Y " todo". Compositor elección" indica que debe haber uno de los elementos enumerados en él, y el compositor " todo» – cualquier combinación de los elementos enumerados.

Como recordarán, en la primera sección del tema, coincidimos en que el paquete se puede transmitir desde uno hasta infinidad de mensajes sms. Por lo tanto, propongo comprender cómo se declaran dichos datos en el esquema XML. La estructura general del paquete podría verse así:

71239876543 Mensaje de prueba 1 2013-07-20T12:00:00 12 71239876543 Mensaje de prueba N 2013-07-20T12:00:00 12
El esquema para un tipo tan complejo se vería así:


El primer bloque contiene la declaración familiar del tipo complejo “ mensaje". Si nota, entonces en cada tipo simple incluido en " mensaje”, se han agregado nuevos atributos calificativos “ minOcurre" Y " maxOcurre". Como no es difícil de adivinar por el nombre, el primero ( minOcurre) indica que la secuencia dada debe contener al menos un elemento del tipo " teléfono», « texto», « fecha" Y " tipo”, mientras que el siguiente ( maxOcurre) el atributo nos declara que hay como máximo uno de esos elementos en nuestra secuencia. Como resultado, cuando escribimos nuestros esquemas para cualquier dato, se nos da la selección más amplia al configurarlos!

El segundo bloque del esquema declara el elemento " lista de mensajes" tipo " Lista de mensajes". Está claro que " Lista de mensajes' es un tipo complejo que incluye al menos un elemento ' mensaje”, ¡pero el número máximo de dichos elementos no está limitado!

4 Escribiendo su WSDL

¿Recuerdas que WSDL es nuestro servicio web? ¡Espero que lo recuerdes! Mientras lo escribimos, nuestro pequeño servicio web flotará sobre él. Así que te sugiero que no hagas trampa.

En general, para que todo nos funcione correctamente, necesitamos transferir un archivo WSDL con el tipo MIME correcto al cliente. Para hacer esto, debe configurar su servidor web en consecuencia, es decir, establecer el tipo MIME para archivos con la extensión *.wsdl en la siguiente línea:

Aplicación/wsdl+xml
Pero en la práctica, generalmente enviaba el encabezado HTTP a través de PHP " texto/xml»:

Encabezado("Tipo de contenido: texto/xml; juego de caracteres=utf-8");
y todo funcionó muy bien!

Quiero advertirle de inmediato, nuestro servicio web simple tendrá una descripción bastante impresionante, así que no se alarme, porque. la mayor parte del texto es obligatorio y, una vez escrito, se puede copiar constantemente de un servicio web a otro.

Dado que WSDL es XML, en la primera línea debe escribir sobre él directamente. El elemento raíz de un archivo siempre debe llamarse " definiciones»:


Por lo general, WSDL consta de 4-5 bloques principales. El primer bloque es la definición de un servicio web, o en otras palabras, un punto de entrada.


Aquí dice que tenemos un servicio llamado - " servicio de sms". En principio, usted puede cambiar todos los nombres en el archivo WSDL a lo que desee, porque no juegan absolutamente ningún papel.

Después de eso, declaramos que en nuestro servicio web " servicio de sms" hay un punto de entrada ("puerto"), que se llama " PuertoServicioSms". Es a este punto de entrada que se enviarán todas las solicitudes de los clientes al servidor. Y especificamos en el elemento " DIRECCIÓN» un enlace a un archivo de controlador que aceptará solicitudes.

Una vez que hayamos definido un servicio web y especificado un punto de entrada para él, debemos vincularle los procedimientos admitidos:


Para hacer esto, enumera qué operaciones y en qué forma se llamará y. Aquellos. para el puerto PuertoServicioSms» un enlace llamado « SmsServiceBinding", que tiene el tipo de llamada " rpc” y HTTP se utiliza como protocolo de transferencia (transporte). Por lo tanto, hemos indicado aquí que realizaremos una llamada RPC sobre HTTP. Después de eso, describimos qué procedimientos ( operación) son compatibles con el servicio web. Apoyaremos solo un procedimiento: " enviar SMS". ¡A través de este procedimiento, nuestros maravillosos mensajes serán enviados al servidor! Una vez declarado el procedimiento, es necesario indicar en qué forma se transmitirán los datos. En este caso, se especifica que se utilizarán sobres SOAP estándar.

Después de eso, necesitamos vincular el procedimiento a los mensajes:


Para ello, especificamos que nuestro enlace ("binding") es de tipo " SmsServicePortType"y en el elemento" Tipo de puerto» con el mismo nombre de tipo, especifique el enlace de los procedimientos a los mensajes. Y así, el mensaje entrante (del cliente al servidor) se llamará " enviarSmsRequest", y saliente (del servidor al cliente)" enviarSmsRespuesta". Como todos los nombres en el WSDL, los nombres de los mensajes entrantes y salientes son arbitrarios.

Ahora necesitamos describir los mensajes en sí, es decir entrantes y salientes:


Para ello, añadimos los elementos " mensaje» con nombres « enviarSmsRequest" Y " enviarSmsRespuesta" respectivamente. En ellos, indicamos que debe llegar un sobre a la entrada, cuya estructura corresponde al tipo de datos " Pedido". Después de eso, el servidor devuelve un sobre que contiene el tipo de datos: " Respuesta».

Ahora solo tenemos que hacer un poco: ¡agregar una descripción de estos tipos a nuestro archivo WSDL! ¿Y cómo cree que el WSDL describe los datos entrantes y salientes? ¡Creo que ha entendido todo durante mucho tiempo y se ha dicho a sí mismo que con la ayuda de esquemas XML! ¡Y tendrás toda la razón!


¡Puedes felicitarnos! ¡Nuestro primer WSDL ha sido escrito! Y estamos un paso más cerca de lograr nuestro objetivo.
A continuación, trataremos qué nos proporciona PHP para desarrollar nuestras propias aplicaciones distribuidas.

5 Nuestro primer servidor SOAP

Anteriormente, escribí que para crear un servidor SOAP en PHP, usaremos la clase integrada SoapServer. Para que todas las acciones posteriores ocurran de la misma manera que las mías, deberá modificar un poco su PHP. Para ser aún más preciso, debe asegurarse de tener instalada la extensión "php-soap". Cómo ponerlo en su servidor web se lee mejor en el sitio web oficial de PHP (ver referencias).

Después de que todo haya sido instalado y configurado, necesitaremos crear el archivo “ smsservice.php» con el siguiente contenido:

setClass("SoapSmsGateWay"); //Iniciar el servidor $servidor->handle();
Lo que está arriba de la línea con la función "ini_set", espero, no necesita ser explicado. Porque define qué encabezados HTTP enviaremos desde el servidor al cliente y configura el entorno. En la línea "ini_set", deshabilitamos el almacenamiento en caché del archivo WSDL para que nuestros cambios surtan efecto inmediatamente en el cliente.

¡Ahora llegamos al servidor! Como puede ver, ¡todo el servidor SOAP tiene solo tres líneas! En la primera línea, creamos una nueva instancia del objeto SoapServer y pasamos la dirección de la descripción de nuestro servicio web WSDL a su constructor. Ahora sabemos que estará ubicado en la raíz del hosting en un archivo con un nombre revelador " smsservice.wsdl.php". En la segunda línea, le decimos al servidor SOAP qué clase extraer para procesar el sobre recibido del cliente y devolver el sobre con la respuesta. Como habrás adivinado, es en esta clase donde se describirá nuestro único método. enviar SMS. ¡En la tercera línea iniciamos el servidor! ¡Todo, nuestro servidor está listo! ¡Con lo cual nos felicito a todos!

Ahora necesitamos crear un archivo WSDL. Para hacer esto, puede simplemente copiar su contenido de la sección anterior, o tomarse libertades y "plantearlo" un poco:

"; ?> /" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:http="http:// esquemas.xmlsoap.org/wsdl/http/" nombre="SmsWsdl" xmlns="http://esquemas.xmlsoap.org/wsdl/"> /"> /serviciosms.php" />
En esta etapa, el servidor resultante debería adaptarse completamente a nosotros, porque. podemos registrar los sobres que llegan y luego analizar con calma los datos entrantes. Para que podamos recibir cualquier cosa en el servidor, necesitamos un cliente. ¡Así que sigamos con ellos!

6 Cliente SOAP en camino

En primer lugar, debemos crear un archivo en el que escribiremos el cliente. Como de costumbre, lo crearemos en la raíz del host y lo llamaremos " cliente.php”, y dentro escribimos lo siguiente:

ListaMensajes = new ListaMensajes(); $req->mensajeLista->mensaje = nuevo Mensaje(); $req->mensajeList->mensaje->teléfono = "79871234567"; $req->messageList->message->text = "Mensaje de prueba 1"; $req->mensajeLista->mensaje->fecha = "2013-07-21T15:00:00.26"; $req->mensajeLista->mensaje->tipo = 15; $cliente = new SoapClient("http://($_SERVER["HTTP_HOST"])/smsservice.wsdl.php", array("soap_version" => SOAP_1_2)); var_dump($cliente->sendSms($req));
Describamos nuestros objetos. Cuando escribimos el WSDL, se describieron tres entidades para el sobre que ingresa al servidor: Pedido, Lista de mensajes Y mensaje. En consecuencia, las clases Pedido, Lista de mensajes Y mensaje son reflejos de estas entidades en nuestro script PHP.

Después de haber definido los objetos, necesitamos crear un objeto ( $requerido), que se enviará al servidor. ¡Luego vienen las dos líneas más queridas para nosotros! ¡Nuestro cliente SOAP! Lo crea o no, ¡pero esto es suficiente para que nuestro servidor comience a enviar mensajes del cliente, y también para que nuestro servidor los reciba y procese con éxito! En el primero de ellos, creamos una instancia de la clase SoapClient y le pasamos la dirección de ubicación del archivo WSDL a su constructor, e indicamos explícitamente en los parámetros que trabajaremos utilizando el protocolo SOAP versión 1.2. En la siguiente línea llamamos al método enviar SMS objeto $cliente e inmediatamente mostrar el resultado en el navegador.
¡Ejecutémoslo y veamos qué obtuvimos finalmente!

Recibí el siguiente objeto del servidor:

Objeto (stdClass) público "estado" => booleano verdadero
Y esto es maravilloso, porque. ¡ahora sabemos con certeza que nuestro servidor está funcionando y no solo funciona, sino que también puede devolver algunos valores al cliente!

¡Ahora veamos el registro que mantenemos prudentemente en el lado del servidor! En la primera parte, vemos los datos sin procesar que ingresaron al servidor:

79871234567 Mensaje de prueba 1 2013-07-21T15:00:00.26 15
Este es el sobre. ¡Ahora sabes cómo se ve! Pero es poco probable que estemos interesados ​​en admirarlo constantemente, así que deserialicemos el objeto del archivo de registro y veamos si todo está bien para nosotros:

Object(stdClass) public "messageList" => object(stdClass) public "message" => object(stdClass) public "phone" => string "79871234567" (longitud=11) public "texto" => string "Mensaje de prueba 1 " (longitud=37) public "fecha" => cadena "2013-07-21T15:00:00.26" (longitud=22) public "tipo" => cadena "15" (longitud=2)
Como puede ver, el objeto se deserializó correctamente, ¡con lo que me gustaría felicitarnos a todos! ¡A continuación, nos espera algo más interesante! Es decir, enviaremos por parte del cliente al servidor no un mensaje sms, sino un paquete completo (para ser más precisos, ¡tres completos)!

7 Envío de objetos complejos

Pensemos en cómo podemos enviar un montón de mensajes al servidor en un solo paquete. Probablemente el más de una manera sencilla¡habrá una organización de matriz dentro del elemento messageList! Vamos a hacerlo:

// crea un objeto para enviar al servidor $req = new Request(); $req->messageList = new MessageList(); $msg1 = nuevo Mensaje(); $msg1->teléfono = "79871234567"; $msg1->text = "Mensaje de prueba 1"; $mensaje1->fecha = "2013-07-21T15:00:00.26"; $mensaje1->tipo = 15; $msg2 = nuevo Mensaje(); $msg2->teléfono = "79871234567"; $msg2->text = "Mensaje de prueba 2"; $mensaje2->fecha = "2014-08-22T16:01:10"; $mensaje2->tipo = 16; $msg3 = nuevo Mensaje(); $msg3->teléfono = "79871234567"; $msg3->text = "Mensaje de prueba 3"; $mensaje3->fecha = "2014-08-22T16:01:10"; $mensaje3->tipo = 17; $req->mensajeLista->mensaje = $mensaje1; $req->mensajeLista->mensaje = $mensaje2; $req->mensajeLista->mensaje = $mensaje3;
Nuestros registros muestran que el siguiente paquete vino del cliente:

79871234567 Mensaje de prueba 1 2013-07-21T15:00:00.26 15 79871234567 Mensaje de prueba 2 2014-08-22T16:01:10 16 79871234567 Mensaje de prueba 3 2014-08-22T16:01:10 17
¿Qué tontería, dices? Y tendrá razón en cierto sentido, porque. así como aprendimos qué objeto salió del cliente, llegó a nuestro servidor en forma de sobre exactamente de la misma forma. Cierto, los mensajes sms no se serializaron en XML de la manera que necesitábamos: tenían que estar envueltos en elementos mensaje, no en estructura. Ahora veamos en qué forma dicho objeto llega al método. enviar SMS:

Object(stdClass) public "messageList" => object(stdClass) public "message" => object(stdClass) public "Struct" => matriz (tamaño=3) 0 => object(stdClass) public "phone" => string "79871234567" (longitud=11) public "texto" => cadena "Mensaje de prueba 1" (longitud=37) public "fecha" => cadena "2013-07-21T15:00:00.26" (longitud=22) public " type" => string "15" (longitud=2) 1 => object(stdClass) public "phone" => string "79871234567" (longitud=11) public "text" => string "Test message 2" (longitud= 37) public "date" => string "2014-08-22T16:01:10" (longitud=19) public "type" => string "16" (longitud=2) 2 => object(stdClass) public "phone " => cadena "79871234567" (longitud=11) public "texto" => cadena "Mensaje de prueba 3" (longitud=37) public "fecha" => cadena "2014-08-22T16:01:10" (longitud= 19) "tipo" público => cadena "17" (longitud = 2)
¿Qué nos da este conocimiento? Solo que la ruta que hemos elegido no es correcta y no hemos recibido una respuesta a la pregunta: "¿Cómo podemos obtener la estructura de datos correcta en el servidor?". Pero sugiero no desesperarse y tratar de convertir nuestra matriz al tipo un objeto:

$req->messageList->mensaje = (objeto)$req->messageList->message;
En este caso, recibiremos otro sobre:

79871234567 Mensaje de prueba 1 2013-07-21T15:00:00.26 15 79871234567 Mensaje de prueba 2 2014-08-22T16:01:10 16 79871234567 Mensaje de prueba 3 2014-08-22T16:01:10 17
Entró en el método enviar SMS el objeto tiene la siguiente estructura:

Object(stdClass) public "messageList" => object(stdClass) public "message" => object(stdClass) public "BOGUS" => matriz (tamaño=3) 0 => object(stdClass) public "phone" => string "79871234567" (longitud=11) public "texto" => cadena "Mensaje de prueba 1" (longitud=37) public "fecha" => cadena "2013-07-21T15:00:00.26" (longitud=22) public " type" => string "15" (longitud=2) 1 => object(stdClass) public "phone" => string "79871234567" (longitud=11) public "text" => string "Test message 2" (longitud= 37) public "date" => string "2014-08-22T16:01:10" (longitud=19) public "type" => string "16" (longitud=2) 2 => object(stdClass) public "phone " => cadena "79871234567" (longitud=11) public "texto" => cadena "Mensaje de prueba 3" (longitud=37) public "fecha" => cadena "2014-08-22T16:01:10" (longitud= 19) "tipo" público => cadena "17" (longitud = 2)
En cuanto a mí, entonces "a partir de un cambio en los lugares de los términos, la suma no cambia" (c). Qué FALSO, Qué estructura¡Aún no hemos alcanzado nuestro objetivo! Y para lograrlo, debemos asegurarnos de que en lugar de estos nombres incomprensibles, nuestro nativo mensaje. Pero cómo lograr esto, el autor aún no lo sabe. Por lo tanto, lo único que podemos hacer es deshacernos del contenedor extra. En otras palabras, ahora nos aseguraremos de que en lugar de mensaje convertirse FALSO! Para hacer esto, cambie el objeto de la siguiente manera:

// crea un objeto para enviar al servidor $req = new Request(); $msg1 = nuevo Mensaje(); $msg1->teléfono = "79871234567"; $msg1->text = "Mensaje de prueba 1"; $mensaje1->fecha = "2013-07-21T15:00:00.26"; $mensaje1->tipo = 15; $msg2 = nuevo Mensaje(); $msg2->teléfono = "79871234567"; $msg2->text = "Mensaje de prueba 2"; $mensaje2->fecha = "2014-08-22T16:01:10"; $mensaje2->tipo = 16; $msg3 = nuevo Mensaje(); $msg3->teléfono = "79871234567"; $msg3->text = "Mensaje de prueba 3"; $mensaje3->fecha = "2014-08-22T16:01:10"; $mensaje3->tipo = 17; $req->mensajeLista = $mensaje1; $req->mensajeLista = $mensaje2; $req->mensajeLista = $msg3; $req->listademensajes = (objeto)$req->listademensajes;
¿Qué pasa si tenemos suerte y surge el nombre correcto del esquema? Para ello, echemos un vistazo al sobre que llegó:

79871234567 Mensaje de prueba 1 2013-07-21T15:00:00.26 15 79871234567 Mensaje de prueba 2 2014-08-22T16:01:10 16 79871234567 Mensaje de prueba 3 2014-08-22T16:01:10 17
¡Sí, el milagro no ocurrió! FALSO- ¡No ganaremos! Llegó en enviar SMS el objeto en este caso se verá así:

Object(stdClass) public "messageList" => object(stdClass) public "BOGUS" => matriz (tamaño=3) 0 => object(stdClass) public "phone" => string "79871234567" (longitud=11) public " texto" => cadena "Mensaje de prueba 1" (longitud=37) public "fecha" => cadena "2013-07-21T15:00:00.26" (longitud=22) public "tipo" => cadena "15" (longitud =2) 1 => objeto(stdClass) public "phone" => cadena "79871234567" (longitud=11) public "texto" => cadena "Mensaje de prueba 2" (longitud=37) public "fecha" => cadena " 2014-08-22T16:01:10" (longitud=19) public "type" => string "16" (longitud=2) 2 => object(stdClass) public "phone" => string "79871234567" (longitud= 11) "texto" público => cadena "Mensaje de prueba 3" (longitud=37) "fecha" pública => cadena "2014-08-22T16:01:10" (longitud=19) "tipo" público => cadena " 17" (longitud=2)
Como dicen - "Casi"! Sobre esta nota (ligeramente triste), propongo redondear tranquilamente y sacar algunas conclusiones para nosotros mismos.

8 Conclusión

¡Finalmente llegamos aquí! Decidamos qué puedes hacer ahora:
  • puede escribir el archivo WSDL necesario para su servicio web;
  • puede escribir su propio cliente sin ningún problema que pueda comunicarse con el servidor utilizando el protocolo SOAP;
  • puedes escribir tu propio servidor comunicarse con el mundo exterior a través de SOAP;
  • puede enviar matrices del mismo tipo de objetos al servidor desde su cliente (con algunas restricciones).
Además, hicimos algunos descubrimientos por nosotros mismos durante nuestra pequeña investigación:
  • la clase nativa SoapClient no sabe serializar correctamente estructuras de datos del mismo tipo en XML;
  • al serializar una matriz en XML, crea un elemento adicional llamado estructura;
  • al serializar un objeto a XML, crea un elemento extra llamado FALSO;
  • FALSO menor mal que estructura debido al hecho de que el sobre es más compacto (no se agregan espacios de nombres adicionales en el encabezado XML del sobre);
  • desafortunadamente, la clase SoapServer no valida automáticamente los datos del sobre con nuestro esquema XML (quizás otros servidores tampoco).

Trataré de ser breve y en mis propias palabras. SOAP es ahora un protocolo API de servicio web muy popular. Es decir, la forma en que interactúas. sistema de informacion a través de la web con otros sistemas de información.

en el mismo vista general SOAP es un protocolo para intercambiar mensajes XML estructurados en un entorno informático distribuido arbitrario. De ello se deduce que debemos enviar XML a algún lugar y recibir XML también. Para la transmisión necesitamos transporte. O un protocolo de transferencia de datos. Por ejemplo, SMTP, FTP, HTTP, HTTPS. La mayoría de las veces HTTP, pero no es esencial.

La clave del éxito de nuestro intercambio es la capacidad de crear y transmitir correctamente una solicitud XML y recibir y analizar correctamente una respuesta XML. Para hacer todo bien, debe seguir (perdón por la tautología) las reglas. Estas reglas se describen en un archivo de formato especial: WSDL. WSDL es un lenguaje para describir las reglas para usar servicios web, incluido el servicio SOAP.

El objeto de la plataforma WS-link integrado en 1C nos permite descargar estas reglas y utilizar el servicio web con la máxima comodidad en función de ellas. El proveedor de servicios desarrolla reglas y las coloca en una dirección accesible para los clientes. Naturalmente, los cambios en el funcionamiento del servicio deberían, si es necesario, ir acompañados de cambios en la instrucción WSDL. Pero esta no es nuestra preocupación (la del cliente). Las reglas son importantes para nosotros. Puede que no tengamos la menor idea de cómo funciona el servicio, pero sabemos con certeza que si recurrimos a él de acuerdo con las reglas, obtendremos la respuesta correcta. Esto simplifica enormemente la vida y el desarrollo. No sé a ti, pero a mí me gusta.

Al llamar al método deseado con una función universal (previamente creando y pasando la estructura de parámetros que necesita) del servicio SOAP, ya puede ver el resultado en forma de árbol. La descripción de los datos de respuesta suele estar contenida en la documentación del proveedor, pero esto no es obligatorio. En cualquier caso, como respuesta, recibirá una determinada estructura de datos en forma archivo XML, que en general se puede convertir al tipo de datos 1C "Value Tree". Es este árbol el que tendrá con cualquier llamada a cualquier método. Llame al depurador en este momento para ver o mostrar el árbol de resultados en el formulario y descubra de qué ramas eliminar los preciados "frutos" -resultados. Y todo :)

Así de fácil es llamar y obtener los resultados de diferentes métodos en servicios completamente diferentes (en el segundo ejemplo, el método sin parámetros):

Pero como en la vida, los métodos SOAP también pueden denominarse procedimientos y funciones. Tuve la suerte de ver el procedimiento solo una vez. Y aun así, porque el servicio público con información de países, que usé como ejemplo No. 1, dejó de funcionar (todavía se muestra en la pantalla) y tuve que buscarle un reemplazo. ¿Qué hacer con el procedimiento, porque no nos devolverá una respuesta y no habrá nada a partir de lo cual crear un árbol y, por lo tanto, no hay dónde frustrar el resultado?

Pero (nuevamente, como sucede a menudo en la vida), todo se volvió aún más fácil con el procedimiento. Devuelve el resultado en sus propios parámetros. Como en la captura de pantalla a continuación:

Porque GetResultTreeForSOAP fue concebido como una función, luego lo obligué a devolver el resultado. En este caso, no un árbol, sino una estructura que contiene los parámetros de salida del método. Cuáles de los parámetros de salida siempre puede ver en sus propiedades. Aunque no puedas mirar. La estructura resultante contendrá todos los parámetros de salida del método. En nuestro ejemplo, estos son "imagen" y "codificación". Obtener el resultado de la estructura es aún más fácil. Si necesita "obtener" del árbol, entonces todo en la estructura está listo para usar.

En el último año, tuve la oportunidad de conectar mi configuración con proveedores de servicios e información a través de la API web tres veces para recibir datos o solicitar servicios (por ejemplo, servicios de entrega de mercancías o envío de SMS). última vez teniendo código terminado ejemplo y procesamiento para 1C del proveedor, los abandoné y elegí el servicio SOAP universal como opción de solución. Simplemente porque resultó ser más fácil con las funciones desarrolladas anteriormente.

Para esta publicación, encontré específicamente un par de recursos SOAP públicos y cegué la configuración usándolos. El 95% del tiempo se dedicó a trabajar con formularios de llamadas y salida de datos. Pero en la demostración puede ver el tipo de cambio del Banco Central de la Federación Rusa para cualquier fecha y un breve conjunto de información sobre cualquier país del mundo. Captura de pantalla de una página web para una URL arbitraria.

En general, quién es demasiado perezoso o no tiene tiempo para lidiar con todo esto, pero debe hacerlo rápidamente y para que funcione el enlace para descargar la configuración de demostración después de la publicación.

parte lírica.

Imagine que ha implementado o está implementando un determinado sistema que debería estar disponible desde el exterior. Aquellos. hay un determinado servidor con el que necesita comunicarse. Por ejemplo un servidor web.

Este servidor puede realizar muchas acciones, trabajar con la base de datos, realizar algunas solicitudes de terceros a otros servidores, hacer algunos cálculos, etc. vivir y posiblemente desarrollarse de acuerdo con su escenario conocido (es decir, de acuerdo con el escenario de los desarrolladores). No es interesante para una persona comunicarse con un servidor de este tipo, porque es posible que no pueda / no quiera ofrecer páginas hermosas con imágenes y otro contenido fácil de usar. Está escrito y funciona para funcionar y emitir datos a las solicitudes de la misma, sin importar que sean legibles por humanos, el cliente los tratará por sí mismo.

Otros sistemas, al acceder a este servidor, ya pueden disponer de los datos recibidos de este servidor a su propia discreción: procesar, acumular, enviar a sus clientes, etc.

Bueno, una de las opciones para comunicarse con dichos servidores es SOAP. Protocolo de mensajería SOAP XML.

Parte práctica.

Un servicio web (eso es lo que proporciona el servidor y lo que usan los clientes) hace posible comunicarse con el servidor en mensajes bien estructurados. El caso es que el servicio web no acepta ningún dato. Cualquier mensaje que no coincida con las reglas será devuelto por el servicio web con un error. El error será, por cierto, también en forma de xml con una estructura clara (lo que no se puede decir del texto del mensaje).

WSDL (lenguaje de descripción de servicios web). Las reglas por las que se componen los mensajes para el servicio web también se describen mediante xml y también tienen una estructura clara. Aquellos. si un servicio web proporciona la capacidad de llamar a un método, debe permitir a los clientes averiguar qué parámetros se utilizan para este método. Si el servicio web espera una cadena para el método Method1 como parámetro y la cadena debe llamarse Param1, estas reglas se especificarán en la descripción del servicio web.

No solo los tipos simples, sino también los objetos, las colecciones de objetos se pueden pasar como parámetros. La descripción del objeto se reduce a la descripción de cada componente del objeto. Si el objeto consta de varios campos, se describe cada campo, qué tipo tiene, el nombre (cuáles son los valores posibles). Los campos también pueden ser de tipo complejo, y así sucesivamente, hasta que la descripción de los tipos termina con los simples: cadena, booleano, número, fecha... Sin embargo, algunos tipos específicos pueden resultar simples, es importante que los clientes pueden entender qué valores pueden estar contenidos en ellos.

Para los clientes, basta con conocer la url del servicio web, wsdl siempre estará cerca, por lo que puede hacerse una idea de los métodos y sus parámetros que proporciona este servicio web.

¿Cuáles son las ventajas de todas estas campanas y silbatos?

  • En la mayoría de los sistemas, la descripción de métodos y tipos ocurre automáticamente. Aquellos. es suficiente que el programador en el servidor diga que este método se puede llamar a través de un servicio web y la descripción wsdl se generará automáticamente.
  • Cualquier cliente de jabón puede leer una descripción que tiene una estructura clara. Aquellos. sea ​​cual sea el servicio web, el cliente entenderá qué datos acepta el servicio web. De acuerdo con esta descripción, el cliente puede construir su propia estructura interna de clases de objetos, los llamados. vinculante" y. Como resultado, el programador que usa el servicio web tiene que escribir algo como (pseudocódigo):

    NewUser:=TSoapUser.Create("Vasya","Pupkin","admin"); jabón.AddUser(NuevoUsuario);

  • Validación automática.

    • validación xml. xml debe estar bien formado. xml inválido: inmediatamente un error para el cliente, déjelo que lo averigüe.
    • validación del esquema. xml debe tener una cierta estructura. xml no coincide con el esquema: inmediatamente un error para el cliente, déjelo que lo averigüe.
    • la validación de datos la lleva a cabo el servidor SOAP para que los tipos de datos y las restricciones coincidan con la descripción.
  • La autorización y la autenticación se pueden implementar mediante un método separado. de forma nativa o utilizando la autorización http.
  • Los servicios web pueden funcionar tanto sobre el protocolo SOAP como sobre http, es decir, a través de solicitudes de obtención. Es decir, si se utilizan datos simples (sin estructura) como parámetros, simplemente puede llamar al get habitual www.site.com/users.asmx/GetUser?Name=Vasia o publicar. Sin embargo, esto no es siempre y en todas partes.
  • ... ver wikipedia

También hay muchos contras:

  • Tamaño de mensaje irrazonablemente grande. Bueno, aquí la propia naturaleza de xml es tal que el formato es redundante, cuantas más etiquetas, más información inútil. Además, el jabón se suma a su redundancia. Para los sistemas de intranet, el problema del tráfico es menos grave que para Internet, por lo que jabón para redes locales más demandado, en particular, Sharepoint tiene un servicio web de jabón con el que puede comunicarse con éxito (y algunas limitaciones).
  • El cambio automático de la descripción del servicio web puede romper todos los clientes. Bueno, es como para cualquier sistema, por lo que si no se admite la compatibilidad con métodos anteriores, todo se caerá ...
  • No es un menos, sino una desventaja. Todas las acciones de llamadas a métodos deben ser atómicas. Por ejemplo, cuando trabajamos con un subd, podemos iniciar una transacción, ejecutar varias consultas y luego retroceder o confirmar. No hay transacciones en jabón. Una solicitud, una respuesta, la conversación ha terminado.
  • Tratar con la descripción de lo que está en el lado del servidor (¿estoy todo descrito correctamente por mí?), Lo que está en el cliente (¿qué se me escribió aquí?) Puede ser bastante difícil. Hubo varias ocasiones en las que tuve que lidiar con el lado del cliente y convencer al programador del servidor de que había descrito incorrectamente los datos, pero no podía entender nada en ellos, porque la generación automática y él, por así decirlo, no deberían, esto es una cuestión de software. Y el error estaba naturalmente en el código del método, el programador simplemente no lo vio.
  • La práctica muestra que los desarrolladores de servicios web están terriblemente lejos de las personas que utilizan estos servicios web. En respuesta a cualquier solicitud (válida desde el exterior), puede aparecer un error ininteligible "Error 5. Todo está mal". Todo depende de la conciencia de los desarrolladores :)
  • seguro que no me acordaba de nada...

Como ejemplo, hay un servicio web abierto de belavia:

  • http://86.57.245.235/TimeTable/Service.asmx - punto de entrada, también hay una descripción de texto de métodos para desarrolladores de terceros.
  • http://86.57.245.235/TimeTable/Service.asmx?WSDL: descripción wsdl de métodos y tipos de datos recibidos y devueltos.
  • http://86.57.245.235/TimeTable/Service.asmx?op=GetAirportsList: descripción de un método específico con un ejemplo del tipo de solicitud xml y respuesta xml.

Puede crear y enviar manualmente una solicitud como:

POST /TimeTable/Service.asmx HTTP/1.1 Host: 86.57.245.235 Tipo de contenido: texto/xml; charset=utf-8 Contenido-Longitud: longitud SOAPAction: "http://webservices.belavia.by/GetAirportsList" es

la respuesta sera:

HTTP/1.1 200 OK Fecha: lunes, 30 de septiembre de 2013 00:06:44 GMT Servidor: Microsoft-IIS/6.0 X-Powered-By: ASP.NET X-AspNet-Version: 4.0.30319 Cache-Control: privado, máx. -edad=0 Tipo de contenido: texto/xml; charset=utf-8 Contenido-Longitud: 2940

ZY Previamente, se abrió el servicio web de Aeroflot, pero después de que 1C agregó soporte para SOAP en 8ku, un grupo de evaluadores beta de 1C lo instalaron con éxito. Ahora algo ha cambiado allí (no sé la dirección, puedes buscar si estás interesado).
Descargo de responsabilidad. Habló a nivel doméstico. Puedes tomar.

¿Qué es SOAP?

SOAP significa Protocolo simple de acceso a objetos (Protocolo simple de acceso a objetos). Espero que después de leer el artículo solo quede perplejo: "¿Cuál es este extraño nombre?"

SOAP en su forma actual es un método de llamada a procedimiento remoto (RPC) a través de una red. (Sí, también se usa para pasar documentos como XML, pero lo omitiremos por ahora).

Averigüémoslo. Imagine que tiene un servicio que devuelve una cotización de acciones para un ticker determinado (símbolo de acciones). Envía datos al sitio de Nasdaq y genera el resultado deseado en función del HTML devuelto. Además, para permitir que otros desarrolladores lo utilicen dentro de sus aplicaciones, convierte este servicio en un componente que encuentra información sobre cotizaciones a través de Internet. Funciona muy bien hasta que un día Nasdaq cambia el diseño de sus páginas. Debe revisar toda la lógica del componente y enviar actualizaciones a todos los desarrolladores que lo utilizan. Y ellos, a su vez, necesitan enviar actualizaciones a todos sus usuarios. Si esto sucede de manera más o menos regular, puede crear muchos enemigos entre sus compañeros desarrolladores. Y con los programadores, como sabes, las bromas son malas. No querrás sacar una foto de tu gato favorito de la trituradora de la oficina mañana, ¿verdad?

¿Qué hacer? Veamos... todo lo que necesita es proporcionar una función que tome un ticker (de tipo cadena) como entrada y devuelva una cotización de bolsa (de tipo flotante o doble). Entonces, ¿no sería más fácil dejar que sus desarrolladores llamen a esta función de alguna manera a través de la web? ¡Excelente! También es una novedad para mí, hay COM y Corba, y Java, que han estado haciendo esto durante años... lo que es cierto es cierto, pero estos métodos no están exentos de fallas. La configuración remota de COM no es trivial. Además, debe abrir tantos puertos en el cortafuegos como administrador de sistema no tomes suficiente cerveza. Sí, y hay que olvidarse de los usuarios de todos sistemas operativos excepto Windows. Pero después de todo, los usuarios de Linux a veces también están interesados ​​en el intercambio.

Aunque parece que no todo está perdido para usuarios de linux si están usando DCOM, más aquí: http://www.idevresource.com/com/library/res/articles/comonlinux.asp.

No puedo decir mucho sobre Corba y Java, así que como ejercicio sugiero a los lectores que encuentren las desventajas de estos enfoques.

SOAP es un estándar que le permite describir una llamada remota de este tipo y la forma en que se devolverá el resultado. Por lo tanto, debe alojar su función en una aplicación que esté disponible en la red y recibir llamadas en forma de paquetes SOAP. Después de eso, valida la entrada, ejecuta su función y devuelve el resultado en un nuevo paquete SOAP. Todo el proceso puede ejecutarse a través de HTTP, por lo que no tiene que abrir un montón de puertos en el cortafuegos. ¿Es sencillo?

De qué se trata este artículo

Este es el primero de una serie de artículos sobre SOAP que estamos escribiendo en Agni Software. En este artículo intentaré darte una idea de qué es SOAP y cómo escribir una aplicación que se comunique con un servidor SOAP.

Jabón y XML

Si SOAP aún le parece simple, agreguemos XML. Ahora, en lugar de un nombre de función y parámetros, obtenemos un sobre XML bastante complejo, como si estuviera diseñado para confundirlo. Pero no te asustes. Hay más por venir, y necesita ver la imagen completa para apreciar la complejidad de SOAP.
Si no sabe qué es XML, primero lea mi artículo sobre XML aquí: http://www.agnisoft.com/white_papers/xml_delphi.asp.

Todos los paquetes SOAP están en formato XML. ¿Qué significa? Vamos a ver. Echa un vistazo a esta función (Pascal):
función GetStockQuote(Símbolo: cadena) : doble; Se ve muy bien, pero el problema es que es Pascal. ¿Cuál es el uso de esta definición simple para un desarrollador de Java? ¿O para alguien que trabaja con VB? Necesitamos algo que todos puedan entender, incluso los programadores de VB. Así que deles XML que contengan la misma información (parámetros, cotizaciones de acciones, etc.). Usted crea un paquete SOAP, que es esencialmente una llamada a su función, envuelto en XML para que cualquier aplicación en cualquier plataforma pueda entenderlo. Ahora veamos cómo se ve nuestra llamada SOAP:
xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/1999/XMLSchema">


IBM


Informativo, ¿verdad? SOAP se está simplificando ante nuestros ojos. Vale, bromas aparte. Ahora intentaré explicarte cómo entender esta llamada SOAP.

Descifrado de etiquetas

La primera etiqueta que te llama la atención es . Esta etiqueta es el envoltorio externo del paquete SOAP, que contiene algunas declaraciones de espacios de nombres que son de poco interés para nosotros, pero que son muy importantes para cualquier lenguaje de programación o analizador. Los espacios de nombres se definen de modo que el analizador acepte los prefijos posteriores, como "SOAP-ENV:" o "xsd:".

La siguiente etiqueta es . (Omitimos una etiqueta no representada aquí - . No está en este ejemplo en particular, pero si desea leer más al respecto, consulte la especificación SOAP aquí: http://www.w3.org/TR/SOAP/). Etiqueta en realidad contiene una llamada SOAP.

La siguiente etiqueta en la lista es − . El nombre de la etiqueta, GetStockQuote, es la función a llamar. De acuerdo con la terminología SOAP, esto se denomina operación. Por lo tanto, GetStockQuote es la operación a realizar. ns1 es el espacio de nombres que apunta a urn:xmethods-quotes en nuestro caso.

Una nota al margen sobre los espacios de nombres: un espacio de nombres le permite calificar una etiqueta XML. No puedes, por ejemplo, tener dos variables con el mismo nombre en un mismo procedimiento, pero si están en dos procedimientos diferentes, no hay problema. Por lo tanto, un procedimiento es un espacio de nombres, ya que todos los nombres que contiene son únicos. De manera similar, las etiquetas XML están dentro del ámbito de los espacios de nombres, por lo que dado un espacio de nombres y un nombre de etiqueta, uno puede identificarlo de manera única. Definiremos un espacio de nombres como URI para distinguir nuestro NS1 de los imitadores. En el ejemplo anterior, NS1 es un alias que apunta a urn:xmethods-quotes.

Tenga en cuenta también el atributo encodingStyle: este atributo especifica cómo se serializa la llamada SOAP.

Dentro de la etiqueta contiene parámetros. En nuestro caso más simple, solo tenemos un parámetro: la etiqueta . Observe esta línea al lado de la etiqueta:
xsi:tipo="xsd:cadena"
Así es más o menos cómo define XML los tipos. (Observe cuán inteligentemente usé la palabra "aproximadamente" al generalizar sobre la tecnología, que puede cambiar una vez que se publique el artículo). Qué significa exactamente esto: el tipo definido en el espacio de nombres xsi, que observa que está definido en la etiqueta – xsd:cadena. Y esto, a su vez, es una cadena definida en el espacio de nombres xsd, nuevamente definido anteriormente. (Estoy seguro de que los abogados estarían encantados con todo esto).

Dentro de la etiqueta Aparece "IBM". Este es el valor del parámetro de símbolo de la función GetStockQuote.

Bueno, al final, como gente decente, cerramos todas las etiquetas.

Entonces descubrimos el paquete SOAP que define la llamada al servidor SOAP. Y el servidor SOAP, utilizando analizadores XML, un botón rojo y la estación espacial MIR, decodifica esta llamada y determina que necesita una cotización de acciones. Inmediatamente encuentra la cotización requerida y se la devuelve en este formulario:
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>


34.5


Después de desenvolver el sobre SOAP, arrancar las cintas y agitar el envoltorio, nos enteramos de que el precio de una acción de IBM es 34,5.

La mayoría de los servidores comerciales devolverían mucha más información, como en qué moneda y a qué precio se compró la última acción. Y el precio de las acciones, quizás, sería más preciso.

De esta forma sabemos qué espera el servidor SOAP y qué devolverá. Entonces, ¿CÓMO envías esta información? Se puede utilizar cualquier transporte. El más iluminado es HTTP. No entraré en los detalles de HTTP, para aquellos que no saben, es lo que usa su navegador para comunicarse con los sitios que visita.

La solicitud HTTP deseada se vería así:
POST /Cotización de acciones HTTP/1.1
Anfitrión: www.stockquoteserver.com

Longitud del contenido: nnnn
SOAPAction: "Algunos-URI"

El paquete de solicitud de jabón aquí... La única otra cosa a tener en cuenta es el encabezado SOAPAction. Este encabezado indica el propósito de la solicitud y es obligatorio. Cada servidor SOAP puede tener un número ilimitado de funciones y puede usar el encabezado SOAPAction para determinar qué función se está llamando. Los cortafuegos y los multiplexores también pueden filtrar contenido según este encabezado.

Respuesta SOAP de servidores HTTP se verá así:
HTTP/1.1 200 Aceptar
Tipo de contenido: texto/xml; juego de caracteres="utf-8"
Longitud del contenido: nnnn

Paquete de respuesta Soap aquí... ¿Por qué HTTP? En primer lugar, administradores de red no tiene que abrir muchos puertos separados para las llamadas SOAP... el servidor web puede manejar las llamadas sin problemas, porque El puerto 80 suele estar abierto a todo el mundo para recibir solicitudes entrantes. Otra ventaja es la extensibilidad de los servidores web mediante CGI, ISAPI y otros módulos nativos. Esta extensibilidad le permite escribir un módulo que maneje solicitudes SOAP sin afectar otro contenido web.

Eso es todo

Espero que este artículo haya ayudado a arrojar algo de luz sobre SOAP. Si todavía está aquí y desea leer más sobre este tema, visite el sitio del autor: http://www.agnisoft.com/soap

Conexión