Passing Parameters to submitted job

The CL runs online, displays a prompt screen for report options and then submits itself with the parms now containing the report options from the user's display input. It uses RTVJOBA JOBTYPE to determine if it's running online or in batch.  In either batch or online mode, depending on how the user wants to run it, it uses the parm fields to build a QRYSLT statement for an OPNQRYF and then runs a report. Not my style but it works fine. I have added a call to another program to allow the user to select a list of values as another selection for the OPNQRYF. To do this, I added a 2000 byte parm as input to the CL, initialize it to blanks (hex 40) when running online. I call my program and it returns a portion of the QRYSLT value. For example, PARM="( (&MFSEL *EQ "AB") *OR (&MFSEL EQ "KA") )" I then test if the &MFSEL field is greater than blank to determine if I need to include it in the OPNQRY QRYSLT statement which is built with " || &MFSEL || ". The problem is that when the program is run online, it works fine but on submitting itself, the remainder of my parm is filled with nulls (hex 00). I've checked it in debug at the time of the submit and it's has blanks but, when the submitted job runs it crashes on the OPNQRY. I'm thinking that it doesn't like the hex zeros. What really bothers me is, WHY is it coming in null filled? It's defined as 2000 characters in both programs. Any software heros out there that can help? Jim ps. (I hate OPNQRY)  :o)

Software/Hardware used:
CL, RPG - AS400

Answer Wiki

Thanks. We'll let you know when a new response is added.

WHY is it coming in null filled??!! It’s defined as 2000 characters in both programs.

It is irrelevant how it’s defined in either program. How is it defined when it’s sitting on a *JOBQ and therefore not inside any program? That is, how is it defined when it’s in a state outside of your programs?

That’s what happens to every submitted job. It doesn’t matter how long it takes; there is a time when it exists as nothing more than a message — a *RQS (request) message.

What is the definition of your parameter during the time that it has no definition?

Well, for a numeric value, it’s *DEC (15 5). For non-numeric, it’s *CHAR (32) by default, but will be longer out to as many non-blank positions go out to the right.

This is because a variable cannot be passed to a submitted job; only a value can be passed. A submitted job might sit on a *JOBQ for a fraction of a second or for an hour or for a week. If the *JOBQ is held, there’s no telling how long it will take. You signed off and went home — what happened to the variable definition when your interactive job ended? What difference does the called program make since it hasn’t started yet?

Because your parm is only a value and not a variable when you submit a job, the definition conforms to default definition rules. These rules haven’t changed in the past quarter century and more. See Passing parameters for one of the descriptions of defaults.

There are a couple valid ways to get around this issue.

First, SBMJOB has two possible parameters that are available to you — CMD() and RQSDTA(). Technically, when the command that you submit is a CALL command, you shouldn’t use the CMD() parameter. That parameter is intended to be used with commands that have typed parms. CALL has undefined parms. It was added to SBMJOB to facilitate prompting of defined commands.

If you must submit a CALL command, then you should use the RQSDTA() parameter. With RQSDTA(), you build the actual “request data” string. You string values together to create a *RQS message text. The resulting string should be capable of running directly on a command line. (A command line is nothing more than an interface to the request processor of your job.)

When you run a command through a command line, you can’t use variables; you must use values. Character variables that have trailing blanks and are longer than 32 characters must be enclosed in quotes and must have trailing blanks included inside the quotes. That’s exactly how they must be specified in the RQSDTA() parameter.

If the parm is 32 characters or less, it doesn’t matter because character values always get a minimum 32-byte area of memory reserved.

The other method is to define a *CMD object. One main purpose of a *CMD is to define data typing for your parameters. A *CMD is to CL what a procedure prototype is to RPG. The *CMD carries the variable definition inside of the *CMD definition.

In short, if you have values longer than 32 bytes that can have trailing blanks, you must use RQSDTA() or create a *CMD in order to pass the values as parameters for a submitted job.

Let’s say that your value in your current programming is “Abcdefg” and your variable is defined as *CHAR (2000). The first 32 bytes will contain “Abcdefg” plus 25 blanks. The called program will run in batch and try to access the next 1968 bytes of memory. Whatever was in that memory will be picked up; it will essentially be random. The memory itself will be memory that was allocated for the *JOBQ, not for your interactive program. (You might even suffer a machine-check error if it happens to be memory that is outside of the *JOBQ allocation.)

But if you build a string that includes the CALL command along with your value of 2000 bytes enclosed in quotes, and you pass the string through RQSDTA(), then the exact string will be stored on the *JOBQ. The actual trailing blanks that you passed in will cause the full 2000 bytes to be both allocated and initialized.

However, you’re currently using CMD(). That means that you aren’t supplying any quotes to mark the end of your value; you’re supplying a bare variable. The command analyzer that is inside the command-processing program of SBMJOB doesn’t have access to the variable definitions in your program. It builds a *RQS message that is based on the significant characters of your value.

You risk garbage in trailing blank positions.

Rather than passing a parm, if you don’t want the trouble of building a RQSDTA() string and you don’t want to define a *CMD, then place the value in a named data area or use the *LDA (Local Data Area). Be aware that the *LDA might unpredictably have a value already in it that’s used by some other programs elsewhere in your job. And a named data area might be referenced by jobs from two different users.

Other methods can be used, but they can have the same problems as data areas.

RQSDTA() and *CMDs are the two “correct” methods.


Discuss This Question: 2  Replies

There was an error processing your information. Please try again later.
Thanks. We'll let you know when a new response is added.
Send me notifications when members answer or reply to this question.
  • TomLiotta
    Based on your answer, I think that I could put an "X" in the last position of the 2000 bytes and strip it off after the job starts and my entire 2000 bytes will still contain a right blank fill. Consider putting your "X" (or "k" or whatever non-blank) in position 2001 instead. Your receiving program should never know it's there since it will only look at the first 2k bytes anyway. Hmmm... this is just a single program -- running interactive or batch. Still, it shouldn't matter; you can use a 2k parm coming in, but copy it to a 2k+1 variable to send it out. Maybe. You know the source better than I do. This is a 'valid' solution. You already understand why I didn't list it. Be careful to document the purpose of the extra 'delimiter' character. Tom
    125,585 pointsBadges:
  • PermanentVacationMan
    Thanks again Tom!
    30 pointsBadges:

Forgot Password

No problem! Submit your e-mail address below. We'll send you an e-mail containing your password.

Your password has been sent to:

To follow this tag...

There was an error processing your information. Please try again later.

Thanks! We'll email you when relevant content is added and updated.


Share this item with your network: