如何从 java 调用 RPGIV 程序 returns 多条记录

How to Call RPGIV program from java that returns more than one record

我正在从 java 调用一个 RPGIV 程序,rpgiv 程序 return 将多记录作为输出参数。

我尝试了以下 return 从 rpgiv return 编辑的所有行。

   // Define Output Data Structure 
      AS400DataType[] outputData = 
    {
        new AS400Text(20),              // parentOperationsItemId;
        new AS400Text(10),              // parentOperationsItemType;
        new AS400Text(10),              // parentOperationsItemSubType;
        new AS400Text(20),              // parentKnownbyId;
        new AS400Text(10),              // parentInternalStatus;
        new AS400Text(1),               // parentLeafIndicator;
        new AS400Text(20),              // childOperationsItemId;
        new AS400Text(10),              // childOperationsItemType;
        new AS400Text(10),              // childOperationsItemSubType;
        new AS400Text(20),              // childKnownbyId;
        new AS400Text(10),              // childInternalStatus;
        new AS400Text(1),               // childLeafIndicator;
        new AS400Text(10)               // InternalStatus;
    };

AS400Structure [] outputDataConverter2 = new AS400Structure[3];

    outputDataConverter2[0] = new AS400Structure(outputData);
    outputDataConverter2[1] = new AS400Structure(outputData);
    outputDataConverter2[2] = new AS400Structure(outputData);


    Object[] dataInputInformation = 
    {
        sSqlSelect,
        sFetchDirection,
        sOperationsItemId,
        sparentOperationsItemTypeList,
        sparentOperationsItemSubTpeList,
        sparentInternalStatusList,
        schildOperationsItemType,
        schildOperationsItemSubTpeList,
        schildInternalStatusList,
        sLinkStatus
    };


    Object[] dataInputInformationControl = 
    {
        sPosition,
        new BigDecimal(sRowsFetched)
    };


    // Set up the parameter list
    ProgramParameter[] parameterList = new ProgramParameter[4];
    parameterList[0] = new ProgramParameter(7); //ReturnStatus
    parameterList[1] = new ProgramParameter(inputDataConverter.toBytes(dataInputInformation)); //Input
    parameterList[2] = new ProgramParameter(inputDataControlConverter.toBytes(dataInputInformationControl)); //Control
    parameterList[3] = new ProgramParameter(outputDataConverter2[0].getByteLength()*3); //Output



    try 
    {
        // Set the program name and parameter list.
        program.setProgram(programName, parameterList);
        // Run Function
        if (program.run() != true) 
        {
            // Calling Error
            AS400Message[] messagelist = program.getMessageList();
            for (int i = 0; i < messagelist.length; ++i) 
            {
                output[0].ReturnStatus += messagelist[i] + "\n";
            }
        } 
        else 
        {
            // Set the output
            output[0] = new GetPlannedRoute();
            output[1] = new GetPlannedRoute();
            output[2] = new GetPlannedRoute();



            output[0].SetOutput(parameterList, outputDataConverter2[0]);
            output[1].SetOutput(parameterList, outputDataConverter2[1]);
            output[2].SetOutput(parameterList, outputDataConverter2[2]);
        }
    } 

这在输出中 class

public void SetOutput(ProgramParameter[] parameterList, AS400Structure outputPlannedRouteConverter) 
    {

        ReturnStatus = P6Entity.CallingRPGFunction.ConvertReturnStatus(parameterList[0]);
        Object[] outputData = (Object[]) outputPlannedRouteConverter.toObject(parameterList[3].getOutputData());
        parentOperationsItemId = ((String) outputData[0]).trim();
        parentOperationsItemType = ((String) outputData[1]).trim();
        parentOperationsItemSubType = ((String) outputData[2]).trim();
        parentKnownbyId = ((String) outputData[3]).trim();
        parentInternalStatus = ((String) outputData[4]).trim();
        parentLeafIndicator = ((String) outputData[5]).trim();

        childOperationsItemId = ((String) outputData[6]).trim();
        childOperationsItemType = ((String) outputData[7]).trim();
        childOperationsItemSubType = ((String) outputData[8]).trim();
        childKnownbyId = ((String) outputData[9]).trim();
        childInternalStatus = ((String) outputData[10]).trim();
        childLeafIndicator = ((String) outputData[11]).trim();

        InternalStatus = ((String) outputData[12]).trim();
    }

