views:

342

answers:

5

Hi,

I have a very limitied (0) knowledge on AS400 and RPG. But we have a urgent requirement where we need to invoke a RPG program from a java class. So I found that we can achieve it through JTOpen. But I am stuck at declaring the ProgramParameter list. I have the following information about RPG Program

Program name: ZM30000R Parameters: Branch 7,0 (Numeric)
Account type 2 (01-cheque,02 savings)
Account Number 20 (character)
Error code 7 (character) DR/CR indicater 1 (character D,C)

But no clue about what is the intput and output .How to declare the ProgramParameter. I have done as below. I cannot test as well because I dont have connectivity to these systems.

// Create AS400 Text objects for the different lengths
          // of parameters you are sending in.
          AS400Text branchTxt = new AS400Text(7);
          AS400Text accntTypeTxt = new AS400Text(2);
          AS400Text accntNumberTxt = new AS400Text(20);
          AS400Text errorCodeTxt = new AS400Text(7);
          AS400Text DCIndicatorTxt = new AS400Text(1);            

          // declare and instantiate  your parameter list.
          ProgramParameter[] parmList = new ProgramParameter[5];

          // assign values to your parameters using the AS400Text class to convert to bytes
          // the second parameter is an integer which sets the length of your parameter output
          parmList[0] = new ProgramParameter( branchTxt.toBytes(branch),7);
          parmList[1] = new ProgramParameter( accntTypeTxt.toBytes(accntTypeTxt),2);      
          parmList[2] = new ProgramParameter( accntNumberTxt.toBytes(accntNumberTxt),20);      
          parmList[3] = new ProgramParameter( errorCodeTxt.toBytes(""),7);      
          parmList[4] = new ProgramParameter( DCIndicatorTxt.toBytes(indicator),5);

Any help will be really highly useful.

Thanks and Regards,

Srinivas

+4  A: 

Well, I do have a clue just by the description of the parameters. Branch, account type and account number are IN. You need that information for a financial booking or transaction. The error code is appearently OUT. In my experience with financial systems it's reasonable normal that the API returns the way the amount is booked. Normally one would use the sign, but in financial systems the (D)ebit or (C)redit is the better way.

The API is very likely the API of a financial system. If that is true, then I'm missing the amount. Are you sure you've the complete description?

Notice that the first parameter is numeric. You're not in luck. The iSeries and RPG are not very forgiving about the type of a numeric. One can choose from Bit, Zoned, Packed, Decimal, Integer, Float and so on. If the RPG is really RPG instead of ILE RPG, then you can bring that down to Zoned, Packed and Byte.

I assume you've access to the iSeries. Then you can watch the program call, debug information and dump information. That will help you if you have to do "trial and error". If you don't have access, the road will be very hard. You'll receive an error in your java class if the program call is not succesfull. But it will be hard to identify the real error without the information from the iSeries yourself. Therefore, access is really required.

robertnl
A: 

If you don't have connectivity, then you really can't do what is asked. How do you test it? Is there numeric parameters or are they all character?

Mike Wills
+2  A: 

Your sample is mostly on the right track. But your branch parameter is numeric. So you should use AS400ZonedDecimal instead of AS400Text:

AS400ZonedDecimal branchNbr = new AS400ZonedDecimal(7,0)

The RPG program may be expecting packed instead of zoned. No big deal, just use AS400PackedDecimal instead.

As you construct your ProgramParameter object, your constructor requirements are different depending on if they are input or output parameters to your program. For input parameters, just pass the toBytes() results. There is no need to include the length. For output-only parameters, just pass the length.

I agree with Robert's answer that there is some missing information, but his assumptions on the outputness of the error code seems valid. I would guess, however, that the DCIndicator parameter is input since your sample passes a value. For the error code parameter, after your program call, you'll need to extract the value and do something with it. Given what you have already, here is how the program call would work. Take note that I specified a library name of "MyLibrary". That is for example purposes. You will have to determine which library your program object is in.

ProgramCall pgm = new ProgramCall(as400, QSYSObjectPathName.toPath("MyLibrary","ZM30000R","PGM"), parmList);
if (pgm.run() == true) {
    String sErrorCode = (String) errorCodeTxt.toObject(parmList[3].getOutputData());

    //Do something with your output data.
}
else {
    AS400Message[] messageList = pgm.getMessageList();
    for (int i=0; i<messageList.length; i++) {
        String sMessageID = messageList[i].getID();
        String sMessageText = messageList[i].getText();

        //Do something with the error messages
    }
}

Something else to consider is library lists. Does the RPG program expect certain libraries to be in the library list? If so, you should issue CommandCalls to add the libraries to the library list before calling the program.

Tracy Probst
Thanks Tracy for the suggestions, the AS400PackedDecimal declaration has solved the problem.
Srinivas
+1  A: 

Hello Gentle People, This is a great post. With its help I have been able to call a RPG program from a Java application successfully. However, I am not passing any parameters to the RPG program. I have a difficulty with calling the RPG that needs parameters from Java. Here's what I have done:

    AS400Text text8 = new AS400Text(8);
    AS400Text text5 = new AS400Text(5);
    AS400Text text3 = new AS400Text(3);        
    AS400Text text1 = new AS400Text(1);

    ProgramParameter [] paramList = new ProgramParameter[6];
    System.out.println(paramList.length);

    paramList[0] = new ProgramParameter(text3.toBytes("LGC"));
    paramList[1] = new ProgramParameter(text8.toBytes("20100218"));
    paramList[2] = new ProgramParameter(text8.toBytes("00000000"));
    paramList[3] = new ProgramParameter(text5.toBytes("00000"));
    paramList[4] = new ProgramParameter(text1.toBytes(" "));
    paramList[5] = new ProgramParameter(text1.toBytes(" "));


    AS400 sys = new AS400("10.1.4.35", "TSTAPPSRV","TSTAPP222");

    try{
        p.setProgram(QSYSObjectPathName.toPath("AGPRODPGM", "R3758R", "PGM"), paramList);
        System.out.println(p.run());
        AS400Message[] ml = p.getMessageList();

        for (int i = 0; i < ml.length; i++) {
            System.out.println(ml[i].getText());
        }
    }catch(Exception e){
        System.out.println(e.getMessage());
    }

Not all of the parameters passed in the R3758R program are string in the table but R3758R is designed such that it expects parameters in String and parses the parameters being passed and converts to the corresponding actual data format defined in the table.

The program runs without any exception being thrown. The time it takes to run is 0 (BUILD SUCCESSFUL (total time: 0 seconds)) so I believe it actually didn't run which is what I don't understand. My other program without the parameter runs just fine. So I am thinking I am doing something wrong while passing parameter list but could not figure it out so far. I would appreciate if some one could point out what I have been doing wrong.

Thank you. T

T Rai
A: 

FWIW: It's a lot easier to call IBM i host programs & service programs using PCML rather than ProgramCall.

The compilers will even generate the PCML document for you.

See http://javadoc.midrange.com/jtopen/com/ibm/as400/data/ProgramCallDocument.html for details.

david