Skip to content

ZMF supplied skeleton changes

General note on usage: The call to the REST server will wait for a response. The REST server will wait for a response from the process that it has been asked to initiate (i.e. a Jenkins job etc.). If the target process returns immediately then response times need not be an issue. If you want the target process to perform significant processing (e.g. standards checking/testing etc.) then the response may be a long time in coming. In these batch processes this may not be a huge concern. However, contrast this with the similar note made at the start of the following section on HLL exit use of the REST server. Also note that the CMNURIBA program will return CC=12 for any http response from the REST server other than one of the 2xx series. Again, contrast this with the out-of-the-box support supplied for HLLX.

Two sample skeletons are provided to allow batch jobs generated by ZMF to call the REST server. The call itself is coded in *CMN$$EVT* and this skeleton can be embedded anywhere. The majority of the out-of-the-box support for ZMF generated batch job event notification is supplied via skeleton *CMNEVT* (which embeds CMN$$EVT).

Existing skeletons related to 'success' notification have been modified to embed CMNEVT as required, these are:

CMN00

CMN00INS

CMNRPMB0

Further changes have been needed to a group of skeletons that embed CMN00INS twice, so that the REST server call is only made for a success notification. These are:

CMN20, 20I, 20T, 20TI

CMN55, 55I

Certain event notifications are generated directly via the ZMF file tailoring mechanism (i.e. the file tailoring includes CMN$$EVT directly). This is to avoid changing more existing skeletons than is absolutely necessary, these event ids are:

50 Package audit
52 Release area audit
57 Package audit autoresolve submitted
58 Release area autoresolve submitted
78 Checkin to release area
100 Build begins
101 Build ends

It may be that one wishes to move the location of the event notification away from that generated by ZMF file tailoring into a skeleton of their choice. To do this the original file tailoring must be neutralized and a sample skeleton, CMN$$EVX, has been provided to show how this can be done. Comparison of CMN$$EVX and CMN$$EVT will reveal the changes required. New variables are defined to indicate whether the REST server is active in general and active for specific events. These variables are set by the job generation program (i.e. CMNVFTLR, CMNVPRFT, CMNVRPFT, CMNVPIJB) and they will be available to all skeletons. If the user has chosen not to enable support for the REST server in general or for a specific event then the imbedded skeleton CMN$$EVT will do nothing. The call to the REST server is made using CMNURIBA (see example above) and every standard variable is passed (whether it is available or not), the REST server will work out which variables, from the list, it will use for a specific event.

The new ISPF variables are these:

EVTACTV The REST server is active if this is set to Y
EVTADDR The DNS/ip address of the REST server
EVTPORT The port number on which the REST server is listening
EVTCTX The context for the event servlet (default is zmfevent)
EVTNOxx xx or xxx is the event number (room for 3 digits if necessary). This variable will be set to Y if the event is active (e.g. EVTNO12=Y)

The ZMF program that is generating these variables will check with the REST server to see if the specific event we are processing is active. If it is active then the EVTNOxx variable will be set to Y, else it will be set to N.

Example of SKEL to IMBED the CMN$$EVT SKEL:

...

)CM
)CM NOTIFICATION 12
)CM
)SEL &EVTACTV EQ Y AND &EVTNO12 EQ Y
)SETF &EVENTID = &STR(12)
)IM CMN$$EVT
)ENDSEL &EVTACTV EQ Y AND &EVTNO12 EQ Y
)CM
)CM End Of Notification 12

*Example SKEL For Event Client:*

