COBOL - CICS - DB2



Vamos a comenzar creando los datasets necesarios para este ejemplo.

IBMUSER.DB2.BIND		Se creara la union entre CICS y DB2. El Compilado CICS dejera datos que usara DB2
IBMUSER.DB2.DMRMLIB		Codigo objeto de compilar para CICS DB2
IBMUSER.DB2.DCLGEN		Contiene Declaraciones a incluir en la working
IBMUSER.DB2.DCLGEN.COBOL	El DCLGEN pedirá este dataset para depositar el miembro de declaraciones aquí
IBMUSER.DB2.DSNHOUT		Dataset para los mensajes de error o problemas
IBMUSER.DB2.SPUFI		Libreria de Spufis. Cada Member es un comando de SPUFI para crear la DB a usar
IBMUSER.DB2.SPUFO		Es la salida de los comandos de SPUFI para ver si algo no fue bien el resultado

Todos los datasets los creamos con la siguiente estructura, excepto IBMUSER.DB2.SPUFO que debe ser secuencial para el volcado de información de la ejecución de los SPUFIs.

Para esto, desde el menú principal de ispf, '3 Utilities', '2 Data Set' y opcíon 'A Allocate new data set' ingresando cada nombre en

Other Partitioned, Sequential or VSAM Data Set:
Name . . . . . . . ___________________


                            Allocate New Data Set                              
Command ===>                                                                   
                                                                                
Data Set Name  . . . : IBMUSER.DB2.SPUFI                                       
                                                                                
Management class . . .                (Blank for default management class)     
Storage class  . . . .                (Blank for default storage class)        
     Volume serial . . . . ZVOL00         (Blank for system default volume) **     
     Device type . . . . .                (Generic unit or device address) **      
Data class . . . . . .                (Blank for default data class)           
     Space units . . . . . TRACK          (BLKS, TRKS, CYLS, KB, MB, BYTES         
                                        or RECORDS)                             
     Average record unit                  (M, K, or U)                             
     Primary quantity  . . 13             (In above units)                         
     Secondary quantity    15             (In above units)                         
     Directory blocks  . . 10             (Zero for sequential data set) *         
     Record format . . . . FB                                                      
     Record length . . . . 80                                                      
     Block size  . . . . . 27920                                                   
     Data set name type    PDS            (LIBRARY, HFS, PDS, LARGE, BASIC, *      
                                        EXTREQ, EXTPREF or blank)               
     Expiration date . . .                (YY/MM/DD, YYYY/MM/DD                    
Enter "/" to select option             YY.DDD, YYYY.DDD in Julian form         
     Allocate Multiple Volumes           DDDD for retention period in days       
                                        or blank)                               
                                                                                
( * Specifying LIBRARY may override zero directory block)                      
                                                                                
( ** Only one of these fields may be specified)                                
                                                                                

Para el caso de IBMUSER.DB2.SPUFO usamos la siguiente configuración.

                            Allocate New Data Set                              
Command ===>                                                                   
                                                                                
Data Set Name  . . . : IBMUSER.DB2.SPUFO                                       
                                                                                
Management class . . .                (Blank for default management class)     
Storage class  . . . .                (Blank for default storage class)        
     Volume serial . . . . ZVOL00         (Blank for system default volume) **     
     Device type . . . . .                (Generic unit or device address) **      
Data class . . . . . .                (Blank for default data class)           
     Space units . . . . . TRACK          (BLKS, TRKS, CYLS, KB, MB, BYTES         
                                        or RECORDS)                             
     Average record unit                  (M, K, or U)                             
     Primary quantity  . . 13             (In above units)                         
     Secondary quantity    15             (In above units)                         
     Directory blocks  . . 0              (Zero for sequential data set) *         
     Record format . . . . FB                                                      
     Record length . . . . 80                                                      
     Block size  . . . . . 27920                                                   
     Data set name type    PDS            (LIBRARY, HFS, PDS, LARGE, BASIC, *      
                                        EXTREQ, EXTPREF or blank)               
     Expiration date . . .                (YY/MM/DD, YYYY/MM/DD                    
Enter "/" to select option             YY.DDD, YYYY.DDD in Julian form         
     Allocate Multiple Volumes           DDDD for retention period in days       
                                        or blank)                               
                                                                                
( * Specifying LIBRARY may override zero directory block)                      
                                                                                
