domingo, 19 de mayo de 2013

Cgidev2

Hola de nuevo. Voy a dejar un momento el tema de ILE que estaba tratando en entradas previas y os voy a presentar Cgidev2. En cualquier caso, la misma estrategia que os estaba presentando para 5250 la utilizo para el desarrollo con Cgidev2 y me sirve para reutilizar todos los componentes que puedo :)

CGIDEV2 es una herramienta Open Source que permite comunicar con un navegador web desde un programa Rpg o Cobol. Por lo tanto permite "crear" páginas web desde estos lenguajes.
En si es un programa de servicio con un conjunto de componentes que encapsulan APIs del sistema operativo y que permiten procesar protocolo http. Con ellos, desde RPG, podemos "leer" un formulario rellenado en una página web y podremos crear un página web de respuesta.

Podrás acceder a la página principal de Cgidev2 y donde encontrarás todo tipo de  documentación a través de este enlace.


En esta entrada definiré un programa sencillo que permitirá obtener una lista de clientes de un fichero. Muestro una imagen de la salida en un navegador web.

Pruebalo aquí. Ahora prueba poniendo sustituyendo el 0 final en la url por un 1. 

Instalación


De la página de Cgidev2 es necesario descargarse la herramienta y las instrucciones de instalación. La instalación creará una biblioteca llamada Cgidev2 con los objetos y el programa de servicio y generará una instancia del servidor web Apache. El servidor web es el que servirá para comunicar entre el navegador web y los programas RPG. 

Que es necesario

En un proceso "normal" del iseries cuya salida es 5250, es necesario, para interactuar con el usuario, un fichero de pantalla Dspf y un programa Rpg. 
Para el entorno web utilizando esta herramienta, es necesario disponer de una plantilla Html y un programa Rpg que además utilice el programa de servicio Cgidev2

Html es un lenguaje de texto y basado en "marcas" y es son capaces de interpretar los navegadores web para presentar una pantalla. Es sencillo y podéis encontrar ayuda en muchas webs como por ejemplo 3schools.

Plantilla html

Es un archivo Html PERO donde se han incluido algunos tags que será interpretados por Cgidev2 en su ejecución. Por lo tanto NO es un html puro. Lo que contiene son definición de secciones (parecido a un formato de registro de un informe Rlu) y variables que se sustituirán en tiempo de ejecución por lo valores asociados. 
Anexo la plantilla html que ha generado la pantalla.





<as400>Cabecera</as400>     **** INICIO HTML 
Content-type: text/html 

 <HTML>
  <HEAD>
    <TITLE>Lista de clientes</TITLE>
  </HEAD>
  <BODY>
    <table align=center>
      <tr>
        <td colspan=2><h1>Lista de clientes</h1></td>
      </tr>
      <tr>
        <td>Cliente:</td>
<td>/%Sel_IdCliente%/</td>
      </tr>
    </table>
    <hr>

    <table align=center border=1>
      <tr>
        <td bgcolor=red align="center" width=100>Codigo</td>
<td bgcolor=red align="center" width=400 colspan=2>
            Nombre</td>
      </tr>
<as400>linea</as400>
      <tr>
<td align="right">/%Dsp_IdCliente%/</td>
<td>/%Dsp_Nombre%/</td>
        <td>/%Dsp_Apellidos%/</td>
      </tr>
<as400>Fin</as400>
      <tr>
<td align=center colspan=3>*** Fin ****</td>
      </tr>
     </table>
   </BODY>
  </HTML>


Destacaré lo específico que convierte el archivo html en la plantilla para poder ser utilizado por Cgidev2.
  • Secciones. He definido tres secciones (Cabecera , linea y Fin). Podríamos decir que es similar a formatos de registro en un Rlu. Se identifican por que están a la izquierda de la fila y están contenidos en dos tags que va a reconocer Cgidev2. En este caso son (<as400> y </as400>). El nombre del tag se define en el programa Rpg.
    Una sección ocupa desde la definición hasta que se encuentra otra sección o el final del archivo.
  • Variables. Se utilizarán para sustituir valores en tiempo de ejecución por el valor que se desee. Cgidev2 las identificará por que empiezan por (/%) y acaban por (%/). En este caso hay cuatro variables (Sel_IdCliente , Dsp_IdClienteDsp_Nombre y Dsp_Apellidos)
La plantilla residirá en el IFS en el As400 y de ahí la tomará el programa rpg para generar la salida para el navegador.

Rpg


Se muestra el programa rpg de ejemplo que presenta la lista de clientes.

