Monday, January 11, 2021

How to schedule jobs using JOBGROUP?

I was on Production support for that week and (Nope! I wasn't haunted by a ghost 👻) I was given a task of running a specific SQL SELECT query against a DB2 table in Production environment, 2 times a day, throughout that week. If the query returned rows, I had to prepare a one time job to be run in Prod. Else, do nothing. 

The project had only scheduled releases due to Agile way of working and the one time job that we ran on Prod environment was a temporary fix that we had to do until the next release, which was to occur in 2 months down the line.  

Therefore, it was imperative to run that SQL SELECT query 2 times a day by the person who is on support for that week and as we all know, Human error is inevitable - there were some misses in running the query. I already knew about JOBGROUP by then. So, I was thinking 🤔 about applying it in this scenario to prevent any misses. 

Thumbnail 😉


The main reason that JOBGROUP struck my mind was due to the fact that we had to run the SQL query at specified times. 

What's JOBGROUP 🤔?

The JOBGROUP statement in JCL allows you to group several jobs together thereby allowing you to schedule them and trigger them based on various events. JOBGROUP gives you just some basic job scheduling capabilities and it is not there to replace high-end batch scheduling softwares like Ctrl-M or CA-7. 

JOBGROUP is available from z/OS Version 2.2

JOBGROUP definition starts with a JOBGROUP statement and ends with an ENDGROUP statement. Within this boundary, we have to define the job names of all the jobs that are being grouped together. We should also specify when each job should run. 

Note: Click on the picture to get an enlarged view. 

Note that the JOBGROUP is given a name (Z01071GP) and an ENDGROUP statement is used to define the end of definition. 

Like the JOB statement, positional parameters like accounting information, programmer's name can also be specified in the JOBGROUP statement. Additionally, we can provide 2 optional parameters in the JOBGROUP statement. Those are as follows:

ERROR=(condition)  - This parameter will define the error condition that the JOBGROUP needs to evaluate after the completion of each job in the group. 

The syntax of condition remains the same as used for the IF statement in JCL. In the picture shown above, ERROR=(ABEND) is being used and ABEND indicates that an ABEND condition occurred. 

ONERROR=STOP|SUSPEND|FLUSH - This parameter will define  the action that needs to be taken when an error occurs. 

When things are put together, ERROR=(ABEND),ONERROR=STOP instructs the JOBGROUP to evaluate each job's output after its completion; if there's an ABEND, STOP submitting new jobs from that JOBGROUP. Though, jobs that are actively running are allowed to complete.

An example showing the usage of JOBGROUP: 

Let's see how we can define the job names inside a JOBGROUP

Defining job names in a JOBGROUP

Each job name within a JOBGROUP is identified by GJOB statement. Job names should be unique. AFTER is positioned after a GJOB statement and it defines the dependency to another job. WHEN defines a condition associated with the dependency. 

In the picture shown above, the jobs are defined in such a way that Z01071A job runs first; Z01071B runs after Z01071A and only WHEN the return code of Z01071A is 0. Likewise, Z01071C job should run after Z01071B and only when the RC of Z01071B is 0. 

Like AFTER statement, BEFORE and CONCURRENT can be specified to define the order in which the jobs can run.  

The next step is to add the jobs to the JCL. Yup! You need to have the JOBGROUP definition and the jobs that are part of the JOBGROUP, in the same JCL. 

The complete JCL with JOBGROUP definition and its jobs.

As you can see from the picture above, all the jobs that are defined within a JOBGROUP is added after the ENDGROUP statement. Do you notice a SCHEDULE statement included below each JOB statement? This is used to assign the scheduling attributes and in this case, it is assigning the job to your group, Z01071GP. Also note that I've used IDCAMS to set the MAXCC to 16 in the second job. This is done deliberately and the reason for doing that, you'll witness shortly. It's time ⏰ to watch things in action. Let's see the outcome of this JCL after submission.

The JOBGROUP and its jobs are submitted.

Tada! 🧞 Just ignore the order the messages are being displayed. Z01071A and Z01071B jobs ran (one after another) and completed with MAXCC 0 👏. But, what happened to the third job? Z01071C job was flushed as the return code from Z01071B was not zero 😑. As per the definition in the JOBGROUP, Z01071C should run only when Z01071B job issues a return code of 0

I hope you are now better off with JOBGROUP. Hang on and read a little bit as I'm about to unearth another useful feature of JOBGROUP i.e., the HOLDUNTL parameter.

How I used JOBGROUP at my site to prevent misses in running the SQL query? 

The requirement was to run the SQL SELECT query 2 times in a day through out that week. I defined a JOBGROUP with 10 jobs in it. Each job had the following steps:
Step 1: a DB2 UNLOAD step with the SQL SELECT query which would write the rows to an output dataset. 
Step 2: IDCAMS step to check for emptiness of the output file. RC=0 if the file is not empty. Else, RC=4. 
Step 3/4: Email step runs based on the return code from Step 2. If RC=0, an email is sent from Mainframe to folks who are on support for that week, notifying that there are rows to update in prod.   

All the 10 jobs were scheduled to run at a pre-defined time. Let me show you how we can do that. 
The SCHEDULE statement of the first job now have the HOLDUNTL parameter with which we can set a job to specify the date and time until which the job should be held. 

After submitting the JOBGROUP, the status of the first job, Z01071A shows HOLD, in spool.

If you traverse across columns from left to right, you'll find a column 'HoldUntil' which holds the Date and time we passed in the JCL

The job are exactly fired at the specified date and time. 


More about HOLDUNTL parameter and its syntax can be found here.

In my scenario, I added HOLDUNTL parameter in all the 10 jobs, with the date and time spanning across that whole week. 

Now, folks who were on support only had to monitor their inbox and when they received an email notification, saying there are rows on Prod table that needs a fix, they had to take an action to run the one-time job on Prod.  JCL's JOBGROUP feature was counted on running the SQL query without a miss 😃.

All of these might sound like automating stuff . True, but only up to certain extent. We still needed manual intervention to run the one-time prod job with help from another team. 

Something is better than nothing!

Thanks for reading! Should you have any questions or suggestions, please drop them in the Comments section below.


References: IBM Knowledge Center
Screenshot courtesy: Screenshots were taken from MTM2020 system. 


No comments:

Post a Comment