( ** Only one of these fields may be specified)                                
                                                                                

El siguiente paso es crear los miembros que vamos a usar con la utilidad SPUFI.

Dentro de IBMUSER.DB2.SPUFI vamos a ir creando con nombre SPU001, SPU002, SPU003, SPU004 y SPU005, cada uno con una función diferente.

Para ejecutar cada uno en SPUFI, desde el menú principal de ispf '=m.15.1' y ENTER, para entrar al SPUFI.

                           SPUFI                              SSID: DB9G       
          ===>                                                                           
                                                                                         
          Enter the input data set name:        (Can be sequential or partitioned)       
           1  DATA SET NAME ... ===> 'IBMUSER.DB2.SPUFI(SPU001)'                         
           2  VOLUME SERIAL ... ===>            (Enter if not cataloged)                 
           3  DATA SET PASSWORD ===>            (Enter if password protected)            
                                                                                         
          Enter the output data set name:       (Must be a sequential data set)          
           4  DATA SET NAME ... ===> 'IBMUSER.DB2.SPUFO'                                 
                                                                                         
          Specify processing options:                                                    
           5  CHANGE DEFAULTS   ===> YES        (Y/N - Display SPUFI defaults panel?)    
           6  EDIT INPUT ...... ===> YES        (Y/N - Enter SQL statements?)            
           7  EXECUTE ......... ===> YES        (Y/N - Execute SQL statements?)          
           8  AUTOCOMMIT ...... ===> YES        (Y/N - Commit after successful run?)     
           9  BROWSE OUTPUT ... ===> YES        (Y/N - Browse output data set?)          
                                                                                         
          For remote SQL processing:                                                     
          10  CONNECT LOCATION  ===>                                                     
                                                                                         
                                                                                         
          PRESS:  ENTER to process    END to exit              HELP for more information 
                                                                                         

Cada vez que ejecutamos uno de los miembros, cambiamos al siguiente en 'IBMUSER.DB2.SPUFI(SPU001)'.

Al terminar con los 5 desde QMF, con un 'select * from clientes' podremos ver la tabla creada con varios registros.

NOTA: Si algo no funcionó deberemos comenzar desde el paso anterior nuevamente. Para borrar el dataset creado usar este JCL


El siguiente paso va a ser crear el miembro de declaraciones (variables usadas por la DB) que se va a incorporar en el COBOL.

Desde el menú principal del ispf '=m.15.2' y ENTER. Completamos como se muestra a continuación.

                           DCLGEN                             SSID: DB9G      
          ===>                                                                          
                                                                                        
          Enter table name for which declarations are required:                         
           1  SOURCE TABLE NAME ===> CLIENTES                                           

           2  TABLE OWNER ..... ===> IBMUSER                                            
                                                                                        
           3  AT LOCATION ..... ===>                                     (Optional)     
          Enter destination data set:          (Can be sequential or partitioned)       
           4  DATA SET NAME ... ===> 'IBMUSER.DB2.DCLGEN(CLIENTES)'                     
           5  DATA SET PASSWORD ===>           (If password protected)                  
          Enter options as desired:                                                     
           6  ACTION .......... ===> REPLACE   (ADD new or REPLACE old declaration)     
           7  COLUMN LABEL .... ===> YES       (Enter YES for column label)             
           8  STRUCTURE NAME .. ===> CL-CLIENTES                         (Optional)     
           9  FIELD NAME PREFIX ===> CL-                                 (Optional)     
          10  DELIMIT DBCS .... ===> NO        (Enter YES to delimit DBCS identifiers)  
          11  COLUMN SUFFIX ... ===> YES       (Enter YES to append column name)        
          12  INDICATOR VARS .. ===> NO        (Enter YES for indicator variables)      
          13  ADDITIONAL OPTIONS===> NO        (Enter YES to change additional options) 
                                                                                        
          PRESS: ENTER to process    END to exit      HELP for more information         
                                                                                        

ENTER para ejecutar y si todo va bien.

DSNE905I EXECUTION COMPLETE, MEMBER CLIENTES ADDED
***                                               

