Tutor de XMLHttpRequest (webServices)

Este tutor es un ejemplo de conectar Velneo a Web services usando XMLHttpRequest. Todos los objetos de este tutor los encontrarás en la carpeta Tutores/Scripts/XMLHttpRequest (vWebServices).

Antes de pasar a explicar los tutores vamos a explicar una serie de conceptos básicos que debemos conocer sobre los webservices.

¿Qué es un web service?

Un web service es un conjunto de protocolos y estándares para intercambiar datos entre aplicaciones.

Aplicaciones desarrolladas en lenguajes de programación diferentes y que son ejecutadas sobre cualquier plataforma, pueden utilizar los servicios web para intercambiar datos entre ellas.

De forma más simple, podemos decir que un web service es una función que diferentes servicios o equipos utilizan, que solo se envían parámetros al servidor (lugar donde está alojado el web service) y que éste responderá a dicha petición.

Suelen utilizar para el intercambio de información los protocolos XML, SOAP, WSDL y UDDI.

XML es usado para describir los datos, SOAP se ocupa para la transferencia de los datos, WSDL se emplea para describir los servicios disponibles y UDDI se ocupa para conocer cuales son los servicios disponibles.

¿Cuales son sus ventajas?

Son independientes de las aplicaciones. No tienen interfaz GUI. Se comparte la lógica de datos y procesos.

Interoperabilidad entre aplicaciones de software independientemente de sus propiedades o de las plataformas sobre las que se instalen.

Al ser servicios Web, están basados en estándares y protocolos de texto. Esto hace más fácil acceder a su contenido y entender su funcionamiento.

Las especificaciones son gestionadas por una organización abierta (W3C) y se garantiza la interoperabilidad entre aplicaciones.

¿Qué es SOAP?

(Simple Object Access Protocol) es un protocolo escrito en XML para el intercambio de información entre aplicaciones. Es un formato para enviar mensajes, diseñado especialmente para servir de comunicación en Internet, pudiendo extender los HTTP headers. Es una forma de definir qué información se envía y cómo mediante XML. Es un protocolo para acceder a un Web Service. Ejemplo:

<SOAP-ENV:Envelope
 xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"   
 SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">    
    <SOAP-ENV:Body>
        <ns:getTemperatura xmlns:ns="http://j2ee.ua.es/ns">    
            <area>Alicante</area>
        </ns:getTemperatura>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

El mensaje SOAP está compuesto por un envelope (sobre), cuya estructura está formada por los siguientes elementos: header (cabecera) y body (cuerpo).

¿Qué es el WSDL?

(Web Services Description Language) es un lenguaje basado en XML para describir los servicios web y cómo acceder a ellos. Se ocupa de definir los Web Service como colecciones de punto de comunicación (end points) capaces de intercambiar mensajes.

La parte WSDL concreta describe el cómo y dónde del servicio:

  • Cómo tiene que llamar un cliente al servicio

    .

  • Qué protocolo debería usar

    .

  • Dónde está disponible el servicio

    .

En el mundo Java podemos pensar en la parte concreta de un WSDL como en la implementación de la parte abstracta, aunque en términos de servicios Web, solamente describe dónde se encuentra dicha implementación para utilizarse. La parte concreta de un WSDL contiene dos componentes principales:

  • Información de enlazado (binding) sobre el protocolo a utilizar.

  • La dirección en donde localizar el servicio.

Detalle de los elementos WSDL

Definitions

Es el elemento raíz y permite especificar el espacio de nombres del documento target namespace, el nombre, y otros prefijos utilizados en el documento WSDL. Un ejemplo de definición de prefijo es:

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

Este prefijo especifica que todos los elementos dentro del documento de esquemas con el target namespace"http://schemas.xmlsoap.org/wsdl/" tendrán el prefijo wsdl.

Types

Se utiliza para definir los tipos de datos que se intercambiarán en el mensaje. Podemos definir dichos tipos directamente dentro de este elemento, o importar la definición de un fichero de esquema (fichero xsd). La definición de tipos puede verse como las definiciones Java de clase, con variables que pueden ser tipos primitivos o referencias a otras clases u objetos. Los tipos primitivos se definen en los espacios de nombres del Schema y normalmente nos referimos a ellos como built-in types. Éstos incluyen tipos simples tales como string, int, double,...