//*)IM CMN$$EVT &EVENTID
)SEL &LISTNO EQ &Z
)SET LISTNO = 0
)ENDSEL &LISTNO EQ &Z
)SET LISTNO = &LISTNO + 1
//*
//* Call the REST server for ZMF event number &EVENTID
//*
//EVENT&EVENTID EXEC PGM=CMNURIBA
//*
)SEL &EVENTID NE 100 AND &EVENTID NE 12
//SYSPRINT DD SYSOUT=*
)ENDSEL &EVENTID NE 100 AND &EVENTID NE 12
)SEL &EVENTID EQ 100 OR &EVENTID EQ 12
//SYSPRINT DD DISP=(,PASS),DSN=&&&&LIST9&LISTNO,
//             &DEFNVKW=&DEFNVUN,SPACE=(TRK,(1,3),RLSE),
//             DCB=(RECFM=FA,LRECL=133,BLKSIZE=0)
)ENDSEL &EVENTID EQ 100 OR &EVENTID EQ 12
//JSONIN DD DATA,DLM=@@
{
  "EVENT" : "&EVENTID.",
  "USERID" : "&USER.",
  "APPL" : "&PROJECT.",
  "PACKAGE" : "&PKGNAME.",
  "SITE" : "&RMTSITE.",
  "RELEASE" : "&RLSNAME.",
  "RELEASEAREA" : "&ARENAME.",
  "PROMOTIONNAME" : "&PROMNME.",
  "PROMOTIONLEVEL": "&PROMLVL.",
  "LIBTYPE" : "&CMPTYPE.",
  "COMPONENT" : "&CMPNAME."
}
@@
//SYSIN DD *
Server=&EVTADDR
Port=&EVTPORT
Context=&EVTCTX
Method=POST
/*
//*

The supplied skeleton, CMN$$EVT, can be further modified should one wish to save the JSON response body as part of the job output. This is not implemented as delivered as, in most cases, one will not wish to do this and we want to keep the skeletons as simple as possible. The way to do this is, as mentioned in an earlier section, to add the CMNRSPNS DD statement to the CMNURIBA step and add a following PRETTY print step. Sample CMN$$EVT modifications are shown here:

...

//*)IM CMN$$EVT &EVENTID
//* Modified to produce JSON body output
//* Modified to produce JSON body output
//* Modified to produce JSON body output
)SEL &LISTNO EQ &Z
)SET LISTNO = 0
)ENDSEL &LISTNO EQ &Z
)SET LISTNO = &LISTNO + 1
//*
//* Call the REST server for ZMF event number &EVENTID
//*
//EVENT&EVENTID EXEC PGM=CMNURIBA
//*
)SEL &EVENTID NE 100 AND &EVENTID NE 12
//SYSPRINT DD SYSOUT=*
)ENDSEL &EVENTID NE 100 AND &EVENTID NE 12
)SEL &EVENTID EQ 100 OR &EVENTID EQ 12
//SYSPRINT DD  DISP=(,PASS),DSN=&&&&LIST9&LISTNO,
//          &DEFNVKW=&DEFNVUN,SPACE=(TRK,(1,3),RLSE),
//          DCB=(RECFM=FA,LRECL=133,BLKSIZE=0)
)ENDSEL &EVENTID EQ 100 OR &EVENTID EQ 12
//CMNRSPNS  DD DISP=(,CATLG),DSN=CMNDEV.&USER..JSON.TEMP&EVENTID.,
//         SPACE=(CYL,(1,1)),UNIT=SYSDA
//JSONIN   DD  DATA,DLM=@@
{
  "EVENT" : "&EVENTID.",
  "USERID" : "&USER.",
  "APPL" : "&PROJECT.",
  "PACKAGE" : "&PKGNAME.",
  "SITE" : "&RMTSITE.",
  "RELEASE" : "&RLSNAME.",
  "RELEASEAREA" : "&ARENAME.",
  "PROMOTIONNAME" : "&PROMNME.",
  "PROMOTIONLEVEL": "&PROMLVL.",
  "LIBTYPE" : "&CMPTYPE.",
  "COMPONENT" : "&CMPNAME."
}
@@
//SYSIN     DD *
Server=&EVTADDR
Port=&EVTPORT
Context=&EVTCTX
Method=POST
/*
//*
//PRETTY   EXEC PGM=IKJEFT01,REGION=0M
//REMOVE    DD DISP=(OLD,DELETE),DSN=CMNDEV.&USER..JSON.TEMP&EVENTID
//SYSEXEC   DD DISP=SHR,DSN=SYS1.SAMPLIB
)SEL &EVENTID NE 100 AND &EVENTID NE 12
//SYSTSPRT  DD SYSOUT=*
)ENDSEL &EVENTID NE 100 AND &EVENTID NE 12
)SEL &EVENTID EQ 100 OR &EVENTID EQ 12
//SYSTSPRT  DD DISP=(,PASS),DSN=&&&&LIST8&EVENTID.,
//            UNIT=SYSALLDA,SPACE=(CYL,(1,5),RLSE),
//            DCB=(RECFM=FBA,LRECL=133,BLKSIZE=27930)
)ENDSEL &EVENTID EQ 100 OR &EVENTID EQ 12
//SYSTSIN    DD *
HWTJSPRT CMNDEV.&USER..JSON.TEMP&EVENTID
//*

The file tailoring programs have been changed to allow for the supplied skeletons to call the REST server as necessary. They each call the REST server during initialization to see whether the REST server is active in general and if the events they will be generating are subscribed to.

The triggers to embed the calls to the REST server will only be active if the REST server is active and the specific event is subscribed to. Those who don't use the REST server will see no changes to the generated JCL.

CMNVFTLR prepends the build job JCL stream with a call to the REST server for event 100 (build job begins), it appends the JCL with a call to the REST server for event 101 (build job ends). It also sets variables for event no 12 (component activation) which prompt the generated JCL to embed CMN$$EVT alongside the SUCCESS step. It also appends the package audit JCL stream with a call for event no 50 (package audit). CMNVPRFT and CMNVRPFT set variables for event no 44 (package demote) and 48 (package promote).

CMNVPIJB sets variables immediately prior to file tailoring the relevant job stream into the 'x' dataset member. It does this for events 01 (package backout), 02 (package install), 03 (temporary package cycle), 10 (package revert), 15 (baseline ripple), and 16 (reverse ripple).