我不确定如何定义 parameterList[3] 才能接收多行或多个数据结构。以及如何获取输出参数List[3].

的具体实例

RPGIV代码:

https://www.dropbox.com/s/a29wf1ft0f07sx1/functionCode.txt?dl=0

* FetchedData Occurs OCCURS(64) INZ是我要return到java.

的输出数据集

已编辑以展示如何转换打包值。

让我们缩短一点。这是一个与您的结构相似的小型 RPG 程序:

 D V00001          DS                  OCCURS(64)
 D  F0000G                       20A
 D  F0000H                       10A
 D  F0000I                       10A
 D  F0000J                       20A
 D  F0000K                        9p 0
 D  F0000L                        1A
 D  F0000M                       20A
 D  F0000N                       10A
 D  F0000O                       10A
 D  F0000P                       20A
 D  F0000Q                       10A
 D  F0000R                        1A
 D  F0000S                       10A

 c     *entry        plist
 c                   parm                    v00001

   // populate the first entry
   %occur(v00001) = 1;
   F0000G = *ALL'1234567890';
   F0000H = *ALL'A';
   F0000I = *ALL'B';
   F0000J = *ALL'C';
   F0000K = 123456789;
   F0000L = *ALL'E';
   F0000M = *ALL'F';
   F0000N = *ALL'G';
   F0000O = *ALL'H';
   F0000P = *ALL'I';
   F0000Q = *ALL'J';
   F0000R = *ALL'K';
   F0000S = *ALL'a';

   // populate the 2nd entry
   %occur(v00001) = 2;
   F0000G = *ALL'1234567890';
   F0000H = *ALL'1234567890';
   F0000I = *ALL'1234567890';
   F0000J = *ALL'1234567890';
   F0000K = 200;
   F0000L = *ALL'1234567890';
   F0000M = *ALL'1234567890';
   F0000N = *ALL'1234567890';
   F0000O = *ALL'1234567890';
   F0000P = *ALL'1234567890';
   F0000Q = *ALL'1234567890';
   F0000R = *ALL'1234567890';
   F0000S = *ALL'b';

   // populate the third entry
   %occur(v00001) = 3;
   F0000G = *ALL'1234567890';
   F0000H = *ALL'1234567890';
   F0000I = *ALL'1234567890';
   F0000J = *ALL'1234567890';
   F0000K = 300;
   F0000L = *ALL'1234567890';
   F0000M = *ALL'1234567890';
   F0000N = *ALL'1234567890';
   F0000O = *ALL'1234567890';
   F0000P = *ALL'1234567890';
   F0000Q = *ALL'1234567890';
   F0000R = *ALL'1234567890';
   F0000S = *ALL'c';

   // reset back to the beginning
   %occur(v00001) = 1;
   dump(a);

   *inlr = *on;

这是成功读取各种 'records':