Message

Define los distintos mensajes que se intercambiaran durante el proceso de invocación del servicio. Se deberán definir los mensajes de entrada y salida para cada operación que ofrezca el servicio. Los mensajes muestran descripciones abstractas de los datos que se van a intercambiar.

portType

Contiene una colección de una o más operaciones. Para cada operación indica cuáles son los mensajes de entrada y salida, utilizando para ello los mensajes definidos en el apartado anterior. Los _portTypes _son, por lo tanto, colecciones abstractas de operaciones soportadas por un servicio .

Binding

Indica el protocolo de red y el formato de los datos para las operaciones de un portType. Los bindings _son definiciones concretas de los _portTypes.

Un portType _puede tener múltiples _bindings asociados.

El formato de datos utilizado para los mensaje de las operaciones del portType puede ser orientado al documento u orientado a RPC. Si es orientado al documento tanto el mensaje de entrada como el de salida contendrán un documento XML. Si es orientado a RPC el mensaje de entrada contendrá el método invocado y sus parámetros, y el de salida el resultado de invocar dicho método, siguiendo una estructura más restrictiva.

Service

Define el servicio como una colección de elementos port a los que se puede acceder. Un port _se define asociando una dirección de red con un _binding, de los definidos en el documento. Dicha dirección de red es la dirección (URL) donde el servicio actúa, y por lo tanto, será la dirección a la que las aplicaciones deberán conectarse para acceder al servicio.

¿Qué es REST?

Los servicios Web RESTful (Representational State Transfer Web Services) son adecuados para escenarios de integración básicos ad-hoc. Dichos servicios Web se suelen integrar mejor con HTTP que los servicios basado en SOAP, ya que no requieren mensajes XML o definiciones del servicio en forma de fichero WSDL.

Los servicios Web REST utilizan estándares muy conocidos como HTTP, SML, URI, MIME, y tienen una infraestructura "ligera" que permite que los servicios se construyan utilizando herramientas de forma mínima. Gracias a ello, el desarrollo de servicios RESTful es barato y tiene muy pocas "barreras" para su adopción.

¿Cómo funciona un web service?

  1. El servicio a conectar es el que genera el WSDL describiendo el Web Service y registra el WSDL en el directorio UDDI o Service Registry.

  2. El servicio a conectar o la aplicación del cliente requiere un Web Service y se pone en contacto con el UDDI para localizar el Web Service.

  3. El cliente, basándose en la descripción descrita por el WSDL, envía un request _para un servicio particular al _Web Service Listener, que se encarga de recibir y enviar los mensajes en formato SOAP.

  4. El Web Service analiza el mensaje SOAP del request e invoca una operación particular en la aplicación para procesar el request. El resultado se escribe de nuevo en SOAP en forma de respuesta y se envía al cliente.

  5. El cliente analiza el mensaje de respuesta SOAP y lo interpreta o genera un error si ha habido alguno.

Ejemplos de web services

Servicios:

Herramientas para pruebas de webservices

En Velneo, utilizamos la herramienta SoapUI para realizar tests de conexión a los diferentes web services.

Podrás descargar aquí una versión gratuita.

Una vez conseguimos conectar y recibir datos, sabemos que la misma operativa y sintaxis nos funcionará en Velneo.

Ejemplo 1: acceder desde Velneo al web service del Catastro español

Primero queremos probar si somos capaces de conectar al web service y para ello, accedemos a la aplicación SoapUI.

Una vez dentro de la aplicación, empezaremos por generar un proyecto donde importaremos las especificaciones de los métodos y acciones a realizar en este proveedor y que están descritas en su WSDL cuyo link hemos comentado antes.

Para crear ese nuevo proyecto, pulsamos en el botón SOAP.

Esto abrirá un formulario donde debemos escribir la URL del WSDL del proveedor que en nuestro caso es:

https://ovc.catastro.meh.es/ovcservweb/ovcswlocalizacionrc/ovccallejero.asmx?WSDL

