A JOBGROUP makes a set of related jobs and their sequencing rules visible to JES2 as a single orchestration object. Instead of asking each job to discover its own dependencies, the orchestration is defined first and the real jobs are then associated to that group.
This article is deliberately practical. It defines a small JOBGROUP, submits the associated jobs in the same input stream, and validates a simple flow:
JGAruns firstJGBandJGCrun afterJGAJGDruns only afterJGBandJGC
1. Lab goals
By the end of the lab you should be able to:
- Explain what a JES2
JOBGROUPis - Distinguish
JOBGROUPfromSCHEDULE AFTER/BEFORE/DELAY=YES - Define a native job group with
GJOBandAFTER - Associate jobs to the group with
SCHEDULE JOBGROUP=... - Understand the main restrictions of the group-definition block
2. Required environment
For this lab, you need:
- z/OS 2.2 or later
- JES2
- TSO/ISPF access with permission to submit stacked jobs
- SDSF access, or an equivalent monitor for JES2 job and job-group status
Important prerequisites:
- JES2 job groups must be configured and active at the system level (JES2
GRPDEF) - The installation must be in the JES2 activation mode required for job groups. All members must be running z/OS 2.2 or later for the required activation mode
If the lab fails immediately at submission time with JES2 job-group errors, ask the system programmer to verify job-group activation before continuing.
3. What JOBGROUP gives you
A JES2 job group is a native orchestration definition inside the submitted input stream. It describes:
- The jobs that belong to the group
- The dependency rules between them
- The overall orchestration object that JES2 monitors
The main statements are:
| Statement | Purpose |
|---|---|
JOBGROUP | Starts the job-group definition |
GJOB | Defines one job inside the group |
JOBSET | Defines a named set of jobs |
SJOB | Defines one job inside a job set |
AFTER | Indicates that the current job or set must wait for another job or set |
BEFORE | Indicates that the current job or set must precede another job or set |
CONCURRENT | Indicates that the jobs must run at the same time |
ENDSET | Ends the definition of a job set |
ENDGROUP | Ends the definition of the job group |
To associate a submitted job to a job group, the job itself uses:
// SCHEDULE JOBGROUP=group-name4. Why JOBGROUP is stronger than lightweight dynamic sequencing
In the SCHEDULE AFTER/BEFORE/DELAY=YES model, each job discovers its dependencies dynamically as jobs enter and leave JES2. That is useful, but it requires some operational care because of the way JES2 implements it: the dependency is resolved in a distributed, dynamic way, job by job, based on the current state of the JES2 queues.
JOBGROUP changes the model:
- The orchestration object is created first
- The jobs register to that group
- JES2 controls the flow from the group definition itself
That is why IBM explicitly notes that JOBGROUP avoids the problems seen in lightweight dynamic sequencing (SCHEDULE AFTER/BEFORE/DELAY=YES model).
5. Important restrictions before coding the lab
The job-group block is not ordinary JCL. There are several restrictions:
- Only JES2 execution control statements are allowed between
JOBGROUPandENDGROUP - JECL statements such as
/*...are not allowed - In-stream data is not allowed
- Symbols are not allowed
- Ordinary
JOB,EXEC, orDDstatements are not allowed inside the group-definition block itself
The real batch jobs come after the group definition and are associated to it with SCHEDULE JOBGROUP=....
6. The orchestration we will build
This lab uses the following native dependency graph:
JGA
├── JGB
└── JGC
└──
JGDMore precisely:
JGBruns afterJGAJGCruns afterJGAJGDruns afterJGBandJGC
The jobs themselves will perform simple data-set actions so you can validate that the sequence really happened.
7. Create the complete input stream
Create a member such as JGLAB with the following content:
//MYJG JOBGROUP
//JGA GJOB
//JGB GJOB
// AFTER NAME=JGA,WHEN=(RC=0)
//JGC GJOB
// AFTER NAME=JGA,WHEN=(RC=0)
//JGD GJOB
// AFTER NAME=(JGB,JGC)
//MYJGD ENDGROUP
//*
//JGA JOB ,'JOBGROUP LAB',CLASS=A,MSGCLASS=X,NOTIFY=&SYSUID
// SCHEDULE JOBGROUP=MYJG
//STEP1 EXEC PGM=IEFBR14
//OUTA DD DSN=&SYSUID..JGDEMO.A,
// DISP=(NEW,CATLG,DELETE),
// SPACE=(TRK,(1,1)),
// DCB=(RECFM=FB,LRECL=80,BLKSIZE=0)
//*
//JGB JOB ,'JOBGROUP LAB',CLASS=A,MSGCLASS=X,NOTIFY=&SYSUID
// SCHEDULE JOBGROUP=MYJG
//STEP1 EXEC PGM=IEFBR14
//OUTB DD DSN=&SYSUID..JGDEMO.B,
// DISP=(NEW,CATLG,DELETE),
// SPACE=(TRK,(1,1)),
// DCB=(RECFM=FB,LRECL=80,BLKSIZE=0)
//*
//JGC JOB ,'JOBGROUP LAB',CLASS=A,MSGCLASS=X,NOTIFY=&SYSUID
// SCHEDULE JOBGROUP=MYJG
//STEP1 EXEC PGM=IEFBR14
//OUTC DD DSN=&SYSUID..JGDEMO.C,
// DISP=(NEW,CATLG,DELETE),
// SPACE=(TRK,(1,1)),
// DCB=(RECFM=FB,LRECL=80,BLKSIZE=0)
//*
//JGD JOB ,'JOBGROUP LAB',CLASS=A,MSGCLASS=X,NOTIFY=&SYSUID
// SCHEDULE JOBGROUP=MYJG
//STEP1 EXEC PGM=IDCAMS
//SYSPRINT DD SYSOUT=*
//SYSIN DD *
DELETE '&SYSUID..JGDEMO.A'
IF LASTCC = 8 THEN SET MAXCC = 0
DELETE '&SYSUID..JGDEMO.B'
IF LASTCC = 8 THEN SET MAXCC = 0
DELETE '&SYSUID..JGDEMO.C'
IF LASTCC = 8 THEN SET MAXCC = 0
/*Submit the member once so the job-group definition and the associated jobs enter JES2 together.
8. What to observe after submission
In SDSF, or in your equivalent JES2 monitor, look for:
- The four jobs
JGA,JGB,JGC, andJGD - The job-group object
JGDEMO - The execution order
Expected behavior:
JGAbecomes eligible firstJGBandJGCremain dependent onJGAJGDremains dependent onJGBandJGC- After
JGAends withRC=0,JGBandJGCbecome eligible - After both of them finish,
JGDbecomes eligible
Expected functional result:
JGA,JGB,JGC, andJGDfinish normallyJGDdeletes the three data sets created by the previous jobs
This confirms that the group sequencing was enforced correctly.
9. Why the WHEN=(RC=0) condition matters
The dependency from JGA to JGB and JGC is not just “after JGA”. It is:
AFTER NAME=JGA,WHEN=(RC=0)This means the dependency is satisfied only when JGA ends with RC=0.
This is the practical value:
- You can build orchestration rules based on completion quality
- A parent job that finishes badly does not have to release the rest of the flow
In larger group designs, this is where WHEN=, ACTION= and OTHERWISE= become operationally important.
10. How JOBSET fits in
This lab uses only GJOB because it is the simplest way to introduce the function, but JOBSET is the next capability to learn once the graph starts getting larger.
The purpose of JOBSET is to allow several jobs to be treated as a single named orchestration unit inside the job group. Instead of writing dependencies against individual jobs one by one, you define a set and then refer to that set by name.
In practice, JOBSET is useful when:
- Several jobs belong to the same logical phase of the flow
- A successor should wait for a complete bundle of jobs, not just one job
- You want the dependency model to describe business phases rather than only isolated jobs
- You want flush behavior to be controlled at the set level with
FLUSHTYP
Think about the distinction like this:
| Construct | Best use |
|---|---|
GJOB | A small direct graph where each job is referenced individually |
JOBSET + SJOB | A larger flow where several jobs should be treated as one named phase |
10.1 What problem JOBSET solves
Suppose you have three extract jobs:
EXTAEXTBEXTC
and then one consolidation job:
LOAD1
Without JOBSET, the dependency is expressed job by job:
//LOAD1 GJOB
// AFTER NAME=(EXTA,EXTB,EXTC)This is still valid, but the intent remains only implicit. JES2 sees three individual parent jobs, not a named phase.
With JOBSET, you can model that phase explicitly:
//EXTRSET JOBSET
//EXTA SJOB
//EXTB SJOB
//EXTC SJOB
//EXTRSET ENDSET
//LOAD1 GJOB
// AFTER NAME=EXTRSETNow the dependency reads more naturally:
- First the extraction set
- Then the load job
That is the main value of JOBSET: a clearer orchestration structure.
10.2 When JOBSET is more useful than GJOB
JOBSET becomes useful when the graph stops being “just a few jobs” and starts having reusable or recognisable phases.
Typical examples:
- A parallel extract phase followed by a merge phase
- Several validation jobs followed by a publish job
- A family of regional jobs followed by one global summary
- A set of preparatory jobs that must all finish before the next phase starts
At that point, JOBSET improves readability because:
- The dependency list becomes shorter
- The group definition starts to reflect the real phases of the process
- Later maintenance becomes easier when a new job has to be added to the set
10.3 Why FLUSHTYP matters
JOBSET also introduces an important capability that plain GJOB does not provide as cleanly: set-level flush semantics.
IBM documents FLUSHTYP on JOBSET as:
ALLFLUSHANYFLUSH
This controls what happens to jobs in the set when parent jobs are flushed.
Practical meaning:
ALLFLUSH: flush a job in the set only if all parent jobs are flushedANYFLUSH: flush a job in the set if any parent job is flushed
This matters when the set represents a real phase and you need consistent failure or bypass behavior for the whole phase.
10.4 Practical rule of thumb
Use GJOB when:
- The graph is small
- Job-by-job dependencies are still easy to read
- You are introducing the function for the first time
Use JOBSET when:
- Several jobs form a single logical phase
- A later job depends on the phase as a whole
- You need flush behavior at the set level
- The orchestration is becoming hard to read as a flat list of
GJOBnames
11. How this differs from the basic scheduling capabilities
The basic scheduling capabilities cover:
HOLDUNTLAFTERBEFOREDELAY=YES
They are still useful, but they work as lighter scheduling controls per job.
Job groups are different:
- The orchestration object exists first as
JOBGROUP - The jobs only associate afterwards with
SCHEDULE JOBGROUP=... - JES2 manages the dependency network from that native group definition
11. Cleanup
In this version of the lab, no additional cleanup job is needed. The final job JGD already removes the three data sets created by JGA, JGB, and JGC.
If you want to repeat the lab immediately after a successful run, it is safer to create a second variant of the member with a different JOBGROUP name and different job names, because JES2 may still retain the metadata of the previous group for some time.
Summary
If you need native orchestration inside JES2, JOBGROUP is the stronger answer.
The practical pattern is:
1. First define the orchestration with JOBGROUP, GJOB, AFTER, and related statements 2. Then submit the real jobs with:
// SCHEDULE JOBGROUP=group-nameThis gives JES2 a native dependency graph instead of asking each job to discover its own dependencies dynamically.