Job dependencies are relationships between separate JCL jobs where the execution of one job depends on the status or output of another job. Unlike step dependencies that occur within a single job, job dependencies manage relationships between independent jobs that may run at different times or even on different systems.
Job dependencies are essential for creating reliable batch processing systems, where complex business processes require multiple jobs to be executed in a specific sequence, often with conditions determining whether dependent jobs should run.
Dependency Type | Description | Common Use Cases |
---|---|---|
Successful Completion | Job B runs only if Job A completes successfully (RC = 0) | Sequential processing steps like extract → transform → load |
Completion (Any Status) | Job B runs after Job A completes, regardless of its success or failure | Cleanup or notification jobs that must run regardless of main job outcome |
Conditional | Job B runs only if Job A completes with a specific return code or range | Error recovery jobs that run only when the main job fails with specific errors |
Multiple Predecessors | Job C runs only after Jobs A and B have both completed successfully | Consolidation jobs that merge outputs from multiple source jobs |
Time-Based | Job B runs at a specific time, but only if Job A has completed | End-of-day processing that waits for daily transaction jobs |
Resource-Based | Job B runs only when a specific dataset or resource is available | Jobs that process files received from external systems |
There are several ways to implement job dependencies in a mainframe environment. The method you choose depends on your available tools, your organization's standards, and the complexity of your dependency requirements.
Enterprise job schedulers like CA-7, Control-M, TWS (IBM Workload Scheduler), or Zeke provide robust facilities for defining and managing job dependencies.
CA-7 uses a database to define job dependencies. Here's a simplified definition:
12345JOBDEF JOB=DAILY01,DAYS=(ALL),LEAD=0 REQ JOB=DAILY01,DAYS=(ALL),LEAD=0 REQ JOB=DAILY02,PRED=(DAILY01(0)),DAYS=(ALL),LEAD=0 REQ JOB=DAILY03,PRED=(DAILY01(0),DAILY02(0)),DAYS=(ALL),LEAD=0 REQ JOB=DAILYFAIL,PRED=(DAILY02(>0)),DAYS=(ALL),LEAD=0
This defines DAILY01 as the first job, DAILY02 runs when DAILY01 completes with RC=0, DAILY03 runs when both DAILY01 and DAILY02 complete with RC=0, and DAILYFAIL runs when DAILY02 has a non-zero return code.
Jobs can be made dependent on the successful creation and availability of datasets. This approach leverages the operating system's dataset protection mechanisms.
Job A creates a dataset that Job B needs:
1234567//JOBA JOB (ACCT),'CREATE DATASET',CLASS=A //STEP1 EXEC PGM=PROGRAM1 //OUTPUT DD DSN=MY.CRITICAL.DATA,DISP=(NEW,CATLG,DELETE) ... //JOBB JOB (ACCT),'USE DATASET',CLASS=A //STEP1 EXEC PGM=PROGRAM2 //INPUT DD DSN=MY.CRITICAL.DATA,DISP=SHR
If JOBA fails to create MY.CRITICAL.DATA, JOBB will fail when it tries to access it. This creates an implicit dependency.
A trigger dataset is a special file created by one job to signal completion, which another job checks for before starting.
Job A creates a trigger dataset:
1234//JOBA JOB (ACCT),'CREATE TRIGGER',CLASS=A //STEP1 EXEC PGM=IEFBR14 //TRIGGER DD DSN=TRIGGER.JOBA.COMPLETE,DISP=(NEW,CATLG), // SPACE=(TRK,1)
Job B checks for the trigger dataset:
12345678910111213//JOBB JOB (ACCT),'CHECK TRIGGER',CLASS=A //CHKTRG EXEC PGM=IDCAMS //SYSPRINT DD SYSOUT=* //SYSIN DD * IF LISTCAT ENT('TRIGGER.JOBA.COMPLETE') THEN DO SET MAXCC=0 END ELSE DO SET MAXCC=8 /* Trigger not found, signal error */ END /* //STEP1 EXEC PGM=PROGRAM2,COND=(0,NE,CHKTRG) //... DD statements ...
GDGs can be used to manage dependencies based on dataset generations.
Job A creates a new generation:
1234//JOBA JOB (ACCT),'CREATE GDG',CLASS=A //STEP1 EXEC PGM=PROGRAM1 //OUTPUT DD DSN=MY.GDG.DATASET(+1),DISP=(NEW,CATLG,DELETE) ...
Job B uses the latest generation:
1234//JOBB JOB (ACCT),'USE GDG',CLASS=A //STEP1 EXEC PGM=PROGRAM2 //INPUT DD DSN=MY.GDG.DATASET(0),DISP=SHR ...
Jobs can be submitted but held until an operator releases them, often based on the completion of other jobs.
123//JOBB JOB (ACCT),'HELD JOB',CLASS=A,TYPRUN=HOLD //STEP1 EXEC PGM=PROGRAM2 //... DD statements ...
Job B is submitted but remains in HOLD status. After Job A completes, an operator can issue a command to release Job B:
1$A JOBB
This example shows a complex batch processing flow with multiple dependencies:
12345JOBDEF JOB=EXTRACT,TIME=20:00,DAYS=(MO-FR) REQ JOB=PROCESS,PRED=(EXTRACT(0)),DAYS=(MO-FR) REQ JOB=REPORT,PRED=(PROCESS(0)),DAYS=(MO-FR) REQ JOB=ARCHIVE,PRED=(REPORT(0)),DAYS=(MO-FR) REQ JOB=NOTIFY,PRED=(PROCESS(>0)),DAYS=(MO-FR)
Design a job dependency solution where JOBB should run only if JOBA completes successfully. Implement this using dataset disposition.
Create JCL for two jobs where the second job uses IDCAMS to check for the existence of a trigger dataset before proceeding.
Design a job scheduler dependency setup for a scenario where Job D depends on both Job A and Job B completing successfully, while Job C depends only on Job A. Job E runs if either Job C or Job D fails.
Automating job submission based on time and dependencies
How dataset disposition affects job dependencies
Managing time constraints for dependent job streams
How procedures can be used in job dependency chains
Handling failures in job dependency networks
1. Which of the following is NOT a common method for implementing job dependencies?
2. What is a trigger dataset?
3. Which statement about job dependencies is FALSE?
4. What is the purpose of TYPRUN=HOLD in job dependencies?
5. Which of these is a benefit of using a job scheduler for dependencies?