Как вызвать программу RPGIV из Java, которая возвращает более одной записи

Я вызываю программу RPGIV из java, программа rpgiv возвращает множественную запись в качестве выходного параметра.

Я попробовал следующее, чтобы вернуть все строки, возвращенные из rpgiv.

   // 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]);
        }
    } 

Это в выходном классе

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 Occures OCCURS(64) INZ - это выходной набор данных, который я хочу вернуть в Java.

2 ответа

Решение

Отредактировано, чтобы показать, как конвертировать упакованное значение.

Давайте уменьшим это немного. Вот небольшая 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;

Вот 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 уродлив. Я бросил возвращенный байт [] в строку и назначил его как блок для DS. Затем я перебираю секцию кода, которая подставляет отдельные переменные по одной. Если бы я знал больше Java, я бы, вероятно, поместил бы этот мусор в конструктор и, возможно, выставил бы его в виде списка.

Разместив все это, я бы ни за что не поступил так с рабочим кодом. Я бы попросил программистов IBM написать мне обертку вокруг SuperUltimateBlockFetch - эта обертка вызовет SuperUltimateBlockFetch и создаст набор результатов для использования Java. Они могут даже превратить это в хранимую процедуру. Это избавит вас от зависимости от понимания внутренней структуры RPG и сделает более естественным работу с отдельными переменными в коде Java. Тогда все, что вам нужно сделать, это вызвать хранимую процедуру и написать while rs.next() петля.

Я бы посоветовал вам не пытаться передавать данные в качестве параметров.

Вместо этого используйте очередь данных для передачи данных обратно.

Пусть Java-программа создаст очередь данных и передаст ее имя программе RPG в качестве параметра.

Затем программа RPG отправляет данные в очередь с использованием API QSNDDTAQ.

Когда элемент управления вернется в программу Java, он должен прочитать записи из очереди данных.

Другие вопросы по тегам