Una vez pulsemos el botón OK. SoapUI generará un nuevo proyecto especificando el nombre asignado por el proveedor (en el caso de que no lo hayamos asignado antes) y añadiendo todos los métodos posibles de comunicación, sus propiedades y resultados a devolver.

Ahora ya podemos empezar a probar con cualquiera de los métodos informados desde el WSDL del web service del proveedor de este ejemplo.

Vamos a ver por ejemplo el método ConsultaMunicipios para saber el código de un municipio de una provincia.

Al hacer doble clic en el método, SoapUI nos abre una ventana de comunicación donde nos informará del formato en XML a enviar y de los parámetros necesarios para que la respuesta sea válida.

Para ejecutar una petición SOAP tan sólo debemos pulsar en el botón del triángulo de color verde de la toolbar:

Una vez pulsado, nos introducirá en la parte izquierda de la aplicación el código XML a enviar y los parámetros necesarios a introducir. En nuestro ejemplo, nos pide pasarle como parámetro la provincia y el municipio para que el servicio nos devuelva el status.

Siguiendo las instrucciones de cada proveedor, pasaremos a añadir los parámetros necesarios. En nuestro ejemplo, la forma de pasarlos es esta:

<cat:Provincia>PONTEVEDRA</cat:Provincia>
<cat:Municipio>VIGO</cat:Municipio>

En la ventana derecha el web service del proveedor de este ejemplo nos devolverá el número de municipios, el código del municipio y el resto de valores establecidos por el web service, tal y como podemos ver en esta imagen:

Una vez hayamos comprobado que la respuesta es la esperada, ya podemos utilizar el modelo de datos XML para conectarlo desde nuestra aplicación desarrollada en Velneo.

Ahora tan sólo nos quedará aplicar el XML de la petición SOAP en nuestra aplicación Velneo utilizando para ello la clase XMLHttpRequest (en la documentación de Velneo existen ejemplos para el uso de esta clase).

Un posible ejemplo de proceso Javascript en Velneo sería este (catastro.js), donde le pasamos unos parámetros a través de las variables ACT, PRO, MUN y REF alimentadas desde un formulario.

// Enviar al web service
importClass("XMLHttpRequest");

// -----------------------------------------
// Función Log
// -----------------------------------------
var setLog = function(texto){
    theRoot.setVar("LOG", theRoot.varToString("LOG") + texto + "\n");
};

var url = theRoot.varToString("URL");

// -----------------------------------------
// build SOAP request editSubscriber
// -----------------------------------------
var sr = '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:cat="http://www.catastro.meh.es/">' +
'<soapenv:Header/>' +
   '<soapenv:Body>' +
    '<Provincia xmlns="http://www.catastro.meh.es/">' + theRoot.varToString("PRO") + '</Provincia>' +
    '<Municipio xmlns="http://www.catastro.meh.es/">' + theRoot.varToString("MUN") + '</Municipio>' +
    '<RefCat xmlns="http://www.catastro.meh.es/">' + theRoot.varToString("REF") + '</RefCat>' +
   '</soapenv:Body>' +
'</soapenv:Envelope>';

// -----------------------------------------------------------------
// Añadimos el método al Header ya que en algunos casos es necesario
// -----------------------------------------------------------------
var tipo_consulta = theRoot.varToString("ACT");


// -----------------------------------------
// Añadimos al log la URL y el SOAP
// -----------------------------------------
setLog("---------- URL ----------");
setLog(url);
setLog(sr);

// -----------------------------------------
// Ejecutamos la petición por el método POST
// -----------------------------------------
var xhr = new XMLHttpRequest();
xhr.open("POST", url, false);
xhr.setRequestHeader('Content-Type', 'text/xml');
xhr.setRequestHeader('SOAPAction' , '"http://tempuri.org/OVCServWeb/OVCCallejero/' + tipo_consulta + '"');
xhr.send(sr);

// -----------------------------------------
// Se procesa la response
// -----------------------------------------
while(xhr.readyState != 4) 
{
    xhr.processEvents();
}

if ((xhr.errorCode == 0) && (xhr.status == 200)) 
{
    theRoot.setVar("RET", xhr.response);
}


