RPG and Java Lists

Discussions relating to writing software in ILE RPG (RPG IV). This includes both fixed and free format RPG.
Post Reply
thomprl
Posts: 5
Joined: Tue Oct 01, 2024 5:29 pm

RPG and Java Lists

Post by thomprl »

I saw a question on one of the Facebook Groups about needing to split a PDF file using RPG and I had previously done something with merging multiple PDF documents into one PDF document with PDFBox and thought maybe this would be similar. I made a good bit of progress using RDi to create the Java Methods I needed, but one Method returns a List of Objects and I wasn't sure how to handle that. I found one example on the internet of a get that I thought would work but I keep getting the following error when I call it.

Code: Select all

Java exception "java.lang.NoSuchMethodError:  java/util/List.get(I)Ljava/util/Object;" when calling method "get" with 
signature "" in class "java.util.List".                                 
The error happens on this line
pdfPartialDocument = get(splitRet : 0);

I've tried 0 and 1 as I wasn't sure whether the list would be 0 or 1 based since it was RPG but I assumed 0. Is there anyway to see what is really wrong?

I used this page to help me get started trying to convert the Java to RPG
https://stackoverflow.com/questions/402 ... -filenames
Also found some information here:
https://stackoverflow.com/questions/164 ... -using-rpg

Code: Select all

**free
// https://stackoverflow.com/questions/40221977/pdfbox-split-pdf-in-multi-files-with-different-page-
//

CTL-OPT ACTGRP(*NEW) Main(Main);

DCL-DS psds psds;
  MsgID CHAR(7) POS(40);
  ExceptData CHAR(80) POS(91);
END-DS;