D W_DatosClie     DS                  Dim(99) LikeDs(Ds_BasClie)
D W_NumReg        S              2  0
D W_TotReg        S             10  0
D W_Pag           S              6  0
D W_RegCarPag     S              3  0
D W_OrderBy       S              2
D W_Sel           DS                  LikeDs(Ds_SelClie)
D wIdx            S              4  0
D P_IdCliente     S             10

 /COPY *LIBL/QRPGLESRC,BAN01M1CP

 /copy usec
 /copy prototypeb

D SavedQryStr     S          32767    Varying

 /Free
   gethtmlIFSmult('/RAS0014402/html/CLILST.htm ' :
                    '<as400>' : '</as400>');

   If ZhbGetInput(SavedQryStr : Qusec) > 0;
     P_IdCliente= ZhbGetvar('IdCliente');
   Else;
     P_IdCliente= *Zeros;
   Endif;

   UpdHtmlVar('Sel_IdCliente' : P_IdCliente);
   wrtsection('Cabecera');

   W_Pag        = *Zeros;
   W_RegCarPag  = *Zeros;
   W_OrderBy    = '1A';
   Clear w_Sel;
   W_Sel.K_IdCliente = %Dec(P_IdCliente : 10 : 0);
   Obt_LstClientes(w_DatosClie : W_NumReg : W_TotReg :
                   W_Pag : W_RegCarPag : W_OrderBy :
                   w_Sel);
   For wIdx=1 To W_NumReg;
     UpdHtmlVar('Dsp_IdCliente' :  
                 %Char(w_DatosClie(widx).IdCliente));
     UpdHtmlVar('Dsp_Nombre'    : w_DatosClie(widx).Nombre);
     UpdHtmlVar('Dsp_Apellidos' : w_DatosClie(widx).Apellidos);
     wrtsection('linea');
   EndFor;

   wrtsection('Fin');

   wrtsection('*fini');
   Eval *InLr=*On;
 /End-Free

Primero están definidas un conjunto de variables de trabajo y un /copy (BAN01M1CP). Estas se utilizan para utilizar un componente de acceso a la base de datos que devolverá un array con una lista de clientes.

Después están dos /Copy necesarios para el procesamiento de cgidev2 (usec y prototypeb). Tienen la definición de componentes del programa de servicio Cgidev2 y la estructura de datos para acceso por Apis.

La variable (SavedQryStr) se utiliza en Cgidev2 para verificar la información que se envía desde el navegador web y de donde se pueden recuperar los "parametros de entrada"

Después comienza el código y lo primero es la definición de la plantilla a utilizar (o incluso podrían ser varias plantillas). Para ello se utilizar el componente de Cgidev2 (gethtmlIFSmult). Este define donde están las plantillas a utilizar del IFS. En este caso (/RAS0014402/html/CLILST.htm); la ruta será (/RAS0014402/html) y la plantilla se llama (CLILST.htm). Los dos siguientes parámetros de este componente son los "tags" de inicio y fin para identificar la secciones en la plantilla html, en este caso son (<as400> y </as400>). El uso de este componente se podría asemejar a la definición de la hoja F de un archivo de pantalla, es decir, es la definición de las plantillas html a utilizar.

Lo siguiente es "recibir los parámetros de entradas" enviados desde el navegador web. Para ello, Cgidev2 utiliza (ZhbGetInput(SavedQryStr : Qusec)) para saber si se ha enviado algún parámetro. En caso de que sea mayor de cero, se habrá enviado parámetros.

Una vez determinados que tiene parámetros de entrada, se tienen que recibir, para ello  en Cgidev2 tenemos el componente (ZhbGetvar). En este componente, le tenemos que decir el  nombre del parametro que queremos recibir y en este caso el código de cliente ('IdCliente'). Es necesario mencionar que desde el navegador web se envían los parámetros con un nombre y con ese mismo nombre se tienen que recibir en el programa Rpg.  Y otro comentario, es que siempre son de tipo alfanumérico.

Después carga una variable de la plantilla y para ello se utiliza el componente del cgidev2 (UpdHtmlVar). Tiene dos parámetros, el nombre de la variable que esta en la plantilla del Html y el valor que se le quiere pasar ('Sel_IdCliente' : P_IdCliente). En este caso se pasa a la variable (Sel_IdCliente) el valor que se ha "pasado" como parámetro (P_IdCliente). Este componente se puede asemejar a un EVAL en RPG.

A continuación, con el componente (wrtsection) "escribe" la sección de la plantilla html. En este caso escribe eñ "formato de registro" de nombre ('Cabecera'). Se puede asemejar en el RPG a WRITE.

Después lee el fichero a través de un componente de acceso a base de datos (Obt_LstClientes) (no tiene nada que ver con Cgidev2) y obtendrá un array (w_DatosClie ) con la  lista de clientes a "pintar". A continuación se realiza un bucle por el numero de registros devueltos en el array y por cada registro: carga las tres variables (Dsp_IdClienteDsp_Nombre y Dsp_Apellidos) de la plantilla y escribe la sección (linea). Hará que escriba n líneas en el html de salida.

Al finalizar con los registros de la tabla, escribe la sección (Fin) que en la plantilla ponía el final de la página.

Hay que indicar que todo lo que se iba generando a través de la escritura de las secciones se la plantilla, se iba almacenando en memoria.

Por ultimo (y obligatorio) tiene que haber la escritura de la sección (*fini), Esta es una sección especial propia de cgidev2 (y que no está en la plantilla). Lo que hace esta sección es enviar TODO lo almacenado en memoria como respuesta al navegador web para que el navegador pinte lo generado. (Nota: es italiano por que una de las personas que creó Cgidev2 es italiano, Giovanni B. Perotti)

Parece sencillo ¿eh?. Pues es cierto, es sencillo; Giovanni ha hecho un trabajo excepcional encapsulando complicadas API de comunicación con protocolo http en componentes muy fáciles de usar.
PERO aunque es fácil lo único es que hay tener algunos conceptos claros de como funciona el entorno web que puede ser algo diferente al procesamiento de una pantalla 5250.

Resumen de componentes

Con unos pocos componentes y sencillos somos capaces de comunicarnos y generar una página web.

  • gethtmlIFSmult. Para definir un plantilla html a utilizar.
  • ZhbGetvar. Para recuperar parámetros de entrada.
  • UpdHtmlVar. Para cargar una variable de la plantilla.
  • wrtsection. Para recuperar escribir un "formato de registro" de la plantilla.
Cgidev2 tiene muchos más componentes y puedes consultarlos en la página web de cgidev2 pero con estos cuatro se puede hacer prácticamente todo.

A tener en cuenta

  • Como se ha comprobado, generar una página web con Cgidev2 es un procesamiento similar a generar un informe RLU en el as400. En el ejemplo, se ha escrito una cabecera, después n lineas y por último un final.
  • Los programas 5250 se mantienen en linea cuando en una pantalla se está esperando que el usuario rellene algo en una pantalla. En estos programas web cuando se "pinta" la ventana en el navegador web, el programa ya ha finalizado (por lo tanto NO existe una pila de programas ni existe aplicación; hay que simular esa sensación de aplicación)
  • Los programas se ejecutan en un subsistema especial asociado al servidor http Apache.
  • Es un procesamiento cliente-servidor. El cliente (navegador) pide (PETICION) algo al servidor (Apache). El servidor solicita la ejecución del programa RPG y este generará (RESPUESTA) una página html resultante y el servidor web (Apache) se la enviará al cliente. A partir de ahi, NO existe una relación mantenida NI en linea entre el cliente y el servidor.
  • Aparecen diferentes y nuevos lenguajes. Del lado del cliente (navegador web), esta HTML pero se puede complementar con JAVASCRIPT para desarrollar pequeñas funciones y hojas de estilo CSS que permiten definir el aspecto visual de la página web.  Puedes aprender algo más de estos "lenguajes" en este enlace.
    Del lado del servidor tendremos nuestro RPG con el uso del programa de servicio Cgidev2.
Si tienes alguna duda, me lo puedes preguntar e intentaré ayudarte. Yo he hecho programas muy "chulos" combinándolo con la estrategia de desarrollo con ILE que utilizo yo   ;)









4 comentarios:

  1. Se debe configurar algo en el Iseries?

    ResponderEliminar
  2. Excelente explicación , hoy 27/08/2018, tuve una reunión y me indicaron si quería desarrollar bajo esta nueva herramienta, y al ver este ejemplo que uds coloca y explica de una forma muy claray sencilla puedo decir que aceptare la propuesta, agradecido de que publiquen los conocimientos.. Saludos.

    ResponderEliminar
  3. Hola.
    Esto solo funciona en una Apache o también podemos utilizar HTTP-SERVER en el i5 ???

    ResponderEliminar
    Respuestas
    1. Hola
      No soy experto en la parte de servidores pero que yo sepa el HTTP-SERVER esta basado en Apache. Creo recordar que en versiones muy antiguas eran diferentes pero ahora están integrados. Échale una pruebecilla para ver si existe algún problema.

      Eliminar