// -----------------------------------------
// Añadimos al log el resultado
// -----------------------------------------
setLog("---------- Código de error ----------");
setLog("errorCode: " + xhr.errorCode + "  status: " + xhr.status + "  readyState: " + xhr.readyState);
setLog("---------- Respuesta ----------");
setLog("response: " + xhr.response);

En el formulario del ejemplo ya vienen unos datos rellenados por defecto para que podamos probar. En este ejemplo lanzaremos la petición para el método visto antes denominado ConsultaMunicipios y utilizado para conocer los códigos de un municipio de una provincia en concreto.

El botón Enviar ejecutará el proceso antes mencionado y nos mostrará el resultado en el log habilitado en nuestra aplicación.

Después de esto, tan sólo nos quedará realizar las operaciones necesarias con el XML devuelto para usar los datos una vez parseado dicho XML.

Ejemplo 2: acceder desde Velneo al web service de E-goi (Herramienta para email marketing)

Para realizar este ejemplo es necesario estar dado de alta en el servicio y disponer de una clave API Key válida que será la utilizada en las operaciones que así lo requieran.

Primero queremos probar si somos capaces de conectar al web service y para ello, accedemos a la aplicación SoapUI.

Una vez dentro de la aplicación, empezaremos por generar un proyecto donde importaremos las especificaciones de los métodos y acciones a realizar en este proveedor y que están descritas en su WSDL cuyo link hemos comentado antes.

Para crear ese nuevo proyecto, pulsamos en el botón SOAP.

Esto abrirá un formulario donde debemos escribir la URL del WSDL del proveedor, que en nuestro caso es:

http://api.e-goi.com/v2/soap_any.php?wsdl

Una vez pulsemos el botón OK, SoapUI generará un nuevo proyecto especificando el nombre asignado por el proveedor (en el caso de que no lo hayamos asignado antes) y añadiendo todos los métodos posibles de comunicación, sus propiedades y resultados a devolver.

Ahora ya podemos empezar a probar con cualquiera de los métodos informados desde el WSDL del web service del proveedor de este ejemplo.

Vamos a ver por ejemplo el método checklogin para saber el estado de la cuenta.

Al hacer doble clic en el método, SoapUI nos abre una ventana de comunicación donde nos informará del formato en XML a enviar y de los parámetros necesarios para que la respuesta sea válida.

Para ejecutar una petición SOAP tan sólo debemos pulsar en el botón del triángulo de color verde de la toolbar.

Una vez pulsado, nos introducirá en la parte izquierda de la aplicación el código XML a enviar y los parámetros necesarios a introducir. En nuestro ejemplo, nos pide pasarle como parámetro la clave APIKey para que el servicio nos devuelva el status.

Siguiendo las instrucciones de cada proveedor, pasaremos a añadir los parámetros necesarios. En nuestro ejemplo, la forma de pasarlos es esta:

<functionOptions xsi:type="xsd:anyType">
         <apikey xsi:type="xsd:anyType">aquí_irá_la_clave_apikey</apikey>
</functionOptions>

En la ventana derecha el web service del proveedor de este ejemplo nos devolverá el status de la cuenta.

Una vez hayamos comprobado que la respuesta es la esperada, ya podemos utilizar el modelo de datos XML para conectarlo desde nuestra aplicación desarrollada en Velneo.

El último ejemplo a realizar será el de añadir un suscriptor a una lista de envío. El método a usar es addSubscriber.

Los pasos a realizar son los mismos, pero en este caso, el WSDL del web service a conectar nos pide además que los parámetros sean una lista de campos. Veamos cómo hacerlo:

<functionOptions xsi:type="xsd:anyType">
            <apikey xsi:type="xsd:anyType">aquí_irá_la_clave_apikey</apikey>
            <listID xsi:type="xsd:anyType">num_lista</listID>
            <email xsi:type="xsd:anyType">email_suscriptor</email>
            <first_name xsi:type="xsd:anyType">Nombre</first_name>
            <last_name xsi:type="xsd:anyType">Apellidos</last_name>
</functionOptions>

Si la petición es correcta, el web service del proveedor de este ejemplo nos mostrará la respuesta satisfactoria indicando los parámetros de respuesta informados en el WSDL.