DCL-PROC Main;

  // Create Java String Object
  DCL-PR newString Object(*JAVA:'java.lang.String')
                   ExtProc(*JAVA:'java.lang.String':*CONSTRUCTOR);
    *N Varchar(65535) Const;
  END-PR;

  // Create Java File Object
  DCL-PR newFile Object(*JAVA:'java.io.File')
                 ExtProc(*JAVA:'java.io.File':*CONSTRUCTOR);
    *N Object(*Java:'java.lang.String');
  END-PR;

  DCL-PR get OBJECT(*JAVA : 'java.util.Object' )
         EXTPROC(*JAVA :
         'java.util.List' : 'get');
    arg0 INT(10) VALUE;
  END-PR;

  // -----------------------------------------------------------------
  // Returned field declaration for Java method:
  //     load in class PDDocument
  //     Java returned type is org.apache.pdfbox.pdmodel.PDDocument
  // -----------------------------------------------------------------
  DCL-S pdfDocument OBJECT(*JAVA : 'org.apache.pdfbox.pdmodel.PDDocument' );
  DCL-S pdfPartialDocument OBJECT(*JAVA : 'org.apache.pdfbox.pdmodel.PDDocument' );

  // -------------------------------------------------------------------------
  // Parameter field declarations for Java method:
  //     load in class PDDocument
  // -------------------------------------------------------------------------
  // Parameter field declaration for Java type: File
  DCL-S j_loadParam0 OBJECT(*JAVA : 'java.io.File' );

  // --------------------------------------------------------------------
  // Prototype for Java method:
  //     load in class PDDocument in package org.apache.pdfbox.pdmodel
  // --------------------------------------------------------------------
  DCL-PR load OBJECT(*JAVA : 'org.apache.pdfbox.pdmodel.PDDocument' )
          EXTPROC(*JAVA : 'org.apache.pdfbox.pdmodel.PDDocument' : 'load' )
          STATIC;
    // Parameter prototype declaration for Java type: File
    arg0 OBJECT(*JAVA : 'java.io.File' );
  END-PR ;

  // --------------------------------------------------
  // Declaration for Java object of class Splitter in package org.apache.pdfbox.multipdf
  // --------------------------------------------------
  DCL-S splitterObj Object(*java: 'org.apache.pdfbox.multipdf.Splitter' );

  // -----------------------------------------------
  // Returned field declaration for Java method:
  //     split in class Splitter
  //     Java returned type is java.util.List
  // -----------------------------------------------
  DCL-S splitRet OBJECT(*JAVA : 'java.util.List' );

  // -------------------------------------------------------------------------
  // Parameter field declarations for Java method:
  //     split in class Splitter
  // -------------------------------------------------------------------------
  // Parameter field declaration for Java type: PDDocument
  DCL-S j_splitParam0 OBJECT(*JAVA : 'org.apache.pdfbox.pdmodel.PDDocument' );

  // -----------------------------------------------------
  // Prototype for Java constructor in class
  //     Splitter in package org.apache.pdfbox.multipdf
  // -----------------------------------------------------
  DCL-PR splitterObjCtor Object(*java :
            'org.apache.pdfbox.multipdf.Splitter' )
            Extproc(*java : 'org.apache.pdfbox.multipdf.Splitter' : *CONSTRUCTOR);

  END-PR ;

  // --------------------------------------------------------------------
  // Prototype for Java method:
  //     split in class Splitter in package org.apache.pdfbox.multipdf
  // --------------------------------------------------------------------
  DCL-PR split OBJECT(*JAVA : 'java.util.List' ) EXTPROC(*JAVA : 'org.a+
         pache.pdfbox.multipdf.Splitter' : 'split' );
    // Parameter prototype declaration for Java type: PDDocument
    arg0 OBJECT(*JAVA : 'org.apache.pdfbox.pdmodel.PDDocument' );
  END-PR ;

  // ---------------------------------------------------------------------------
  // Prototype for Java method:
  //     setStartPage in class Splitter in package org.apache.pdfbox.multipdf
  // ---------------------------------------------------------------------------
  DCL-PR setStartPage  EXTPROC(*JAVA : 'org.apache.pdfbox.multipdf.Spli+
         tter' : 'setStartPage' );
    // Parameter prototype declaration for Java type: int
    arg0 INT(10) VALUE;
  END-PR ;

  // ---------------------------------------------------------------------------
  // Prototype for Java method:
  //     setStartPage in class Splitter in package org.apache.pdfbox.multipdf
  // ---------------------------------------------------------------------------
  DCL-PR setEndPage  EXTPROC(*JAVA : 'org.apache.pdfbox.multipdf.Spli+
         tter' : 'setStartPage' );
    // Parameter prototype declaration for Java type: int
    arg0 INT(10) VALUE;
  END-PR;


  // --------------------------------------------------
  // Declaration for Java object of class PDDocument in package org.apache.pdfbox.pdmodel
  // --------------------------------------------------
  DCL-S pDDocumentObj Object(*java: 'org.apache.pdfbox.pdmodel.PDDocume+
              nt' );

  // -------------------------------------------------------------------------
  // Parameter field declarations for Java method:
  //     save in class PDDocument
  // -------------------------------------------------------------------------
  // Parameter field declaration for Java type: File
  DCL-S j_saveParam0 OBJECT(*JAVA : 'java.io.File' );
  // ------------------------------------------------------
  // Prototype for Java constructor in class
  //     PDDocument in package org.apache.pdfbox.pdmodel
  // ------------------------------------------------------
  DCL-PR pDDocumentObjCtor Object(*java : 'org.apache.pdfbox.pdmodel.PD+
              Document' ) Extproc(*java : 'org.apache.pdfbox.pdmodel.PDDocum+
              ent' : *CONSTRUCTOR);
  END-PR ;

  // --------------------------------------------------------------------
  // Prototype for Java method:
  //     save in class PDDocument in package org.apache.pdfbox.pdmodel
  // --------------------------------------------------------------------
  DCL-PR save  EXTPROC(*JAVA : 'org.apache.pdfbox.pdmodel.PDDocument' :
               'save' );
    // Parameter prototype declaration for Java type: File
    arg0 OBJECT(*JAVA : 'java.io.File' );
  END-PR ;


  DCL-S vPdfFilePathAndName CHAR(5000);
  DCL-S j_NewFile OBJECT(*JAVA : 'java.io.File' );
  DCL-S j_PartialNewFile OBJECT(*JAVA : 'java.io.File' );
  DCL-S j_NewString OBJECT(*JAVA : 'java.lang.String');
  // Parameter field declaration for Java type: int
  DCL-S j_StartPage INT(10) INZ(1);
  DCL-S j_EndPage INT(10) INZ(2);
  DCL-S j_Index INT(10) INZ(0);

  // QCMDEXEC to run IBMi commands
  DCL-PR QCmdExc ExtPgm('QCMDEXC');
    *N CHAR(2000) Const;
    *N PACKED(15:5) Const;
  END-PR;

  DCL-S cmdString CHAR(2000);
  DCL-C TICK '''';

  // Set Classpath or Change Classpath
  cmdString = 'ADDENVVAR (CLASSPATH) VALUE(' + TICK +
      '/home/rthompson/pdfbox2/pdfbox-app-2.0.27.jar' + TICK +
      ')';
  Monitor;
    QCmdExc(cmdString : %len(%trim(cmdString)));
  On-Error;
    If MsgID = 'CPFA980';
      cmdString = 'CHGENVVAR (CLASSPATH) VALUE(' + TICK +
        '/home/rthompson/pdfbox2/pdfbox-app-2.0.27.jar' + TICK +
        ')';
      Monitor;
        QCmdExc(cmdString : %len(%trim(cmdString)));
      On-Error;
        *INLR = *On;
        Return;
      EndMon;
    EndIf;
  EndMon;

  vPdfFilePathAndName = '/home/rthompson/pdfMerge/nwpdf2.pdf';
  j_NewString = newString(%trim(vPdfFilePathAndName));
  j_NewFile = newFile(j_NewString);

  // --------------------------------
  // Call Java method:
  //      load in class PDDocument
  // --------------------------------
  //
  pdfDocument = load(j_NewFile);

  splitterObj = splitterObjCtor();

  // --------------------------------------
  // Call Java method:
  //      setStartPage in class Splitter
  // --------------------------------------
  setStartPage( splitterObj : j_StartPage );
  setEndPage( splitterObj : j_EndPage );

  // -------------------------------
  // Call Java method:
  //      split in class Splitter
  // -------------------------------
  splitRet = split( splitterObj : pdfDocument );

  pdfPartialDocument = pDDocumentObjCtor();
  pdfPartialDocument = get(splitRet : 0);

  vPdfFilePathAndName = '/home/rthompson/pdfMerge/split.pdf';
  j_NewString = newString(%trim(vPdfFilePathAndName));

  j_PartialNewFile = newFile(j_NewString);

  // --------------------------------
  // Call Java method:
  //      save in class PDDocument
  // --------------------------------
  save( pdfPartialDocument : j_PartialNewFile );

END-PROC;

Scott Klement
Site Admin
Posts: 799
Joined: Sun Jul 04, 2021 5:12 am

Re: RPG and Java Lists

Post by Scott Klement »

thomprl wrote: Tue Oct 01, 2024 6:07 pm

Code: Select all

Java exception "java.lang.NoSuchMethodError:  java/util/List.get(I)Ljava/util/Object;" when calling method "get" with 
signature "" in class "java.util.List".                                 
The error happens on this line
pdfPartialDocument = get(splitRet : 0);

I've tried 0 and 1 as I wasn't sure whether the list would be 0 or 1 based since it was RPG but I assumed 0. Is there anyway to see what is really wrong?
The actual problem seems to be "java.lang.NoSuchMethodError: java/util/List.get(I)Ljava/util/Object;"

Java methods are located based on the parameters and return value in addition to the method name. In this case, the method name is 'get', and it is in the java.util.List class... you are attempting to call it with an integer (I) parameter, and expecting it to return a java.util.Object.

However, what the message is telling you is that there is no get method in that class that accepts an integer and returns an object. You ask about passing a 0 or a 1... but it doesn't matter for this error. It's not finding the method, so it really doesn't matter at this point which value you pass to it.

Here is the documentation for java.util.List (I have not used this class before, this is just from a quick Google search)
https://docs.oracle.com/en/java/javase/ ... /List.html

When I look at the docs for the 'get' method, it doesn't return an Object. That seems to be the source of the problem.
thomprl
Posts: 5
Joined: Tue Oct 01, 2024 5:29 pm

Re: RPG and Java Lists

Post by thomprl »

Well I'm not exactly sure what I had wrong but I had something wrong somewhere. But this actually works. This needs to be cleaned up and documented. Not sure if this is a good example or not either. You would probably need to get the number of pages and somehow intelligently split the PDFs.

I have another article about merging multiple PDF's if anyone ever needed too.
https://www.linkedin.com/pulse/merging- ... me7g%3D%3D

Code: Select all

**free

CTL-OPT ACTGRP(*NEW) Main(Main);

DCL-DS psds psds qualified;
  MsgID CHAR(7) POS(40);
  ExceptData CHAR(80) POS(91);
END-DS;

DCL-PROC Main;

  // Create Java String Object
  DCL-PR newString Object(*JAVA:'java.lang.String')
                   ExtProc(*JAVA:'java.lang.String':*CONSTRUCTOR);
    *N Varchar(65535) Const;
  END-PR;

  // Create Java File Object
  DCL-PR newFile Object(*JAVA:'java.io.File')
                 ExtProc(*JAVA:'java.io.File':*CONSTRUCTOR);
    *N Object(*Java:'java.lang.String');
  END-PR;

  DCL-PR get OBJECT(*JAVA : 'java.lang.Object' )
         EXTPROC(*JAVA : 'java.util.List' : 'get');
    arg0 INT(10) VALUE;
  END-PR;

  // --------------------------------------------------------------------
  // Prototype for Java method:
  //     load in class PDDocument in package org.apache.pdfbox.pdmodel
  // --------------------------------------------------------------------
  DCL-PR load OBJECT(*JAVA : 'org.apache.pdfbox.pdmodel.PDDocument' )
          EXTPROC(*JAVA : 'org.apache.pdfbox.pdmodel.PDDocument' : 'load' )
          STATIC;
    // Parameter prototype declaration for Java type: File
    arg0 OBJECT(*JAVA : 'java.io.File' );
  END-PR ;

  // --------------------------------------------------
  // Declaration for Java object of class Splitter in package org.apache.pdfbox.multipdf
  // --------------------------------------------------
  DCL-S splitterObj Object(*java: 'org.apache.pdfbox.multipdf.Splitter' );

  // -----------------------------------------------
  // Returned field declaration for Java method:
  //     split in class Splitter
  //     Java returned type is java.util.List
  // -----------------------------------------------
  DCL-S splitRet OBJECT(*JAVA : 'java.util.List' );

  // -----------------------------------------------------
  // Prototype for Java constructor in class
  //     Splitter in package org.apache.pdfbox.multipdf
  // -----------------------------------------------------
  DCL-PR splitterObjCtor Object(*java :
            'org.apache.pdfbox.multipdf.Splitter' )
            Extproc(*java : 'org.apache.pdfbox.multipdf.Splitter' : *CONSTRUCTOR);

  END-PR ;

  // --------------------------------------------------------------------
  // Prototype for Java method:
  //     split in class Splitter in package org.apache.pdfbox.multipdf
  // --------------------------------------------------------------------
  DCL-PR split OBJECT(*JAVA : 'java.util.List' ) EXTPROC(*JAVA : 'org.a+
         pache.pdfbox.multipdf.Splitter' : 'split' );
    // Parameter prototype declaration for Java type: PDDocument
    arg0 OBJECT(*JAVA : 'org.apache.pdfbox.pdmodel.PDDocument' );
  END-PR ;

  // ---------------------------------------------------------------------------
  // Prototype for Java method:
  //     setStartPage in class Splitter in package org.apache.pdfbox.multipdf
  // ---------------------------------------------------------------------------
  DCL-PR setStartPage  EXTPROC(*JAVA : 'org.apache.pdfbox.multipdf.Spli+
         tter' : 'setStartPage' );
    // Parameter prototype declaration for Java type: int
    arg0 INT(10) VALUE;
  END-PR ;

  // ---------------------------------------------------------------------------
  // Prototype for Java method:
  //     setStartPage in class Splitter in package org.apache.pdfbox.multipdf
  // ---------------------------------------------------------------------------
  DCL-PR setEndPage  EXTPROC(*JAVA : 'org.apache.pdfbox.multipdf.Spli+
         tter' : 'setEndPage' );
    // Parameter prototype declaration for Java type: int
    arg0 INT(10) VALUE;
  END-PR;

  // ------------------------------------------------------
  // Prototype for Java constructor in class
  //     PDDocument in package org.apache.pdfbox.pdmodel
  // ------------------------------------------------------
  DCL-PR pDDocumentObjCtor Object(*java : 'org.apache.pdfbox.pdmodel.PD+
              Document' ) Extproc(*java : 'org.apache.pdfbox.pdmodel.PDDocum+
              ent' : *CONSTRUCTOR);
  END-PR ;

  // --------------------------------------------------------------------
  // Prototype for Java method:
  //     save in class PDDocument in package org.apache.pdfbox.pdmodel
  // --------------------------------------------------------------------
  DCL-PR save  EXTPROC(*JAVA : 'org.apache.pdfbox.pdmodel.PDDocument' :
               'save' );
    // Parameter prototype declaration for Java type: File
    arg0 OBJECT(*JAVA : 'java.io.File' );
  END-PR ;

  // -----------------------------------------------------------------------------
  // Prototype for Java method:
  //     setSplitAtPage in class Splitter in package org.apache.pdfbox.multipdf
  // -----------------------------------------------------------------------------
  DCL-PR setSplitAtPage  EXTPROC(*JAVA : 'org.apache.pdfbox.multipdf.Sp+
              litter' : 'setSplitAtPage' );
    // Parameter prototype declaration for Java type: int
    arg0 INT(10) VALUE;
  END-PR ;

  DCL-S vPdfFilePathAndName CHAR(5000);
  DCL-S j_NewFile OBJECT(*JAVA : 'java.io.File' );
  DCL-S j_PartialNewFile OBJECT(*JAVA : 'java.io.File' );
  DCL-S j_NewString OBJECT(*JAVA : 'java.lang.String');
  DCL-S pdfDocument OBJECT(*JAVA : 'org.apache.pdfbox.pdmodel.PDDocument' );
  DCL-S pdfPartialDocument OBJECT(*JAVA : 'org.apache.pdfbox.pdmodel.PDDocument' );

  // Parameter field declaration for Java type: int
  DCL-S j_StartPage INT(10) INZ(1);
  DCL-S j_EndPage INT(10) INZ(2);

  // QCMDEXEC to run IBMi commands
  DCL-PR QCmdExc ExtPgm('QCMDEXC');
    *N CHAR(2000) Const;
    *N PACKED(15:5) Const;
  END-PR;

  DCL-S cmdString CHAR(2000);
  DCL-C TICK '''';

  // Set Classpath or Change Classpath
  cmdString = 'ADDENVVAR (CLASSPATH) VALUE(' + TICK +
      '/home/rthompson/pdfbox2/pdfbox-app-2.0.27.jar' + TICK +
      ')';
  Monitor;
    QCmdExc(cmdString : %len(%trim(cmdString)));
  On-Error;
    If psds.MsgID = 'CPFA980';
      cmdString = 'CHGENVVAR (CLASSPATH) VALUE(' + TICK +
        '/home/rthompson/pdfbox2/pdfbox-app-2.0.27.jar' + TICK +
        ')';
      Monitor;
        QCmdExc(cmdString : %len(%trim(cmdString)));
      On-Error;
        *INLR = *On;
        Return;
      EndMon;
    EndIf;
  EndMon;

  vPdfFilePathAndName = '/home/rthompson/pdfMerge/nwpdf2.pdf';
  j_NewString = newString(%trim(vPdfFilePathAndName));
  j_NewFile = newFile(j_NewString);

  pdfDocument = load(j_NewFile);

  splitterObj = splitterObjCtor();

  setStartPage( splitterObj : j_StartPage );
  setEndPage( splitterObj : j_EndPage );
  setSplitAtPage( splitterObj : j_EndPage - j_StartPage + 1);

  splitRet = split( splitterObj : pdfDocument );

  pdfPartialDocument = pDDocumentObjCtor();
  pdfPartialDocument = get(splitRet : 0);

  vPdfFilePathAndName = '/home/rthompson/pdfMerge/split.pdf';
  j_NewString = newString(%trim(vPdfFilePathAndName));

  j_PartialNewFile = newFile(j_NewString);

  save( pdfPartialDocument : j_PartialNewFile );

END-PROC;

Scott Klement
Site Admin
Posts: 799
Joined: Sun Jul 04, 2021 5:12 am

Re: RPG and Java Lists

Post by Scott Klement »

Hmmm... yeah, you didn't change how the get() routine works. I guess that error message was misleading.

It looks like what you changed had to do with the way you're setting the start/end pages and setting the split at page. Your original setEndPage was calling the setStartPage Java method, which could be the culprit... but is fixed in the new version.
thomprl
Posts: 5
Joined: Tue Oct 01, 2024 5:29 pm

Re: RPG and Java Lists

Post by thomprl »

It was starting to bother me so I took the old and new and compared. In the get I was using java.util.Object and should've been using java.lang.Object.
Scott Klement
Site Admin
Posts: 799
Joined: Sun Jul 04, 2021 5:12 am

Re: RPG and Java Lists

Post by Scott Klement »

That explains it. Thanks!
allthom
Posts: 10
Joined: Thu Apr 13, 2023 4:02 pm

Re: RPG and Java Lists

Post by allthom »

I received a similar request, given a pdf file with a hundred pages, which contains invoices issued to different customers, split it, reading the VAT number of each customer placed on the page, and then save the new pdf file in a specific directory of the IFS.
Be careful the number of pages of each new pdf can vary, in the original, an invoice can be one or more pages, in any case the vat number is always positioned in the same position on the page on all pages
Do you think it's possible with a library like PDF Box?
thomprl
Posts: 5
Joined: Tue Oct 01, 2024 5:29 pm

Re: RPG and Java Lists

Post by thomprl »

Yeah that would take more work for sure. I haven't tried reading a PDF file with PDFBox only merging multiple documents together and now splitting based on knowing the pages to split. I know it has some capabilities to read PDF but never explored it. Mostly just wanted to see if I could split it with RPG. Python might be a better option
thomprl
Posts: 5
Joined: Tue Oct 01, 2024 5:29 pm

Re: RPG and Java Lists

Post by thomprl »

Here are two articles I wrote on LinkedIn to go with this if anyone is interested.

https://www.linkedin.com/pulse/splittin ... son-lnuue/
https://www.linkedin.com/pulse/splittin ... son-ygtte/
Post Reply