lunes, 20 de mayo de 2013

Modulo. Lista de seleccion (F4)

Continuando con la serie de entradas relacionadas con el tema de la estrategia de desarrollo en ILE presento una plantilla de programa de selección de un registro.

Objetivo


Realizar un programa que presenta una ventana de selección (típica consulta de F4 en formato window) donde se podrá un registro para devolver al programa que le ha llamado.
En este ejemplo, se realizará una ventana de selección de países.

Referencias: ILE estrategiaBD Pruebas


Configuración 

Este programa utilizará un componente de acceso a base de datos de lista de países similar al que se definió en la entrada de acceso a BD a través del uso del programa de servicio que lo contiene .
  • El nombre del módulo donde esta el ventana de lista de selección BAN40P1
    • La definición de la pantalla estará definida como BAN40S1
  • Utiliza el programa de servicio BAN01SRV que contiene los componentes de acceso a BD.
    • El miembro (/Copy) con la definición del prototipo con los componentes y con la definición de estructuras será BAN01M1CP
Este ejemplo sirve de plantilla para otro proceso similar.


Fuente de la pantalla. BAN40S1

Se define la pantalla para presentar la lista de registro y para seleccionar un registro.



A                                      DSPSIZ(24 80 *DS3)
A                                      PRINT
A          R BAN40S01                  SFL
A                                      SFLNXTCHG
A            S_OPCION       1A  B  8  4VALUES(' ' '1')
A            S_DSPAIS      35A  O  8 12
A            S_IDPAIS       3A  O  8  8
A          R BAN40C01                  SFLCTL(BAN40S01)
A                                      CF03(03 'Salir')
A                                      RTNCSRLOC(*RECNAME &REGCUR &CAMCUR)
A                                      OVERLAY
A                                      SFLCSRRRN(&CURS01)
A  40N41                               SFLDSP
A N41                                  SFLDSPCTL
A  41                                  SFLCLR
A  40N41                               SFLEND(*MORE)
A                                      SFLSIZ(0010)
A                                      SFLPAG(0009)
A  61                                  SFLMSG('Solo se puede seleccionar u-
A                                      n registro' 61)
A                                      WINDOW(BAN40P01)
A            CURS01         5S 0H
A            NRR            4S 0H      SFLRCDNBR(CURSOR)
A            CAMCUR        10A  H
A            REGCUR        10A  H
A            WKSTNS        10A  O  1 30DSPATR(HI)
A                                  2  3DATE
A                                      EDTCDE(Y)
A                                      DSPATR(HI)
A                                  2 40USER
A                                      DSPATR(HI)
A            D_DSPAIS      25A  B  4 10DSPATR(HI)
A                                  4  4'Pais'
A                                  7  3'Opc'
A                                      DSPATR(HI)
A                                      DSPATR(UL)
A                                  7  8'Pais'
A                                      DSPATR(HI)
A                                      DSPATR(UL)
A                                  5  4'1-Seleccionar'
A                                  1 18'Lista de paises'
A                                      DSPATR(HI)
A                                  1  3'BAN40P1'
A                                      DSPATR(HI)
A          R BAN40P01
A                                      WINDOW(2 15 20 50)
A                                      WDWBORDER((*DSPATR RI) (*CHAR '    -
A                                          '))
A                                 18  5'F3-Salir'
A          R BAN40R00
A                                      KEEP
A                                      ASSUME
A                                  5  3' ' 


Se define:

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.


viernes, 17 de mayo de 2013

Indice. ILE

En este índice están recopiladas las entradas más importantes relacionadas con el tema de ILE así como los ejemplo de código aportado.

Definición



Como ejemplo de desarrollo, se realizarán las siguientes funcionalidades basada de un esquema de base de datos de prueba relativas a clientes y cuentas de clientes:

  • Tres programas de lista de selección (F4). Lista de países, de tipos de cliente y de tipos de cuenta. (BAN40P1EJ, BAN40P2EJ, BAN40P3EJ)
  • Un programa ejecutable con la lista de clientes y el mantenimiento de clientes y también el acceso a la lista de cuentas de un cliente y el mantenimiento de una cuenta de clientes (BAN01P1EJ), Este programa tendrá cuatro módulos; para lista de clientes, para mantenimiento de un cliente, para lista de cuentas del cliente y para mantenimiento de una cuenta. 
  • Un programa de servicio con todos los componentes de acceso a base de datos, de actualización de la base de datos y de validación. (BAN01M1SRV)



Capa de acceso a datos y lógica de negocio


Capa de presentación visual 

 Se puede descargar todos los programas, módulos y pantalla de esta aplicación de prueba desde este enlace

Cuando se descargue, todos los fuentes deberían ponerse en un archivo de fuentes QRPGLESRC ya que tiene un CL para poderlo compilar los módulos y programas (previamente hay que compilar las pantallas). Se utilizará el comando:
 CALL BAN_COMPIL PARM('*ALL  ' 'Libfuentes' 'LibObjetos') donde Libfuentes será la biblioteca donde están los fuentes y LibObjetos la biblioteca donde se generarán los objetos.


Información adicional

miércoles, 15 de mayo de 2013

Componente. Validación



Objetivo


Crear componentes  que sean capaces de validar determinada información. 
En este ejemplo, se realizará un componente para validar varios campos.

Referencias: ILE estrategiaBD Pruebas

Estos componentes complementan al componente acceso de datos y de actualización de base de datos presentado en entradas anteriores.

Configuración

Se utiliza SQL para el desarrollo del código. El componente  formará parte de un programa de servicio y será exportable por lo que podrá ser llamado por el programa que enlace este programa de servicio.
  • Los nombres de los componentes (Val_Nombre, Val_IdPais). Utilizo siempre Val_xxxxxx donde xxxxx es el nombre del campo a validar.
  • El nombre del módulo donde estarán los componentes BAN01M1
  • El miembro (/Copy) con la definición del prototipo con los componentes y con la definición de estructuras será BAN01M1CP
  • El programa de servicio donde estarán los módulos BAN01SRV. Tendrá un miembro asociado con el mismo nombre con la definición (binder) de los componentes a exportar.

Miembro /Copy. BAN01M1CP

Se describen las estructuras de datos que dan servicio al componente de acceso a base de datos y el prototipo de llamada. Estarán en un miembro fuente independiente para que sea utilizado como /Copy tanto por el fuente del componente como los fuentes de los posibles programas que lo utilicen.


 *==========================================================
 *    Validar Campo de Nombre de cliente
 *       E01 - No permite blancos
 *==========================================================
DVal_Nombre       PR              n
D P_Nombre                      50    Const
D P_IdError                      3

 *==========================================================
 *    Validar Campo de Pais
 *       E01 - No permite blancos
 *       E02 - Pais no existe
 *==========================================================
DVal_IdPais       PR              n
D P_IdPais                       3    Const
D P_IdError                      3          



Está compuesto por:
  • (Val_Nombre) Definición de prototipo (interfaz) para validar el campo de nombre del fichero de clientes.
  • (Val_IdPais) Definición de prototipo (interfaz) para validar el campo de Id de Pais del fichero de clientes.

Al principio del fuente del componente se utiliza el /COPY para “cargar” las estructuras de datos y los prototipos de los componentes. 

/COPY *LIBL/QRPGLESRC,BAN01M1CP

Fuente del componente. Val_Nombre en BAN01M1

Este componente valida que sea correcto el contenido del campo nombre que pertenece al fichero de clientes

El componente tiene el siguiente código:

martes, 14 de mayo de 2013

Componente. Actualización de base de datos


Objetivo


Crear un componente que sea capaz de añadir, actualizar o borrar un registro de una entidad de una base de datos. 
En este ejemplo, se realizará un componente para actualizar información de la tabla de clientes.


Estos componentes complementan al componente acceso de datos presentado en entradas anteriores.

Configuración

Se utiliza SQL para el desarrollo del código. El componente  formará parte de un programa de servicio y será exportable por lo que podrá ser llamado por el programa que enlace este programa de servicio.
  • Los nombres de los componentes (Add_Cliente, Upd_Cliente, Dlt_Cliente). Utilizo siempre Add_xxxxxx, Upd_xxxxx, Dlt_xxxxx donde xxxxx es la entidad para la definición del componente de actualización.
  • El nombre del módulo donde estarán los componentes BAN01M1
  • El miembro (/Copy) con la definición del prototipo con los componentes y con la definición de estructuras será BAN01M1CP
  • El programa de servicio donde estarán los módulos BAN01SRV. Tendrá un miembro asociado con el mismo nombre con la definición (binder) de los componentes a exportar.

Miembro /Copy. BAN01M1CP

Se describen las estructuras de datos que dan servicio al componente de acceso a base de datos y el prototipo de llamada. Estarán en un miembro fuente independiente para que sea utilizado como /Copy tanto por el fuente del componente como los fuentes de los posibles programas que lo utilicen.


 *===========================================================
 ** Alta de cliente
 *===========================================================
DDs_AddClie       DS                  QUALIFIED
D Nombre                        50
D Apellidos                    100
D Direccion                    100
D IdPais                         3
D IdTipCli                       1

DAdd_Cliente      PR            10  0
D P_DsClieAlt                         Const LikeDs(Ds_AddClie)

 *============================================================
 ** Actualizacion de cliente
 *============================================================
DDs_UpdClie       DS                  QUALIFIED
D Nombre                        50
D Apellidos                    100
D Direccion                    100
D IdPais                         3
D IdTipCli                       1

DUpd_Cliente      PR
D P_IdCliente                   10  0 Const
D P_DsClieMod                         Const LikeDs(Ds_UpdClie)

 *============================================================
 ** Borrado de cliente
 *============================================================
DDlt_Cliente      PR
D P_IdCliente                   10  0 Const


Está compuesto por:
  • (Ds_AddClie) y (Ds_UpdClie)  Estructura de datos con los campos para generar un cliente y para actualizar un cliente respestivamente.
  • (Add_Cliente) Definición de prototipo (interfaz) para generar un nuevo cliente.
  • (Upd_Cliente) Definición de prototipo (interfaz) para actualizar los datos de un cliente
  • (Dlt_Cliente) Definición de prototipo (interfaz) para generar un nuevo cliente.

Al principio del fuente del componente se utiliza el /COPY para “cargar” las estructuras de datos y los prototipos de los componentes. 

/COPY *LIBL/QRPGLESRC,BAN01M1CP

Fuente del componente. Add_Cliente en BAN01M1

Este componente genera un nuevo cliente en la tabla correspondiente y devuelve el id de cliente (clave primaria) que ha generado


El componente tiene el siguiente código:

lunes, 13 de mayo de 2013

Componente. Acceso a BD

Objetivo


Crear un componente que sea capaz de devolver un registro o una lista de registros de una o varias entidades de una base de datos. Debe permitir que se pueda seleccionar un filtro de datos y también indicar la ordenación que se desea. Además debe ser posible indicar que se devuelvan los registros de una determinada página, es decir, desde una determinada posición y un número determinado de registros.
En este ejemplo, se realizará un componente para obtener información de la tabla de clientes.




Configuración

Se utiliza SQL para el desarrollo del código. El componente  formará parte de un programa de servicio y será exportable por lo que podrá ser llamado por el programa que enlace este programa de servicio.
  • El nombre de componente (Obt_LstClientes). Utilizo siempre Obt_Lstxxxxxx donde xxxxx es la entidad para la definición del componente de acceso a base de datos para recuperar una  lista de registros.
  • El nombre del módulo donde estarán los componentes BAN01M1
    Tendrá los siguientes componentes:
    • (Obt_LstClientes) para recuperar la lista de clientes. Exportable
    • (Obt_LstCuentas) para recuperar la lista de cuentas. Exportable
    • (Sentencia_Ini) para inicializar el cursor de la ejecución de la sentencia. INTERNO.
    • (Sentencia_Fin) para finalizar el cursor de la ejecución de la sentencia. INTERNO.
  • El miembro (/Copy) con la definición del prototipo con los componentes y con la definición de estructuras será BAN01M1CP
  • El programa de servicio donde estarán los módulos BAN01SRV. Tendrá un miembro asociado con el mismo nombre con la definición (binder) de los componentes a exportar.

Miembro /Copy. BAN01M1CP

Se describen las estructuras de datos que dan servicio al componente de acceso a base de datos y el prototipo de llamada. Estarán en un miembro fuente independiente para que sea utilizado como /Copy tanto por el fuente del componente como los fuentes de los posibles programas que lo utilicen.


      ** Estrutura datos basicos de Clientes
DDs_BasClie       DS                  QUALIFIED
D IdCliente                     10  0
D Nombre                        50
D Apellidos                     50
D Direccion                     50
D IdPais                         3
D DsPais                        50
D IdTipCli                       1
D DsTipCli                      50

** Estructura seleccionador de datos
DDs_SelClie       DS                  QUALIFIED
D K_IdCliente                   10  0
D S_DsCliente                   50
D S_IdPais                       3
D S_IdTipCli                     1

** Prototipo de lista de clientes.
DObt_LstClientes  PR
D P_DatosClie                         Dim(99) LikeDs(Ds_BasClie)
D P_NumReg                       2  0
D P_TotReg                      10  0
 *Opcionales
D P_Pag                          6  0 Const OPTIONS(*NOPASS)
D P_RegCarPag                    3  0 Const OPTIONS(*NOPASS)
D P_OrderBy                      2    Const OPTIONS(*NOPASS)
D P_Sel                               LikeDs(Ds_SelClie) Const
D                                     OPTIONS(*NOPASS)


Está compuesto por:
  • (Ds_BasClie) Estructura de datos con los campos que se recuperarán de la instrucción SQL y que estarán en el array de datos que se devuelve.
  • (Ds_SelClie) Estructura de datos con los campos que se permite utilizar para seleccionar (se utilizarán en WHERE) para filtrar la sentencia SQL.
    • (K_) Seleccionador de clave primaria del fichero, en este ejemplo, será el código de cliente.
    • (S_) Otros posibles seleccionadores según la definición que se haga en el componente. 
  • (Obt_LstClientes) La definición del prototipo (interfaz) de llamada al componente. Más adelante explicaré los parámetros del mismo.

Al principio del fuente del componente se utiliza el /COPY para “cargar” las estructuras de datos y los prototipos de los componentes. 

/COPY *LIBL/QRPGLESRC,BAN01M1CP

Fuente del componente. Obt_LstClientes en BAN01M1

Parámetros

El componente tendrá la siguiente definición de parámetros:

jueves, 9 de mayo de 2013

Estructuras de datos

Antes de comenzar con el detalle del desarrollo que indicaba en el artículo de estrategia con ILE voy a introducir un concepto que utilizo para el desarrollo de plantillas de código. Son el uso de estructuras de datos (Ds).

Parámetros, un problema para desarrollar plantillas.

Comentaba en el artículo que hecho referencia anteriormente que se podría desarrollar plantillas tanto para los módulos de presentación de pantalla como para los de acceso a base de datos y de lógica de negocio pero un problema a resolver para facilitar el uso de plantillas es el paso de parámetros entre programas, módulos o componentes.
La idea de tener plantillas es que tengan código invariable y ya probado que es independiente  de la funcionalidad que se esta desarrollando y que no hay que habría que tocar ni modificar. Pero ¿que pasa con los parámetros y el código probado para no tocar?

Imaginemos que tenemos un fichero X que tiene tres atributos (campos) y otro fichero Y que tenga cinco campos. Comentabamos que podíamos hacer una plantilla de componente para insertar registros a un fichero y que ese componente pudiera ser utilizado desde un modulo de presentación de pantalla Mod1 que en un caso haga el mantenimiento del fichero X y en otro Mod2 para el fichero Y.

La parte del código de los módulos de presentación de pantalla para llamar a insertar un registro cada uno en su fichero sería algo así

Parte del código de Mod1
 . . .
IdRegGenerado = Insertar_FileX(Campo1 : Campo2 : Campo3);



Parte del código de Mod2
 . . .
IdRegGenerado = Insertar_FileY(Campo1 : Campo2 : Campo3 : Campo4 : Campo5);


Así se presenta un problema a la hora de gestionar plantillas. Cada vez que se haga un proceso específico habría que cambiar las llamadas a TODOS los programas, módulos y componentes para poner los parámetros propios de cada uno. Y esto no parece muy bueno para la definición de plantillas.

La solución. Estructuras de datos. 

El objetivo es que los parámetros de llamada SIEMPRE sean los mismos y así no tener que "tocar" en la plantilla los parámetros de llamada a un programa, módulo o componente y en dichos fuentes tampoco tener que tocar los parámetros que recibe. 
Para ello utilizaré las estructuras de datos. Los parámetros serán estructuras de datos; así no hay que tocar los parámetros de llamada. Lo único que hay que hacer de una funcionalidad específica a otra, sería añadir más campos a la definición  de la estructura de datos y antes de la llamada, cargar los campos de esa estructura de datos.

Parte del código de Mod1

     D DsAltaFic       DS                  Qualified
     D   Campo1                       5
     D   Campo2                       5
     D   Campo3                       5 
. . .

         DsAltaFic.Campo1 = Campo1; 
         DsAltaFic.Campo2 = Campo2; 
         DsAltaFic.Campo3 = Campo3;  
         IdRegGenerado = Insertar_FileX(DsAltaFic);  




Parte del código de Mod2

     D DsAltaFic       DS                  Qualified
     D   Campo1                       5
     D   Campo2                       5
     D   Campo3                       5 
     D   Campo4                       5
     D   Campo5                       5

. . .

         DsAltaFic.Campo1 = Campo1; 
         DsAltaFic.Campo2 = Campo2; 
         DsAltaFic.Campo3 = Campo3; 
         DsAltaFic.Campo4 = Campo4; 
         DsAltaFic.Campo5 = Campo5; 
         IdRegGenerado = Insertar_FileY(DsAltaFic);  



Como vemos, aunque son dos componentes diferentes (insertar_FileX e insertar_FileY) que darán la misma funcionalidad (insertar un registro), ambos tienen el mismo número de parámetros, en este caso una estructura de datos con el mismo nombre pero que en cada caso tendrá un número de campos diferente.

En mis plantillas de fuentes Rpg, las llamadas siempre están definidas con estructuras de datos para evitar estar "tocando" los parámetros entre los procesos que llaman y los llamados.