Building modular JCL with external code fragments and library management
JCL Include is a mechanism that allows you to insert predefined JCL code fragments from libraries into your job stream. This promotes modular JCL development by enabling reuse of common code patterns across multiple jobs without duplication.
Key benefits of using JCL Include:
The JCLLIB statement specifies the libraries that contain procedures and include members for a job. It establishes the search order for these libraries.
12//jobname JOB parameters // JCLLIB ORDER=(library1,library2,...)
The JCLLIB statement must appear after the JOB statement but before any EXEC statements that reference procedures or INCLUDE statements.
When the system searches for a procedure or include member, it searches the libraries in the order specified in the JCLLIB statement, and then the standard system procedure libraries.
12345678910//MYJOB JOB (ACCT),'MY JOB',CLASS=A //*-------------------------------------------------- //* Specify procedure and include libraries //*-------------------------------------------------- // JCLLIB ORDER=(USER.PROCLIB, // DEPT.PROCLIB, // SYS1.USERPROC) //STEP1 EXEC MYPROC //STEP2 EXEC PGM=MYPROG //...
In this example, when the system looks for the procedure MYPROC, it will search the libraries in this order:
The INCLUDE statement inserts JCL code from a specified library member directly into the job stream at the point where the INCLUDE appears.
1// INCLUDE MEMBER=membername
The system searches for the member in the libraries specified in the JCLLIB statement, or in the standard system include libraries if no JCLLIB statement is present.
1234567891011//MYJOB JOB (ACCT),'MY JOB',CLASS=A // JCLLIB ORDER=(USER.JCLLIB) //*-------------------------------------------------- //* Include standard JCL fragment for DB2 setup //*-------------------------------------------------- // INCLUDE MEMBER=DB2SETUP //*-------------------------------------------------- //* The rest of the job //*-------------------------------------------------- //STEP1 EXEC PGM=DB2PROG //...
In this example, the contents of the DB2SETUP member from USER.JCLLIB will be inserted at the point of the INCLUDE statement, as if it had been coded directly in the job.
Important: The included JCL is inserted during the conversion phase, before execution. All JCL rules and syntax must be valid after the inclusion.
Include members are created and stored as members of a partitioned dataset (PDS or PDSE). They can contain any valid JCL statements that would normally appear in a job.
Here's an example of what might be in the DB2SETUP include member:
12345678//*-------------------------------------------------- //* Standard DB2 environment setup //*-------------------------------------------------- //DB2LIB DD DSN=SYS1.DB2.LOADLIB,DISP=SHR //DBRMLIB DD DSN=USER.DB2.DBRMLIB,DISP=SHR //SYSTSIN DD * DSN SYSTEM(DB01) /*
When this member is included in a job, these statements will be inserted exactly as they appear here.
Effective management of JCL libraries is crucial for a successful modular JCL implementation:
Organize libraries by function, department, or application area to make members easy to locate.
Establish clear naming conventions for include members to indicate their purpose and usage.
Implement appropriate security controls to manage who can update JCL libraries.
Maintain version history of include members to track changes and support rollback if needed.
A typical JCL library structure might include:
Using a consistent library hierarchy helps ensure that the most appropriate version of an include member is found first when multiple libraries are searched.
Breaking down JCL into modular, reusable components offers several advantages:
When a change is needed, it can be made once in the include member rather than in multiple jobs.
Standard processes are implemented the same way across all jobs that use the include member.
Developers can focus on job-specific logic while reusing tested, proven components.
Organizational standards can be enforced by providing standard include members.
Include members can be thoroughly tested and optimized, benefiting all jobs that use them.
Use symbolic parameters to make include members flexible and adaptable to different contexts:
123456// SET ENV=PROD // SET APP=PAYROLL // INCLUDE MEMBER=DBSETUP ... // In DBSETUP: //DB DD DSN=&ENV..&APP..DATABASE,DISP=SHR
Create small, focused include members that do one thing well and can be combined as needed:
123// INCLUDE MEMBER=DBCONNECT // INCLUDE MEMBER=SECURITY // INCLUDE MEMBER=LOGGING
Include clear documentation within each include member:
12345678910//*-------------------------------------------------- //* DB2SETUP - Standard DB2 environment setup //* //* Parameters: //* &DBSYS - DB2 subsystem (default: DB01) //* &PLAN - Application plan name (required) //* //* Dependencies: //* Requires DB2 libraries to be available //*--------------------------------------------------
Use consistent, descriptive names for include members to indicate their purpose:
Thoroughly test include members before placing them in production libraries:
123456789101112131415//DBUTIL JOB (ACCT),'DB UTILITIES',CLASS=A // JCLLIB ORDER=(DBA.JCLLIB) // SET DBSYS=PROD // SET TABNAME=CUSTOMER //*-------------------------------------------------- // INCLUDE MEMBER=DBASETUP //*-------------------------------------------------- //STEP1 EXEC PGM=DSNUTILB,PARM='&DBSYS' //SYSPRINT DD SYSOUT=* //SYSIN DD * RUNSTATS TABLESPACE &TABNAME INDEX ALL UPDATE ACCESSPATH UPDATE SPACE /*
This example includes a standard database administration setup that might contain all the necessary DD statements for DB2 utilities.
123456789//CONFIG JOB (ACCT),'CONFIG JOB',CLASS=A // JCLLIB ORDER=(APP.JCLLIB,ENV.JCLLIB) //*-------------------------------------------------- // SET ENV=PROD //*-------------------------------------------------- // INCLUDE MEMBER=&ENV.CONFIG //*-------------------------------------------------- //STEP1 EXEC PGM=APPRUN //...
This example dynamically includes a configuration based on the environment (using member names like PRODCONFIG, TESTCONFIG, etc.).
12345678910//MYJOB JOB (ACCT),'MY JOB',CLASS=A // JCLLIB ORDER=(STD.JCLLIB) //*-------------------------------------------------- // SET JOBNAME=MYJOB //*-------------------------------------------------- //STEP1 EXEC PGM=MYPROG //... //*-------------------------------------------------- // INCLUDE MEMBER=JOBEND //*--------------------------------------------------
This includes a standard job trailer that might contain notification steps, cleanup processing, or audit logging.
12345678910//MYJOB JOB (ACCT),'MY JOB',CLASS=A // JCLLIB ORDER=(STD.JCLLIB) //*-------------------------------------------------- //STEP1 EXEC PGM=MYPROG //... //*-------------------------------------------------- // IF STEP1.RC > 0 THEN // INCLUDE MEMBER=ERRORPROC // ENDIF //*--------------------------------------------------
This conditionally includes standardized error handling procedures when a step fails.
While both JCLLIB/INCLUDE and cataloged procedures promote JCL reusability, they serve different purposes:
In practice, many organizations use both approaches together, leveraging the strengths of each:
12345678910//MYJOB JOB (ACCT),'MY JOB',CLASS=A // JCLLIB ORDER=(STD.JCLLIB) //*-------------------------------------------------- // INCLUDE MEMBER=STDSETUP //*-------------------------------------------------- //STEP1 EXEC MYPROC //... //*-------------------------------------------------- // INCLUDE MEMBER=CLEANUP //*--------------------------------------------------
Design a modular JCL framework for a data processing application using include members. The framework should support:
Create include members for:
Then create a job that uses these include members to demonstrate the framework.
Consider how you would:
Try designing this framework yourself, then compare with sample solutions in a future lesson.
1. What is the primary purpose of the JCLLIB statement?
2. Where must the JCLLIB statement be placed in a JCL job?
3. What does the INCLUDE statement do in JCL?
4. Which statement correctly uses the JCLLIB statement?
5. What happens if you do not specify a JCLLIB statement in your job?