MainframeMaster

JCL Tutorial

JCL Execution Groups

Progress0 of 0 lessons

What are Execution Groups?

Execution Groups in JCL are logical collections of job steps that are treated as a unit for conditional processing. They provide a powerful way to organize complex job flows and implement sophisticated error handling strategies.

Unlike individual job steps, execution groups allow you to apply conditional logic to multiple steps at once, making it easier to control job flow and implement recovery procedures in complex batch applications.

Creating Execution Groups

Execution groups are defined using the IF/THEN/ELSE/ENDIF construct or by enclosing a set of steps within CNTL/ENDCNTL statements. Each approach offers different capabilities and is suited to different situations.

Method 1: Using IF/THEN/ELSE/ENDIF

This approach allows you to conditionally execute multiple steps based on test conditions.

jcl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//MYJOB JOB (ACCT),'MY NAME',CLASS=A // IF (RC=0) THEN /* IF the return code from previous step is 0 */ //* ----- BEGINNING OF GROUP ----- //STEP1 EXEC PGM=PROGRAM1 //...DD statements... //STEP2 EXEC PGM=PROGRAM2 //...DD statements... // ENDIF /* END OF GROUP */ // IF (RC >= 4) THEN /* IF return code is 4 or greater */ //* ----- BEGINNING OF ERROR HANDLING GROUP ----- //ERRLOG EXEC PGM=ERRLOGPGM //...DD statements... //NOTIFY EXEC PGM=SENDMAIL //...DD statements... // ENDIF /* END OF GROUP */

Method 2: Using CNTL/ENDCNTL

The CNTL/ENDCNTL approach is particularly useful when working with utility programs that support control groups, such as IDCAMS.

jcl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//MYJOB JOB (ACCT),'MY NAME',CLASS=A //STEP1 EXEC PGM=IDCAMS //SYSPRINT DD SYSOUT=* //SYSIN DD * DELETE dataset.name SCRATCH PURGE SET MAXCC=0 /* //STEP2 EXEC PGM=IDCAMS //SYSPRINT DD SYSOUT=* //SYSIN DD * /* Beginning of control group */ IF LASTCC=0 THEN DO DEFINE CLUSTER(...) - DATA(...) - INDEX(...) END ELSE DO /* Error handling within control group */ SET MAXCC=8 END /*

Common Use Cases for Execution Groups

1. Coordinated Error Handling

Group error handling steps that should execute together when errors occur. This ensures that all required recovery actions take place.

jcl
1
2
3
4
5
6
7
8
// IF (RC >= 8) THEN //BACKUP EXEC PGM=BAKUPPGM //... //RESTORE EXEC PGM=RESTPGM //... //NOTIFY EXEC PGM=MAILPGM //... // ENDIF

2. Conditional Processing Paths

Execute different groups of steps based on the outcome of previous steps, creating branching logic in your job.

jcl
1
2
3
4
5
6
7
8
9
10
11
// IF (RC = 0) THEN //NORMAL EXEC PGM=NORMPRC //... //UPDTMST EXEC PGM=UPDATE //... // ELSE //ERRPROC EXEC PGM=ERRORPRC //... //LOGFAIL EXEC PGM=LOGFAIL //... // ENDIF

3. Environment-Specific Processing

Execute different groups of steps based on environmental variables, such as system ID or date.

jcl
1
2
3
4
5
6
7
8
9
10
11
// SET SYSID=&SYSUID // IF (&SYSID = 'PROD') THEN //PRODSTEP EXEC PGM=PRODPGM //... // ELSE IF (&SYSID = 'TEST') THEN //TESTSTEP EXEC PGM=TESTPGM //... // ELSE //DEVSTEP EXEC PGM=DEVPGM //... // ENDIF

Nesting Execution Groups

Execution groups can be nested within each other to create complex conditional logic. This allows for sophisticated job flows that can handle a variety of conditions and scenarios.

jcl
1
2
3
4
5
6
7
8
9
10
11
12
13
// IF (RC = 0) THEN //STEP1 EXEC PGM=PROGRAM1 //... // IF (DSN='PROD.MASTER') THEN //PRODPROC EXEC PGM=PRODPGM //... // ELSE //TESTPROC EXEC PGM=TESTPGM //... // ENDIF //STEP2 EXEC PGM=PROGRAM2 //... // ENDIF

You can nest up to 15 levels of IF statements in z/OS JCL, though keeping nesting to a reasonable depth improves readability and maintainability.

Execution Groups vs Individual Conditions

FeatureExecution Groups (IF/THEN/ELSE)Individual COND Parameters
ScopeMultiple steps as a unitSingle step only
ReadabilityMore explicit, easier to followMore compact but can be harder to follow
FlexibilitySupports complex branching logicLimited to pre-defined conditions
ImplementationAdded in later versions of z/OSTraditional approach, available in all versions

