Discussions relating to writing software in ILE RPG (RPG IV). This includes both fixed and free format RPG.
thomprl
Posts: 5 Joined: Tue Oct 01, 2024 5:29 pm
Post
by thomprl » Tue Oct 01, 2024 6:07 pm
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
Post
by Scott Klement » Tue Oct 01, 2024 8:34 pm
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
Post
by thomprl » Tue Oct 01, 2024 9:48 pm
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
Post
by Scott Klement » Tue Oct 01, 2024 10:01 pm
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
Post
by thomprl » Tue Oct 01, 2024 10:36 pm
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.
allthom
Posts: 10 Joined: Thu Apr 13, 2023 4:02 pm
Post
by allthom » Thu Oct 03, 2024 7:52 am
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
Post
by thomprl » Thu Oct 03, 2024 2:15 pm
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