Pyxis Logo
Home / IBM Training / Technical article

JES2 Job Groups in Practice

A hands-on lab that defines a JES2 JOBGROUP, associates batch jobs to the group with SCHEDULE JOBGROUP=, and validates native multi-job sequencing without an external scheduler.

18 min read
Published 2026-05-18
Pyxis editorial team
Rate this article
Average rating: Not rated
Your rating: Not rated
visualizations: 0
Dark abstract illustration of JES2 job groups with grouped nodes and branching dependencies

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:

  • JGA runs first
  • JGB and JGC run after JGA
  • JGD runs only after JGB and JGC

1. Lab goals

By the end of the lab you should be able to:

  • Explain what a JES2 JOBGROUP is
  • Distinguish JOBGROUP from SCHEDULE AFTER/BEFORE/DELAY=YES
  • Define a native job group with GJOB and AFTER
  • 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:

StatementPurpose
JOBGROUPStarts the job-group definition
GJOBDefines one job inside the group
JOBSETDefines a named set of jobs
SJOBDefines one job inside a job set
AFTERIndicates that the current job or set must wait for another job or set
BEFOREIndicates that the current job or set must precede another job or set
CONCURRENTIndicates that the jobs must run at the same time
ENDSETEnds the definition of a job set
ENDGROUPEnds the definition of the job group

To associate a submitted job to a job group, the job itself uses:

//         SCHEDULE JOBGROUP=group-name

4. 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 JOBGROUP and ENDGROUP
  • JECL statements such as /*... are not allowed
  • In-stream data is not allowed
  • Symbols are not allowed
  • Ordinary JOB, EXEC, or DD statements 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
    └──
     JGD

More precisely:

  • JGB runs after JGA
  • JGC runs after JGA
  • JGD runs after JGB and JGC

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, and JGD
  • The job-group object JGDEMO
  • The execution order

Expected behavior:

  • JGA becomes eligible first
  • JGB and JGC remain dependent on JGA
  • JGD remains dependent on JGB and JGC
  • After JGA ends with RC=0, JGB and JGC become eligible
  • After both of them finish, JGD becomes eligible

Expected functional result:

  • JGA, JGB, JGC, and JGD finish normally
  • JGD deletes 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:

ConstructBest use
GJOBA small direct graph where each job is referenced individually
JOBSET + SJOBA larger flow where several jobs should be treated as one named phase

10.1 What problem JOBSET solves

Suppose you have three extract jobs:

  • EXTA
  • EXTB
  • EXTC

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=EXTRSET

Now 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:

  • ALLFLUSH
  • ANYFLUSH

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 flushed
  • ANYFLUSH: 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 GJOB names

11. How this differs from the basic scheduling capabilities

The basic scheduling capabilities cover:

  • HOLDUNTL
  • AFTER
  • BEFORE
  • DELAY=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-name

This gives JES2 a native dependency graph instead of asking each job to discover its own dependencies dynamically.

Useful IBM documentation

More in this area

More in this area

Back to training
Article category

z/OS Articles

Browse all technical articles for z/OS in one category page.

Open category z/OS