En muchas de las ocasiones es necesario integrar aplicaciones creadas con Genexus y el generador RPG mediante la utilizaciòn de los servicios web Rest.
Porque utilizar servicios web REST, justamente poque resulta mas facil realizar el parseo de datos enviados y recibidos, con SOAP, se tiene mas complicaciones en el sentido de armar bien el XML.
Realmente la independencia que se tiene con REST resulta sencillo consumirlos de una forma rapida sin muchos dolores de cabeza, ya que el trabajar con RPGLE es bastante engorroso por su sintaxis y sobre todo su editor.
Tambien se tuvo problemas con el manejo de apuntadores, en algunos casos no fue posible generan ciertos errores al compilar y sobre todo al ejecutar, la información que supuestamente deberia disponer no estaba tan visible con este concepto.
De hecho que pudo revisar algunas librerias y ejemplos que ayudan a tener una vision muy clara del tema, pero lo mas gravitante del problema es conocer RPGLE, para ello recomiendo el siguiente libro: Guia del Programador RPGLE en español
Es importante resaltar que es necesario revisar las siguientes librerias, que permiten conectar el ISERIES con servicios web externos, un excelente trabajo de Robert Cozzi y algunos otros amantes del ISERIES:
- Libreria ISOCKETS
- Libreria ISOCKETS para conectar desde y hacia ISERIES
- Informacion sobre ISOCKETS
- Programaciòn de SOCKETS con el ISERIES
- Ejemplo de RPGLE y JSON
- PARSING RPGLE y JSON Ejemplos
- EBOOK - PDF con algunas referencias de como utilizar JSON y RPGLE
- Mas herramientas OPENSOURCE para IBM
- Libreria JSON para ser utilizada con RPGLE
- Otra libreria de JSON para RPGLE
- Una breve explicación de la utilizacion de JSON con RPGLE
- Informacion de las funciones disponibles en ISOCKETS
Un sitio con abundante información sobre RPGLE, SOAP y JSON .
Como instalar en el ISERIES - Instrucciones:
Descargar la Libreria: Libreria ISOCKETS
En la PC desempaquetar el ZIP en una carpeta, luego realice lo siguiente:
FTP iseriestest usuario password
FTP QGPL/iSockets
BINARY
QUOTE SITE NAMEFMT 1
CD /QSYS.LIB/QGPL.LIB
LCD "C:\[carpeta donde esta el archivo iSockets.savf]
QUOTE RCMD CRTSAVF QGPL/ISOCKETS
PUT iSOCKETS.SAVF
QUIT
En el ISERIES, restauramos la libreria con el siguiente comando:
RSTLIB SAVLIB(ISOCKETS) DEV(*SAVF) SAVF(QGPL/ISOCKETS)
Como utilizar ISOCKETS desde RPG IV?
En este link existen algunas instrucciones con ejemplos para utilizar de mejor manera la libreria iSockets ===> , Ejemplos.
Para el Caso tambien hemos creado un servicio web REST EMISOR con un Data Provider de tal forma que pueda ser leido con el Metodo GET, si deseamos utilizar el metodo POST debemos utilizar un Procedimiento, en virtud de ello para mayor facilidad ya que solo se trata de recuperar informaciòn que es nuestro caso utilizaremos un DataProvider.
En nuestro caso hemos trabajado con JDK1.6 y Tomcat7.
En las Reglas del DataProvider:
// Parametros
Parm(In:&Numerocliente);
Tener presente que el nombre del parametro es CASE SENSITIVE.
En el SOURCE:
SDTConsultaClientes
Where ClienteCodigo = &Cliente
{
Cliente = ClienteCodigo
Nombres = ClienteNombres
Estado = ClienteEstado
codigoError = '0000'
mensajeError = 'PROCESO OK'
}
En las propiedades:
Expose as Web Service = True
WebServices Protocol = REST Protocol
El ejemplo que a continuacion se detalla fue adoptado en base al codigo publicado en la siguiente URL: Ejemplo con RPGLE e ISOCKETS - GetUrlData
Se tuvo algunos problemas al utilizar la librerias YAJL, dicha libreria que permiten leer y escribir JSON, en nuestro caso especifico se requeria solo leer un JSON, de tal forma que se opte por acoplar un algoritmo que permita cumplir con ese objetivo, aquello facilito el consumo del servicio web desde el ISERIES, con estos antecendentes se procedio a crear el mismo, tomando como ejemplo de la libreria ISOCKETS el siguiente programa RPGLE:
H OPTION(*NODEBUGIO:*SRCSTMT) BNDDIR('ISOCKETS':'QC2LE')
/IF DEFINED(*CRTBNDRPG)
H DFTACTGRP(*NO)
/ELSE
H NOMAIN
/ENDIF
/COPY iSockets/QCPYSRC,iSockets
/COPY iSockets/QCPYSRC,cprotos
/IF NOT DEFINED(*CRTBNDRPG)
D GetURLData PR 10I 0
D URL 128A Const
D rtnHTML 65535A OPTIONS(*VARSIZE)
D nRtnLen 10I 0 Const
P GetURLData B Export
D GetURLData PI 10I 0
D URL 128A Const
D rtnHTML 65535A OPTIONS(*VARSIZE)
D nRtnLen 10I 0 Const
/ELSE
D URL S 128A
/ENDIF
D SALIDA S 2000A
D LARGO S 10A
D cRet S 100A dim(30) D szURL S 128A Varying
D hURL S 10I 0
D nBytes S 10I 0
D szHtml S 65535A
D pHtml S * Inz(%addr(szHtml))
D nLen S 10I 0
D nPage S 10I 0
D nPageB S 10I 0
D nPageF S 10I 0
D szDomain S Like(szURL)
D szPage S Like(szURL)
D szParms S Like(szURL)
D cJson S 2000A
D nPos S 10I00
D nPosIni S 10I00
D nPosFin S 10I00
D cReturn S 2000A
D nLarJson S 10I00
D nLargo S 10I00
D nUbiIni S 10I00
D nUbiFin S 10I00
D nLarCpo S 10I00
D cCampo S 100A
D cValor S 100A
D nError S 010I00
D nNro S 010I00
D cLinea S 050A
D cBuscar S 020A
D cCliente S 010A
/IF DEFINED(*CRTBNDRPG)
C *ENTRY PLIST
C PARM cCliente // Parametro de Entrada Cliente
C PARM cRet // Retorna dato en unarreglo
/free
URL = 'http://localhost:8080/swrest/rest'
+ '/consultaccliente?Clientecodigo='
+ %trim(ccliente);
/end-free
/ENDIF
C* callp Joblog('URL-->%s':URL)
C* Permite desplegar en JOBLOG de la SESION el contenido de la Variable
C callp iSocketsOptions('DBG':*ON)
C if %Parms >= 1
C eval szUrl = %trimR(URL)
C endif
C if szURL = ''
C return
C endif
** Find the end of the URL
C eval nLen = %scan(' ':szURL)
C if nLen > 0 and nLen < %len(szURL)
C eval %len(szURL) = nLen
C endif
C if stricmp(%subst(szURL:1:5):'http:')=0 or
C stricmp(%subst(szURL:1:6):'https:')=0
C eval nPageF = %scan('//':szURL)
C if nPageF > 0
C eval szUrl = %subst(szURL:nPageF+2)
C endif
C endif
C eval nPageF = %scan('\':szURL)
C eval nPageB = %scan('/':szURL)
C if nPageB = 0 and nPageF = 0
C eval nPage = 0
C else
C if nPageB > nPageF
C eval nPage = nPageB
C else
C eval nPage = nPageF
C endif
C endif
C if nPage > 0
C eval szDomain = %subst(szURL:1:nPage-1)
C eval szPage = %Subst(szURL:nPage)
C else
C eval szDomain = %trimR(szURL)
C endif
C eval nBytes=GetUrldata(szDomain:
C szPage : *OMIT:
C pHtml:%size(szHtml):
C 0 : 367)
C* Recuperar los datos que retorna el SW REST y la Longitud de los datos.
C MOVEL SZHTML cReturn
C MOVEL NBYTES LARGO
/free
exsr leer_json;
/end-free
C
c return
/IF NOT DEFINED(*CRTBNDRPG)
C if nBytes <= nRtnLen
C eval szRtnHtml = %subst(szHtml:nBytes)
C else
C eval szRtnHtml = %subst(szHtml:nRtnLen)
C endif
C callp Joblog('Salida larga %s':szrtnhtml)
/free
dsply szRTNhtml;
/end-free
C callp Joblog('Salida CORTA %s':szrtnhtml)
C return nBytes
/else
C return
/endif
/free
// Rutina propia para recuperar datos de JSON exclusivo para datos
// alfanumericos
begsr leer_json;
for nNro = 1 to 30;
cRet(nNro) = ''; // Encerar variable
endfor;
nPosIni = %scan('200 OK' : cReturn); // Revisar si existe respuesta
if nPosIni <= 0;
nLarJson = 0;
else;
nLarJson = 1;
Endif;
if nLarJson = 0;
cRet(01) = '500';
cRet(02) = 'SERVICIO WEB NO DISPONIBLE';
else;
nPosIni = %scan('{' : cReturn);
nLargo = %size(cReturn);
nLarJson = nLargo - nPosIni;
cJson = %subst(cReturn : nPosIni : nLarJson);
cBuscar = 'codigoError';
exsr Busca_error;
exsr Busca_Json ;
if %trim(cValor) = '0000';
cRet(01) = %trim(cValor);
cRet(02) = 'SERVICIO WEB EN LINEA';
else;
cRet(01) = %trim(cValor);
cBuscar = 'mensajeError';
exsr Busca_error;
exsr Busca_Json ;
cRet(02) = cValor;
nLarJson = 0;
endIf;
endIf;
if nLarJson > 0;
nPosIni = 1;
nNro = 3;
dow nlarjson > 0;
exsr Busca_Json;
if nError > 0;
leave;
endif;
cRet(nnro) = cValor;
exsr Busca_Json;
if nError > 0;
leave;
endif;
nNro = nNro + 1;
cRet(nNro) = cValor;
nNro = nNro + 1;
enddo;
Endif;
endsr;
// Subrutina para Buscar en la cadena JSON si existe error en la
// Recuperacion de datos
begsr Busca_Error;
nError = 0;
nPosIni = 1;
nUbiIni = %scan(%trim(cBuscar) : cJson : nPosIni);
if nUbiIni = 0;
nError = 1;
else;
nPosIni = nUbiIni + 1 + %len(%trim(cBuscar));
endif;
endsr;
// Subrutina para Buscar en la cadena JSON los datos de etiqueta y valor,
// funciona bien solo en el caso de DATOS ALFANUMERICOS, cuya forma
// simple es {"NombreCliente":"JOSE CANDELARIOS TRES PATINES",
// "ClienteCodigo":"95959595"}
begsr Busca_json;
nError = 0;
nUbiIni = %scan('"' : cJson : nPosIni);
if nUbiIni = 0;
nError = 1;
else;
nPosFin = nUbiIni + 1;
nUbiFin = %scan('"' : cJson : nPosFin);
if nUbiFin = 0;
nError = 2;
else;
nPosIni = nUbiFin + 1;
nUbiIni = nUbiIni + 1;
nUbiFin = nUbiFin;
nLarCpo = nUbiFin - nUbiIni;
if nLarCpo > 0;
cValor = %subst(cJson : nUbiIni : nLarCpo);
else;
cValor = '';
endif;
endif;
endif;
endsr;
/end-free
En el ISERIES se puede crear un RPG o CL que invoque a dicho programa de la siguiente forma:
CALL CONSUMESW('09292', '')
y Retornara un Arreglo de la siguiente forma:
Pos-1 0000
Pos-2 SERVICIO WEB DISPONIBLE
Pos-3 Cliente
Pos-4 09292
Pos-5 Nombres
Pos-6 JOSE CANDELARIO TRES PATINES
Pos-7 codigoError
Pos-8 '0000'
Pos-9 mensajeError
Pos-10 'PROCEOS OK'
De esta forma el acceso resulta facil, ya que en RPG realmente es complicado el manejo de cadenas, un poco a mejorado con el RPGLE, pero su editor SEU realmente es muy pobre para este tipo de tareas.
Existe algunas nuevas funciones para ello sugiero siguiente LINK:
Nuevas funciones de RPGLE
Cualquier comentario adicional por favor dejeme hagame conocer y estaremos en contacto, quiero agradecer a todos ellos que me respondieron a la consulta el HELP400.
CONCLUSIONES: Para aspectos de explotación de la información lo mejor es accesar a ella con cualquier otro lenguaje como Java, CSharp o Python entre los mas utilizados, pero para interconectar el servidor ISERIES y su potente sistema operativo, personalmente creo que vale la pena optar por la idea de consumir servicios web REST o SOAP, con RPGLE, exponer servicios web con RPGLE, de muchas formas no le veo muy eficiente porque es un esfuerzo grande para poder obtener resultados aceptables, creo que los lenguajes de 3ra generacion tienen una series de librerias y funciones que superan en gran medida la funcionalidad del RPGLE, recuerden es una vision muy personal.
No hay comentarios:
Publicar un comentario