En el artículo:
Consumiendo WebServices desde Visual FoxPro (1)
ya hemos visto como realizar los 4 pasos que necesitamos para consumir WebServices usando SOAP y WSDL:
- Crear la solicitud de ejecución de una función del WebService. A esto se le llama XML REQUEST
- Enviar el XML REQUEST al Servidor (o sea que se le envía una URL que termina con las letras wsdl)
- Esperar hasta recibir la respuesta del Servidor. A lo recibido se le llama XML RESPONSE
- Procesar esa respuesta para extraer el dato (o los datos) que necesitamos
Ahora veremos las explicaciones de la clase que realiza esa tarea y de los programitas de ejemplos.
Propiedades usadas
cMensajeError = "" && El mensaje que corresponde al último error ocurrido
cRespuestaWS = "" && Si la solicitud fue exitosa entonces contendrá: el dato pedido. En caso contrario contendrá: ¡¡¡ERROR!!!
cURL_WebService = "" && La URL donde se encuentra el WebService solicitado
lHTTPS = .F. && ¿Quiere usar el protocolo HTTPS? Si es .F. entonces se usará el protocolo HTTP
lResultadoOK = .T. && ¿La última operación con HTTP o con HTTPS finalizó exitosamente?
nTimeOutConectar = 5 * 1000 && el tiempo está en milisegundos
nTimeOutEnviar = 15 * 1000 && el tiempo está en milisegundos
nTimeOutRecibir = 15 * 1000 && el tiempo está en milisegundos
nTimeOutResolver = 5 * 1000 && el tiempo está en milisegundos
es bastante auto-explicativo. En el caso de los TimeOut se refiere al tiempo máximo (en milisegundos) que esperará el Servidor antes de finalizar con un error. Si se pone 0 entonces esperará indefinidamente.
Método: BORRAR_ARCHIVO_TEMPORAL
Para consumir el WebService se crea un archivo con extensión .XML pero después de obtener la respuesta ese archivo ya no es necesario y por lo tanto lo puedes borrar si quieres.
Método: EJECUTAR_WS
Crea un objeto HTTP o HTTPS, se conecta al Servidor, y le envía la solicitud. Si tuvo éxito entonces crea un archivo temporal con extensión .XML (que luego podrás borrar si quieres). Si falló entonces en la propiedad cMensajeError coloca un texto describiendo el error ocurrido.
Método: ESTABLECER_TIMEOUTS
Establece los tiempos máximos (en milisegundos) que el Servidor esperará antes de terminar con error. Si no estableces esos tiempos máximos entonces el Servidor usará los que tiene predeterminados.
Método: FUNCION_SOLICITADA
Ejecuta la función tuya, propia, que creaste en el archivo WS_FUNCIONES.PRG. No es obligatorio hacerlo así, podrías si quisieras tener esa función dentro de esta clase pero en ese caso se te complicará la vida porque estarás muy desorganizado. Es conveniente tener a las funciones en un archivo .PRG separado, es más claro, más fácil de leer y de entender.
Al finalizar, devuelve lo solicitado (si todo estuvo ok) o la palabra ¡¡¡ERROR!!! (si ocurrió algún error).
Método: TO_STR
Como al Servidor se le debe enviar un string entonces si los parámetros recibidos no son de tipo string los convierte a string, y si son de tipo string entonces les coloca una comilla al inicio del string y otra comilla al final del string ¿por qué eso? porque si no se agregan las comillas el Visual FoxPro cree que son variables en lugar de ser constantes.
Veamos ahora el contenido del archivo WS_FUNCIONES.PRG
PROCEDURE WS_SALUDAR
LPARAMETERS toWS, tcNombre
LOCAL lcSolicitudXML, lcArchivoXML, lcRespuestaXML, lcRespuestaWS
* --- Paso 1. Se crea la solicitud
lcSolicitudXML = WS_SALUDAR_CREAR_SOLICITUD(tcNombre)
lcArchivoXML = "SALUDAR.XML"
* --- Paso 2. Se ejecuta el WebService
toWS.lResultadoOK = toWS.EJECUTAR_WS(lcSolicitudXML, lcArchivoXML) = 0
IF !toWS.lResultadoOK THEN
toWS.cRespuestaWS = "¡¡¡ERROR!!!"
RETURN
ENDIF
*--- Paso 3. Se convierte el archivo a string para poder manipular su contenido
lcRespuestaXML = FileToStr(lcArchivoXML)
*--- Paso 4. Se extraen del string todos los caracteres que no necesitamos para que solamente quede la respuesta
lcRespuestaWS = StrExtract(lcRespuestaXML, "<Message>", "</Message>")
toWS.cRespuestaWS = lcRespuestaWS
toWS.BORRAR_ARCHIVO_TEMPORAL(lcArchivoXML)
ENDPROC
Lo primero que se hace es guardar en la variable lcSolicitudXML el string que contiene la solicitud que se enviará al Servidor. Luego, se guarda en la variable lcArchivoXML el nombre de un archivo temporal con extensión .XML. Después se ejecuta la solicitud. Si tuvo éxito entonces el archivo temporal se convierte a string y se extrae de ese string el dato deseado y se lo guarda en la propiedad .cRespuestaWS para que esté disponible al programa llamador. Y finalmente, se borra el archivo temporal con extensión .XML (si quieres podrías no borrarlo para ver cual fue la respuesta completa del Servidor).
FUNCTION WS_SALUDAR_CREAR_SOLICITUD
LPARAMETERS tcNombre
LOCAL lcSolicitudXML
TEXT TO lcSolicitudXML TEXTMERGE PRETEXT 7 NOSHOW
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:hel="http://learnwebservices.com/services/hello">
<soapenv:Header/>
<soapenv:Body>
<hel:SayHello>
<hel:HelloRequest>
<hel:Name><<tcNombre>></hel:Name>
</hel:HelloRequest>
</hel:SayHello>
</soapenv:Body>
</soapenv:Envelope>
ENDTEXT
RETURN (lcSolicitudXML)
ENDFUNC
Esta función crea un string llamado lcSolicitudXML que contiene la solicitud que se debe enviar al Servidor. ¿Y cómo sabemos lo que debe estar en ese string? pues justamente para eso habíamos usado al programa SoapUI en el artículo anterior de esta serie. Si miras la Captura 2. y la Captura 3. de ese artículo entonces verás como obtener lo que necesitas. Solamente recuerda que debes reemplazar cada símbolo de ? por una variable delimitada con los caracteres << y >>
En este caso nuestra variable se llama tcNombre y por eso en el string se escribió <<tcNombre>>
Veamos ahora uno de los programas de ejemplo
LOCAL lcNombre, loWS, lcRespuesta
#DEFINE MSG_ICONO_ERROR 16
#DEFINE MSG_ICONO_INFORMACION 64
lcNombre = "Walter"
SET PROCEDURE TO WS_CLASS ADDITIVE
loWS = CreateObject("VFP_WebService")
WITH loWS
.cURL_WebService = "http://www.learnwebservices.com/services/hello?WSDL"
lcRespuesta = .FUNCION_SOLICITADA("WS_SALUDAR", lcNombre)
IF .lResultadoOK THEN
=MessageBox(lcRespuesta, MSG_ICONO_INFORMACION, "WebService ejecutado OK")
ELSE
=MessageBox(loWS.cMensajeError, MSG_ICONO_ERROR, "Ocurrió un problema...")
ENDIF
ENDWITH
loWS = .NULL.
RELEASE loWS
RETURN
*
*
Esto ya es muy sencillo de entender:
- Creamos una instancia de la clase VFP_WebService
- En la propiedad cURL_WebService colocamos la URL donde se encuentra el WebService
- Llamamos al método FUNCION_SOLICITADA() enviándole como parámetros el nombre de una función que se encuentra en el archivo WS_FUNCIONES.PRG y los parámetros que necesita esa función
- Si todo salió ok, mostramos la respuesta que recibimos del WebService
- Si ocurrió algún error, mostramos el mensaje correspondiente
Los programas de ejemplo
Para que todo sea más fácil de entender en el artículo anterior se colocó un enlace para descargar un archivo .ZIP que contiene varios pequeños .PRG con ejemplos de consumo de WebServices. Veamos esos ejemplos:
Conclusión
Con lo que aprendiste en este artículo y en el artículo anterior ya sabes todo lo que necesitas saber para consumir cualquier WebService desde Visual FoxPro usando los protocolos SOAP y WSDL. Todos esos WebServices ahora están a tu disposición.
En síntesis, lo que debes hacer es:
- Obtener la URL donde se encuentra el WebService
- Con el programa SoapUI obtener la solicitud que le debes enviar al Servidor
- En el programa WS_FUNCIONES.PRG escribir el PROCEDURE que ejecuta la solicitud y extrae la respuesta
- En el programa WS_FUNCIONES.PRG escribir la FUNCTION que te crea la solicitud en Visual FoxPro
- En otro programa o formulario crear un objeto de clase VFP_WebService, asignarle un valor a su propiedad cURL_WebService y ejecutar el método FUNCION_SOLICITADA() con los argumentos necesarios
- Y listo, ya está.
Artículos relacionados
¿Cómo se puede «levantar» o crear un WebService desde VFP 9 para que el mismo sea consumido desde otro equipo en la LAN? Algo así como un WebService que reciba un código de cliente y devuelva un XML con cierta data del cliente.