的 Java(我不是 Java 程序员!)
public String testSO(AS400 system, String programName) {
    boolean success = false;
    final int ONE_ROW_LEN = 147;
    final int DS_ROWS = 64;
    AS400Text dsText = new AS400Text(ONE_ROW_LEN * DS_ROWS);
    AS400Text p0000g = new AS400Text(20);
    AS400Text p0000h = new AS400Text(10);
    AS400Text p0000i = new AS400Text(10);
    AS400Text p0000j = new AS400Text(20);
    int p0000k;  // packed(9, 0) is 5 bytes
    AS400Text p0000l = new AS400Text( 1);
    AS400Text p0000m = new AS400Text(20);
    AS400Text p0000n = new AS400Text(10);
    AS400Text p0000o = new AS400Text(10);
    AS400Text p0000p = new AS400Text(20);
    AS400Text p0000q = new AS400Text(10);
    AS400Text p0000r = new AS400Text( 1);
    AS400Text p0000s = new AS400Text(10);
    String ds = null;

    String returnString = null;

    try
    {
        ProgramCall program = new ProgramCall(system);

        // Set up the parameter list
        ProgramParameter[] parameterList = new ProgramParameter[1];
        parameterList[0] = new ProgramParameter(ONE_ROW_LEN * DS_ROWS); 
        program.setProgram(programName, parameterList);
        success = program.run();

        if(success!=true){
            AS400Message[] messagelist = program.getMessageList();
            System.out.println("\nMessages received:\n");
            for (int i = 0; i < messagelist.length; i++) {
                System.out.println(messagelist[i]);
            }
        } else {
            // RPG is returning a giant chunk of memory
            //allBytes = parameterList[0].getOutputData();
            ds = (String)dsText.toObject(parameterList[0].getOutputData());
            System.out.println("ds=" + ds);
            System.out.println("ds len=" + ds.length());

            // Need to index our way into the block of memory
            // zero-based!
            int row = 0;
            int x = row * ONE_ROW_LEN;
            System.out.println("x=" + x);

            // parse out the individual elements for this row
            int len = p0000g.getByteLength();
            String s0000g = ds.substring(x, x+len);
            x += len;
            len = p0000h.getByteLength();
            String s0000h = ds.substring(x, x+len);
            x += len;
            len = p0000i.getByteLength();
            String s0000i = ds.substring(x, x+len);
            x += len;
            len = p0000j.getByteLength();
            String s0000j = ds.substring(x, x+len);

        // this is packed(9, 0)
        x += len;
        len = 5;
        byte[] b0000k = dsText.toBytes(ds.substring(x, x+len));
        BigDecimal d0000k = (BigDecimal)new AS400PackedDecimal(9, 0).toObject(b0000k);
        p0000k = d0000k.intValue();
        String s0000k = d0000k.toString();

            x += len;
            len = p0000l.getByteLength();
            String s0000l = ds.substring(x, x+len);
            x += len;
            len = p0000m.getByteLength();
            String s0000m = ds.substring(x, x+len);
            x += len;
            len = p0000n.getByteLength();
            String s0000n = ds.substring(x, x+len);
            x += len;
            len = p0000o.getByteLength();
            String s0000o = ds.substring(x, x+len);
            x += len;
            len = p0000p.getByteLength();
            String s0000p = ds.substring(x, x+len);
            x += len;
            len = p0000q.getByteLength();
            String s0000q = ds.substring(x, x+len);
            x += len;
            len = p0000r.getByteLength();
            String s0000r = ds.substring(x, x+len);
            x += len;
            len = p0000s.getByteLength();
            String s0000s = ds.substring(x, x+len);


            returnString = s0000s;
            System.out.println("Return=" + returnString);
            System.out.println("g=" + s0000g);
            System.out.println("h=" + s0000h);
            System.out.println("i=" + s0000i);
            System.out.println("i=" + s0000i);
            System.out.println("j=" + s0000j);
            System.out.println("k=" + s0000k);
            System.out.println("l=" + s0000l);
            System.out.println("m=" + s0000m);
            System.out.println("n=" + s0000n);
            System.out.println("o=" + s0000o);
            System.out.println("p=" + s0000p);
            System.out.println("q=" + s0000q);
            System.out.println("r=" + s0000r);
            System.out.println("r=" + s0000s);
        }

    } catch (Exception e) {
        System.out.println("\ne:\n");
        System.out.println(e);
        System.out.println("\nStack trace:\n");
        e.printStackTrace();

    }
    return returnString;
}

在 Java 中要理解的关键部分是在这种设计中,Parameter.getOutputData() 返回 byte[]。我不是 Java 程序员,所以我的 Java 代码很丑。我将返回的 byte[] 转换为 String 并将其作为块分配给 ds。然后,我暴力破解了一段代码,将各个变量逐个子字符串化。如果我知道更多 Java 我可能会把那些垃圾放在构造函数中,并可能将其公开为列表。

发布了所有这些内容后,我绝不会以这种方式使用生产代码进行操作。我会让 IBM 程序员给我写一个围绕 SuperUltimateBlockFetch 的包装器——该包装器将调用 SuperUltimateBlockFetch 并构建一个结果集供 Java 使用。他们甚至可以把它变成一个存储过程。这将使您不再依赖于理解 RPG 结构的内部构造,并使处理 Java 代码中的各个变量变得更加自然。然后你要做的就是调用存储过程并编写一个 while rs.next() 循环。

我建议您不要尝试将数据作为参数传递。

而是使用数据队列将数据传回。

让 java 程序创建一个数据队列并将其名称作为参数传递给 RPG 程序。

然后 RPG 程序将使用 QSNDDTAQ API.

将数据发送到队列

当控制 returns 到 Java 程序时,让它从 data queue.

中读取条目