Best Practices for Execution Groups

  • Keep it readable: Use comments to clearly mark the beginning and end of execution groups, especially in complex JCL.
  • Avoid excessive nesting: While nesting is supported, deep nesting can make JCL difficult to maintain. Try to limit nesting to 3-4 levels.
  • Group related steps: Put logically related steps in the same execution group to make the job flow clearer.
  • Include error handling: Use ELSE clauses to handle error conditions explicitly, rather than letting steps fail silently.
  • Document conditions: Add comments that explain the purpose of each condition, especially for complex business rules.

Execution Groups Exercises

Exercise 1: Create a Basic Execution Group

Write JCL that uses IF/THEN/ELSE to create an execution group that runs steps STEP1 and STEP2 only if a previous step ended with RC=0, otherwise runs ERRSTEP.

Exercise 2: Nested Execution Groups

Create JCL with nested execution groups that implement the following logic: If STEP1 is successful (RC=0), run STEP2. If STEP2 is successful, run STEP3. If STEP2 fails (RC> 0), run ERROR1. If STEP1 fails, run ERROR2.

Exercise 3: Environment-Based Execution

Write JCL that checks a symbolic parameter ENVIRONMENT and runs different execution groups based on whether it's set to PROD, TEST, or DEV.

Examples of Complex Execution Groups

Data Processing Pipeline with Error Handling

jcl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
//DATAJOB JOB (ACCT),'DATA PIPELINE',CLASS=A,MSGCLASS=X //* --------- EXTRACTION PHASE --------- //EXTRACT EXEC PGM=DATAXTRCT //SYSOUT DD SYSOUT=* //INPUT DD DSN=PROD.SOURCE.DATA,DISP=SHR //OUTPUT DD DSN=WORK.EXTRACT.DATA,DISP=(,PASS) //* --------- CONDITIONAL PROCESSING BASED ON EXTRACTION --------- // IF (EXTRACT.RC = 0) THEN //* ----- NORMAL PROCESSING PATH ----- //VALIDATE EXEC PGM=DATAVAL //SYSOUT DD SYSOUT=* //INPUT DD DSN=WORK.EXTRACT.DATA,DISP=(OLD,PASS) //OUTPUT DD DSN=WORK.VALID.DATA,DISP=(,PASS) //* // IF (VALIDATE.RC = 0) THEN //PROCESS EXEC PGM=DATAPROC //SYSOUT DD SYSOUT=* //INPUT DD DSN=WORK.VALID.DATA,DISP=(OLD,DELETE) //OUTPUT DD DSN=PROD.OUTPUT.DATA,DISP=(NEW,CATLG) // ELSE //VALIDERR EXEC PGM=ERRLOGGER //SYSOUT DD SYSOUT=* //INPUT DD DSN=WORK.VALID.DATA,DISP=(OLD,DELETE) //ERRFILE DD DSN=PROD.ERROR.LOG,DISP=MOD //MESSAGE DD * DATA VALIDATION FAILED - PROCESS TERMINATED /* // ENDIF //* // ELSE //* ----- ERROR HANDLING PATH ----- //EXTRERR EXEC PGM=ERRLOGGER //SYSOUT DD SYSOUT=* //ERRFILE DD DSN=PROD.ERROR.LOG,DISP=MOD //MESSAGE DD * DATA EXTRACTION FAILED - PROCESS TERMINATED /* // ENDIF //* //* --------- NOTIFICATION ALWAYS RUNS --------- //NOTIFY EXEC PGM=NOTIFYPGM //SYSOUT DD SYSOUT=* //MSGFILE DD DSN=PROD.MESSAGES,DISP=MOD

This example shows a data pipeline with nested execution groups that handle both normal processing and error conditions at different stages.

Frequently Asked Questions

Test Your Knowledge

1. What are JCL Execution Groups primarily used for?

  • To group statements for better formatting
  • To logically organize job steps that should be treated as a unit for conditional processing
  • To reduce JCL coding errors
  • To allocate system resources more efficiently

2. Which construct can be used to create execution groups in JCL?

  • GROUP/ENDGROUP
  • IF/THEN/ELSE/ENDIF
  • BEGIN/END
  • EXEC GROUP

3. What is the maximum nesting level supported for IF statements in z/OS JCL?

  • 5 levels
  • 10 levels
  • 15 levels
  • No limit

4. What happens to steps inside an IF/THEN block when the condition evaluates to false?

  • They execute with a warning message
  • They are skipped and not executed
  • They execute but with a return code of 4
  • They execute with default parameters

5. Which of the following is NOT a recommended best practice for execution groups?

  • Use comments to clearly mark beginning and end of groups
  • Keep nesting to a reasonable depth
  • Avoid using ELSE clauses to maintain simplicity
  • Group logically related steps together