I wrote a Java program with iText 9.0.0 to create a PDF file. I need to add external PDFs as XObjects to every page of a PDF. Everything goes fine if the number of the PDF pages is 1 or 2. However, if the number of pages >= 3 (for example change int n = 30;
to int n = 31;
in the following code), the program crashes and the PDF will be unable to generate correctly. This behavior is really eerie!
package net.opho;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfReader;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.kernel.pdf.xobject.PdfXObject;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.Paragraph;
public class Main {
public static void main(String[] args) throws Exception {
PdfDocument output = new PdfDocument(new PdfWriter("C:\\develop\\demo.pdf"));
Document document = new Document(output);
document.setTopMargin(120);
Paragraph paragraph = (new Paragraph("Some texts...")).setFontSize(24);
int n = 30;
for (int i = 0; i < n; i++) {
document.add(paragraph);
}
PdfDocument logoPdf = new PdfDocument(new PdfReader("C:\\develop\\OPhOLogo.pdf"));
PdfXObject logoObject = logoPdf.getFirstPage().copyAsFormXObject(output);
logoPdf.close();
Rectangle logoRectangle = PdfXObject.calculateProportionallyFitRectangleWithWidth(logoObject, 20, 750, 200);
for (int i = 1; i <= output.getNumberOfPages(); i++) {
PdfCanvas canvas = new PdfCanvas(output, i);
canvas.addXObjectFittedIntoRectangle(logoObject, logoRectangle);
}
output.close();
}
}
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "java.util.Map.get(Object)" because "this.map" is null
at com.itextpdf.kernel.pdf.PdfDictionary.get(PdfDictionary.java:471)
at com.itextpdf.kernel.pdf.PdfDictionary.getAsNumber(PdfDictionary.java:184)
at com.itextpdf.kernel.pdf.PdfPage.getRotation(PdfPage.java:151)
at com.itextpdf.kernel.pdf.canvas.PdfCanvas.<init>(PdfCanvas.java:229)
at com.itextpdf.kernel.pdf.canvas.PdfCanvas.<init>(PdfCanvas.java:271)
at net.opho.Main.main(Main.java:25)
To turn the solution found in the comments into an answer:
iText by default flushes created pages as soon as possible to the output steam and clears them from memory to conserve resources. Thus, you have to either disable this mechanism, or add your graphics early (using page events), or add them in a second pass.
To disable this early flushing mechanism use the three-parameter Document
constructor and set the boolean immediateFlush
parameter to false
. Also see this answer.
after this code change I should also change
output.close();
todocument.close();
, otherwise the texts will not be rendered.
Yes, when using a Document
, you need to close it, and closing it implicitly closes the PdfDocument
. Usually the easiest way is to use try-with-resources
.