Topic
  • 6 replies
  • Latest Post - ‏2013-02-26T19:03:19Z by nick_tn
SystemAdmin
SystemAdmin
6195 Posts

Pinned topic How to submit an iSeries program in EGL?

‏2013-02-13T07:09:01Z |
Hi all,

To call an iSeries program we define a linkage option in the project's build descriptor, and pass it's parameters by passing a BasicRecord on the call statement.
Works like a sunshine.
Now we would like to run this same program in batch. Is there a typical EGL way to submit it to the iSeries?

Thanks,
Guus
Updated on 2013-02-26T19:03:19Z at 2013-02-26T19:03:19Z by nick_tn
  • markevans
    markevans
    2815 Posts

    Re: How to submit an iSeries program in EGL?

    ‏2013-02-13T13:53:45Z  
    Guus,

    A couple of questions (pardon me if I ask something that should be obvious in the i world):

    a.) do you mean calling a program that is running under the equivalent of SBMJOB command you might do from a command line?

    b.) How would you do this if calling this program from an RPG/COBOL program running on system i?

    c.) How would you expect the data to be passed in?

    d.) Do you expect this to be an synchronous call meaning you want to wait and get input back from the call (in the passed record)? Or just submit it and come back...but the end of the job is then separate?

    I don't know of a way to submit specifically to batch, but I am thinking that the use of something like QCMDEXC may be the answer, where your input to that is the SBMJOB command. But I am not sure how to pass the data except as single text string as a PARM within a SBMJOB command.
  • SystemAdmin
    SystemAdmin
    6195 Posts

    Re: How to submit an iSeries program in EGL?

    ‏2013-02-13T20:48:52Z  
    • markevans
    • ‏2013-02-13T13:53:45Z
    Guus,

    A couple of questions (pardon me if I ask something that should be obvious in the i world):

    a.) do you mean calling a program that is running under the equivalent of SBMJOB command you might do from a command line?

    b.) How would you do this if calling this program from an RPG/COBOL program running on system i?

    c.) How would you expect the data to be passed in?

    d.) Do you expect this to be an synchronous call meaning you want to wait and get input back from the call (in the passed record)? Or just submit it and come back...but the end of the job is then separate?

    I don't know of a way to submit specifically to batch, but I am thinking that the use of something like QCMDEXC may be the answer, where your input to that is the SBMJOB command. But I am not sure how to pass the data except as single text string as a PARM within a SBMJOB command.
    Hi Mark,

    Below the answers to your questions:
    a) yes. something like SBMJOB CMD(call pgm1 parm('O' '')).
    b) You would also have to compose the parm-string 'manually', or perhaps passing a pointer to the parm-datastructure might make things easier(?).
    c) Similar to calling a pgm-object directly from EGL, by passing a record to the submit command.
    d) I would expect this to be an asynchronous call. So, submitting the program to batch (adding it to the jobqueue) and continue processing the EGL program without waiting for completion.

    We had already tried the QCMDEXEC like you suggested, amongst some other options. But the drawback of these techniques is passing the parms in a string, like you mentioned. You will have to build this 'manually'. This means for example converting numeric values to packed values, if the program's plist demands this.
    Since calling an RPG program (or any other program-object) from EGL directly is easily done, we would think that a similar approach could be used in submitting a program-object. It would be quite nice if EGL provided a way to do so, otherwise we just have to build the parm-string ourselves.

    Guus
  • markevans
    markevans
    2815 Posts

    Re: How to submit an iSeries program in EGL?

    ‏2013-02-15T21:18:28Z  
    Hi Mark,

    Below the answers to your questions:
    a) yes. something like SBMJOB CMD(call pgm1 parm('O' '')).
    b) You would also have to compose the parm-string 'manually', or perhaps passing a pointer to the parm-datastructure might make things easier(?).
    c) Similar to calling a pgm-object directly from EGL, by passing a record to the submit command.
    d) I would expect this to be an asynchronous call. So, submitting the program to batch (adding it to the jobqueue) and continue processing the EGL program without waiting for completion.

    We had already tried the QCMDEXEC like you suggested, amongst some other options. But the drawback of these techniques is passing the parms in a string, like you mentioned. You will have to build this 'manually'. This means for example converting numeric values to packed values, if the program's plist demands this.
    Since calling an RPG program (or any other program-object) from EGL directly is easily done, we would think that a similar approach could be used in submitting a program-object. It would be quite nice if EGL provided a way to do so, otherwise we just have to build the parm-string ourselves.

    Guus
    Guus,

    Unfortunately, I don't know of any way to pass the record to the PARM within the SBMJOB as a pointer to the record the called program expects. I looked at the JT400 toolkit and I did not even see a class/method to submit a job which would make implementing something like this very hard. If you find one, then maybe an external type could be used for now.

    In the meantime, I can think of a couple of approaches which may work (have to be tested). Both assume the called program expects a structure of fields.

    a.) Write another called program which is called on the i5 and receives the parm and then it does the QCMDEXC and concatenates one long CHAR field to the command string that is being built. In other words if you have a record something like this:

    10 topfield char(80)
    20 chafield char(20);
    20 packfield decimal(5); // 3 bytes
    20 NUMfield num(7);
    20 cha2field char(50);

    when you build your command you could just use TOPFIELD. While the characters would not be readable, I would think the SBMJOB (Call pgm(mypgm) PARM(topfield_contents)) would just be passed as is.

    b.) One of the things you have to be concerned with on the remote calls to the i5 is the data conversion. The above approach lets the record layout determine the conversions that are needed on the call itself. However, you can tell EGL not to do conversion and convert the data prior and after the call using the syslib.convert. Then "insert" the data into the command using a similar technique to item a.) where you build the command using the "topfield" with data that has already been converted according to its datatype. then on the call it will just be passed as a byte stream that the receiving program will break back out based on the structure. To tell the communication layer to not convert it just don't specify a conversion table.

    Again, I have not tested any of this, so use the ideas at your own risk.
  • SystemAdmin
    SystemAdmin
    6195 Posts

    Re: How to submit an iSeries program in EGL?

    ‏2013-02-18T04:31:20Z  
    • markevans
    • ‏2013-02-15T21:18:28Z
    Guus,

    Unfortunately, I don't know of any way to pass the record to the PARM within the SBMJOB as a pointer to the record the called program expects. I looked at the JT400 toolkit and I did not even see a class/method to submit a job which would make implementing something like this very hard. If you find one, then maybe an external type could be used for now.

    In the meantime, I can think of a couple of approaches which may work (have to be tested). Both assume the called program expects a structure of fields.

    a.) Write another called program which is called on the i5 and receives the parm and then it does the QCMDEXC and concatenates one long CHAR field to the command string that is being built. In other words if you have a record something like this:

    10 topfield char(80)
    20 chafield char(20);
    20 packfield decimal(5); // 3 bytes
    20 NUMfield num(7);
    20 cha2field char(50);

    when you build your command you could just use TOPFIELD. While the characters would not be readable, I would think the SBMJOB (Call pgm(mypgm) PARM(topfield_contents)) would just be passed as is.

    b.) One of the things you have to be concerned with on the remote calls to the i5 is the data conversion. The above approach lets the record layout determine the conversions that are needed on the call itself. However, you can tell EGL not to do conversion and convert the data prior and after the call using the syslib.convert. Then "insert" the data into the command using a similar technique to item a.) where you build the command using the "topfield" with data that has already been converted according to its datatype. then on the call it will just be passed as a byte stream that the receiving program will break back out based on the structure. To tell the communication layer to not convert it just don't specify a conversion table.

    Again, I have not tested any of this, so use the ideas at your own risk.
    Guus

    Maybe you could create an IBM i command which points to your program. The CPP would handle the packed fields. Once you have the command created on your IBM i, you could build a "mycommand" string in EGL and use QCMDEXEC in a stored procedure program to submit your job. For example,

    // EGL code
    mycommand string = "SBMJOB JOB(MYCOMMAND TOPFIELD('" + topfield + "') CHARFIELD('" + charfield + "YYY + "') PACKEDFLD(" + packedfield as string + ") JOB(MYBATCHJOB) JOBQ(QSYS/QBATCH)";
    


    Then pass mycommand to a stored procedure to submit the job using QCMDEXEC.

    // EGL code
    SQLLib.connect(mydatasource, "userid", "password");
    execute 
      #sql{
            CALL MYSTOREDPR( :mycommand )
           };
    SQLLib.disconnect(mydatasource);
    


    Just another option...
    Updated on 2014-03-25T04:36:07Z at 2014-03-25T04:36:07Z by iron-man
  • SystemAdmin
    SystemAdmin
    6195 Posts

    Re: How to submit an iSeries program in EGL?

    ‏2013-02-22T09:40:46Z  
    Guus

    Maybe you could create an IBM i command which points to your program. The CPP would handle the packed fields. Once you have the command created on your IBM i, you could build a "mycommand" string in EGL and use QCMDEXEC in a stored procedure program to submit your job. For example,

    <pre class="java dw" data-editor-lang="java" data-pbcklang="java" dir="ltr">// EGL code mycommand string = "SBMJOB JOB(MYCOMMAND TOPFIELD('" + topfield + "') CHARFIELD('" + charfield + "YYY + "') PACKEDFLD(" + packedfield as string + ") JOB(MYBATCHJOB) JOBQ(QSYS/QBATCH)"; </pre>

    Then pass mycommand to a stored procedure to submit the job using QCMDEXEC.

    <pre class="java dw" data-editor-lang="java" data-pbcklang="java" dir="ltr">// EGL code SQLLib.connect(mydatasource, "userid", "password"); execute #sql{ CALL MYSTOREDPR( :mycommand ) }; SQLLib.disconnect(mydatasource); </pre>

    Just another option...
    Hi Mark/Daniel
    Thanks for you suggestions. We dit not find the time yet to experiment with them.
    When we do, I will add the results to this thread.
    Guus
  • nick_tn
    nick_tn
    584 Posts

    Re: How to submit an iSeries program in EGL?

    ‏2013-02-26T19:03:19Z  
    Hi Mark/Daniel
    Thanks for you suggestions. We dit not find the time yet to experiment with them.
    When we do, I will add the results to this thread.
    Guus
    Guus,

    another option would be to do the actual submit on the iseries. I call a cl pgm on the iseries that submits another CL.

    I also tried the following without parms and it worked nice. Not sure about sql limitations with parms lengths and such
    pgm = "sbmjob job(" + clip(pgm) + ") cmd(call " + pgm + ") ";
    len decimal(15,5) = strlib.characterLen(pgm);
    execute #sql{call qcmdexc(:pgm,:len)};
    
    Updated on 2014-03-25T04:36:03Z at 2014-03-25T04:36:03Z by iron-man