Ahora tan sólo nos quedará aplicar el XML de la petición SOAP en nuestra aplicación Velneo utilizando para ello la clase XMLHttpRequest (en la documentación de Velneo existen ejemplos para el uso de esta clase).

Un posible ejemplo de proceso Javascript en Velneo sería este, donde le pasamos unos parámetros a través de las variables API_KEY, LIST_ID, EMAIL, FIRST_NAME y LAST_NAME alimentadas desde un formulario.

importClass("XMLHttpRequest");

// -----------------------------------------
// Función Log
// -----------------------------------------
var setLog = function(texto){
    theRoot.setVar("LOG", theRoot.varToString("LOG") + texto + "\n");
};

var url='http://api.e-goi.com/v2/soap_any.php';

// -----------------------------------------
// build SOAP request editSubscriber
// -----------------------------------------
var sr = '<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soap="http://api.e-goi.com/v2/soap_any.php">' +
   '<soapenv:Header/>' +
   '<soapenv:Body>' +
      '<soap:checklogin soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">' +
         '<functionOptions xsi:type="xsd:anyType">' +
                 '<apikey xsi:type="xsd:anyType">' + theRoot.varToString("API_KEY") + '</apikey>' +
         '</functionOptions>' +
      '</soap:checklogin>' +
   '</soapenv:Body>' +
'</soapenv:Envelope>';

// -----------------------------------------
// Añadimos al log la URL y el SOAP
// -----------------------------------------
setLog("---------- URL ----------");
setLog(url);
setLog(sr);

// -----------------------------------------
// Ejecutamos la petición por el método POST
// -----------------------------------------
var xhr = new XMLHttpRequest();
xhr.open("POST", url, false);
xhr.responseType = "text/xml"; // Para que la respuesta sea un objeto Javascript Json
xhr.setRequestHeader('Content-Type', 'text/xml');
xhr.send(sr);


// -----------------------------------------
// Añadimos al log el resultado
// -----------------------------------------
setLog("---------- Código de error ----------");
setLog("errorCode: " + xhr.errorCode + "  status: " + xhr.status + "  readyState: " + xhr.readyState);
setLog("---------- Respuesta ----------");
setLog("response: " + xhr.response);

En el formulario del ejemplo de este tutor se pueden rellenar los parámetros necesarios y mediante un botón (en este ejemplo) lanzaremos la petición para el método visto antes denominado _addSubscriber _y utilizado para dar altas de registros en la tabla de suscriptores.

El botón addSubscriber ejecutará el proceso antes mencionado y nos mostrará el resultado en el log habilitado en el formulario del tutor. Después de esto, tan sólo nos quedará realizar las operaciones necesarias con el XML devuelto para usar los datos una vez parseado dicho XML.

Ejemplo para parsear la respuesta (Response) de un web service

Nos basaremos en el primer ejemplo de conexión a un web service (el del Catastro español).

Si nos fijamos en su respuesta (response) ...

Vemos una serie de valores entre los distintos nodos del formato XML de respuesta y que habitualmente nos definen desde el propio web services.

En nuestro ejemplo, queremos leer las variables siguientes:

  • cd (código locat) (ejemplo: <cd>54</cd>)

    .

  • cmc (código de municipio locat) (ejemplo: <cmc>57</cmc>)

    .

  • cp (código postal ine) (ejemplo: <cp>36</cp>)

    .

  • cm (código de municipio ine) (ejemplo: <cm>57</cm>)

    .

Para ello, vamos a añadir al proceso CAT (catastro.js) descrito antes, el siguiente texto:

// -----------------------------------------
// Se procesa la response
// -----------------------------------------
while(xhr.readyState != 4) 
{
    xhr.processEvents();
}

if ((xhr.errorCode == 0) && (xhr.status == 200)) 
{
    theRoot.setVar("RET", xhr.response);
}

Este código procesa el resultado que nos devuelve _xhr.response _y lo inserta en la variable RET con la instrucción theRoot.setVar("RET", xhr.response);

La variable RET es la que podremos procesar a posteriori en el mismo evento del formulario Velneo donde hacemos la petición (Request).