Hasta aquí la creación de la DB y las declaraciones (que se pueden visualizar en IBMUSER.DB2.DCLGEN.COBOL(CLIENTES).

Ahora vamos a crear el mapa CICS en IBMUSER.CICS.MAPS(HOL4MP).

HOL4MP es muy simple y solo tiene unas pocas modificaciones respecto del ejercicio anterior. HOL4MP.TXT.

Una vez creado en la carpeta correspondiente, para compilarlo usamos este JCL.

Antes de submitirlo, ejecutamos el comando 'C XXXXXX HOL4MP ALL' en modo view, para cambiar las XXXXXX por HOL4MP en el código, y finalmente el 'sub' y ENTER.


Pasamos al código COBOL. Creamos IBMUSER.CICS.SOURCE(HOL4). El código es HOL4.

NOTA: Al copiar HOL4 al z/OS revisar que cada instrucción comience en la columna correspondiente (7 para comentarios, 8 para AREA A, 12 para AREA B) para evitar errores al compilar.


Solo nos queda el JCL que va a unir compilando todo junto 'IBMUSER.JCL(CCICSDB2)'. El código es CCICSDB2.

Con esto ya tenemos todos los codigos que formarán parte de la transacción CICS.

Ahora pasamos a un detalle muy importante.

Nuestro z/OS, CICS al iniciarse debe establecer contacto de comunicación con DB2 y para esto debemos decirle explícitamente que lo haga.

Para esto vamos a entrar al CICS 'L CICS' y vamos a cerrarlo con 'CEMT P SHUT I'

En la terminal 1 nos indica '+DFHKE1799 CICS TERMINATION OF CICS IS COMPLETE.'.

Con '=3.4' y ENTER desde el menú principal de ispf buscamos los dataset con 'DSNAME LEVEL . . . **.SYSIN'

Va a encontrar 'DFH320.SYSIN(DFH$SIP1)', y con muchísimo cuidado vamos a editarlo.

Luego de la linea '000300 AUXTR=OFF,' vamos a insertar una linea en blanco para ingresar lo siguiente.

'DB2CONN=YES,' como se muestra en la siguiente imagen.

Le damos ENTER, guardamos con SAVE, y salimos. Ahora reiniciamos el cics desde la terminal 1 con 'S CICSA'



NOTA: En este punto estoy trabado ya que el CICS, al iniciar, tira error al iniciar conexion con la DB. Si alguien sabe como arreglarlo por favor contácteme a marauggar@gmail.com. GRACIAS.

Este error '- 01.23.41 STC00264 +DFHSI8442 CICS Connection to DB2 has failed.'

NOTA 2: Error corregido. En breve continuaré desarrollando este ejemplo y explicaré como configurar todo para que no ocurra.



Dado el problema que tuve, voy a hacer un paréntesis en el ejemplo para explicar algunas cosas.

Al reiniciar el CICS como se indica mas arriba, nos encontraremos en la terminal 1 con la siguiente indicación.

'- 01.23.41 STC00264  +DFHSI8442 CICS Connection to DB2 has failed.'

Este mensaje significa que se ha intentado iniciar automaticamente alguna conexión de cics con DB2 y no se ha podido.

¿Por que?. Porque cada vez que salimos de CICS o reiniciamos CICS todas las instalaciones que habiamos hecho dejan de funcionar.

Ejemplo de esto es que los ejercicios anteriores al salir de cics, ya no funcionan.

Entonces ¿que se puede hacer?. Hay dos salidas al problema.


Vamos a crear tres estructuras en CICS para ir retomando el ejercicio y explicando las dos soluciones. La primera estructura es la conexión.

CEDA DEF DB2CONN

y llenamos con los siguientes datos (Esta es la DB2Connection)

DB2Conn    ==> CICS$DB2
Group      ==> HOL4

DB2id      ==> DB9G

Nontermrel ==> NO

THREADError==> Abend

ACcountrec ==> TXID
AUTHId     ==> IBMUSER

COMAUTHId  ==> IBMUSER

     

Con ENTER se crea el group HOL4.



La segunda estructura se llama DB2Entry (La entrada de nuestra transaccion al db2)

CEDA DEF DB2ENTRY
DB2Entry	==> HOL4
Group		==> HOL4

ACcountrec	==> TXid
AUTHId		==> IBMUSER

PLAN		==> HOL4PL
     

(Por cada plan creado en DB2 se crea una DB2 Entry para que el grupo pueda utilizar el plan y el acceso)



La tercera estructura, con la que llamaremos a que el programa se ejecute

CEDA DEF DB2TRAN
DB2Tran		==> HOL4TRAN
Group		==> HOL4
Entry		==> HOL4
Transid		==> HOL4
          
     


Para ver las estructuras que acabamos de crear

CEDA DI GROUP(HOL4)

Si en este momento instalamos como vimos en ejemplos anteriores, CICS$DB2 y ejecutamos el comando 'DSNC STRT' recibiriamos el siguiente error.

DFHDB2040 12/08/2023 11:47:26 CICS DSNC Module DSNAPRH could not be found.

que no significa otra cosa que debemos agregar el dataset que contiene DSNPRH al concatenado de inicio de CICS.

Con 'C CICSA' en la terminal 1 detenemos el CICS.

Buscamos con '**.proclib' (=3.4 desde el menú de inicio de ispf), (que son las librerias de inicio), cual es la de inicio de CICS.

En nuestro caso 'ADCD.Z110.PROCLIB(CICSA)'

Editamos CICSA con mucho cuidado de cambiar solo lo siguiente.

En las lineas 60, 61, 62, (en el STEPLIB), agregamos '// DD DSN=DSN910.SDSNLOAD,DISP=SHR', grabamos con 'SAVE' y salimos con 'F3'

Desde el terminal 1 reiniciamos el CICS con 'S CICSA'. Aún seguiremos viendo la falla en el inicio de la conexion con DB2, ya lo resolveremos.

Entramos al CICS, ejecutamos 'CEDA DI GROUP(HOL4)', instalamos 'CICS$DB2', salimos con 'F3' y 'ALT+C' (que es CLEAR).

Ahora ejecutamos nuevamente 'DSNC STRT', y ¡FUNCIONO!. Este es el método MANUAL.

Ya que estamos, hagamos que la conexión con DB2 se ejecute AUTOMATICAMENTE. Esto lo hacemos con las listas de ejecucion de inicio de CICS.

Por defecto CICS trae una lista de ejecución de programas al inicio llamada 'XYZLIST'

Para no mezclar nuestros programas con la lista original vamos a crear una lista nueva 'MAGLIST' en mi caso.

Desde CICS ejecutamos lo siguiente para crearla

CEDA ADD GROUP(HOL4) LIST(MAGLIST)

Volvemos a editar 'DFH320.SYSIN(DFH$SIP1)' para agregar GRPLIST=(XYZLIST,MAGLIST), en donde solo estaba 'XYZLIST' que es la lista por defecto.

Cerramos y volvemos a iniciar CICS... y veremos en la terminal 1 que la connexión se ha establecido AUTOMATICAMENTE con la base de datos.

¡Se acabo el problema! podemos seguir con nuestro ejemplo.



Volvemos al CICS para seguir creando las estructuras necesarias para que todo funcione.

Con CEDA DEF MAP(HOL4MP) GROUP(HOL4) indicamos cual va a ser el mapa.

Con CEDA DI GROUP(HOL4) ahora deberían aparecer 4 estructuras.

Con CEDA DEF PROG(HOL4) GROUP (HOL4) definimos el programa cobol compilado.

Con CEDA DEF TRANS(HOL4) PROG(HOL4) GROUP(HOL4) definimos la forma en que vamos a ejecutar todo desde CICS (la transacción)

Ahora si hacemos CEDA DI GROUP(HOL4) apareceran los seis miembros del grupo.

Con 'I' en cada uno de los miembros instalamos los seis.

Si todo fue bien hasta acá, con CEMT S PROG(HOL4) indicamos que comience a ejecutar la transacción. Para esto ingresamos 'N' entre Pri y Ced.

Al darle ENTER cambiara el Len()...

NOTA: Habiendo llegado hasta acá, si este punto da error es porque falta definir en CICSA el dataset IBMUSER.CICS.LOAD, en la sección 'DFHRPL DD...' (que ya lo habiamos hecho en el ejercicio Hola Mundo)

Todo listo para probar. Con 'HOL4' debería funcionar.












¡Listo!




NOTA: me habia olvidado de la descripción una parte importantisima para que todo funcione. Desde ya me disculpo por los quebraderos de cabeza.

En IBMUSER.DB2.BIND vamos a cargar este CODIGO con el nombre 'HOL4'

En IBMUSER.MAG.JCL vamos a cargar este CODIGO con el nombre 'DFHEILID'