Search code examples
javaitextstack-overflow

Stackoverflow error in OnstartPage method


I intend to have a different String for every Start of Page depending on values I read from another File. I have Placed this in my onStartPage Method Like this:

@Override
    public void onStartPage(PdfWriter writer, Document output) {
        try {
            File finish = new File("C:/Statements final/");
            File[] finf = finish.listFiles();
            Font f1 = new Font(Font.NORMAL, 12);
            f1.setColor(Color.BLACK);            
            String firstline = "";
            for (int k = 0; k < filenames1.length; k++) {
                FileInputStream fs = new FileInputStream("C:/Statements final/" + filenames1[k]);
                BufferedReader br = new BufferedReader(new InputStreamReader(fs));
                for (int i = 0; i < 0; i++) {
                    br.readLine();
                }
                firstline = br.readLine();          

            System.out.println(firstline);

            output.add(new Paragraph(new Phrase(new Chunk(firstline, f1))));
            }
        } catch (Exception ex) {
            System.out.println(ex);
        }
    }

I am getting this StackOverflow error:

Exception in thread "main" java.lang.StackOverflowError
    at java.lang.String.toLowerCase(String.java:2524)
    at com.lowagie.text.pdf.PdfEncodings.convertToBytes(PdfEncodings.java:149)
    at com.lowagie.text.pdf.BaseFont.convertToBytes(BaseFont.java:795)
    at com.lowagie.text.pdf.FontDetails.convertToBytes(FontDetails.java:160)
    at com.lowagie.text.pdf.PdfContentByte.showText2(PdfContentByte.java:1386)
    at com.lowagie.text.pdf.PdfContentByte.showText(PdfContentByte.java:1396)
    at com.lowagie.text.pdf.PdfDocument.writeLineToContent(PdfDocument.java:1587)
    at com.lowagie.text.pdf.ColumnText.go(ColumnText.java:841)
    at com.lowagie.text.pdf.ColumnText.go(ColumnText.java:752)
    at com.lowagie.text.pdf.PdfPRow.writeCells(PdfPRow.java:513)
    at com.lowagie.text.pdf.PdfPTable.writeSelectedRows(PdfPTable.java:511)
    at com.lowagie.text.pdf.PdfPTable.writeSelectedRows(PdfPTable.java:587)
    at com.lowagie.text.pdf.PdfPTable.writeSelectedRows(PdfPTable.java:543)
    at com.lowagie.text.pdf.PdfDocument.newPage(PdfDocument.java:830)
    at com.lowagie.text.pdf.PdfDocument.carriageReturn(PdfDocument.java:1192)
    at com.lowagie.text.pdf.PdfDocument.add(PdfDocument.java:482)
    at estatement.Border.onStartPage(Border.java:112)

Anyone who knows what I should Do.


Solution

  • onStartPage is very brittle if you try to change document contents in it, cf. the JavaDoc comment of PdfPageEvent.onStartPage warning about infinite loops:

    /**
     * Called when a page is initialized.
     * <P>
     * Note that if even if a page is not written this method is still
     * called. It is preferable to use <CODE>onEndPage</CODE> to avoid
     * infinite loops.
     *
     * @param writer the <CODE>PdfWriter</CODE> for this document
     * @param document the document
     */
    public void onStartPage(PdfWriter writer, Document document);
    

    The reason is that onStartPage is called during page initialization but additions to the document require page initialization to already have finished.

    @VigneshVino's proposal (if properly implemented), therefore, will prevent the infinite loop but might still cause some parts of page initialization to be executed twice. This might be harmless (setting the same variables to the same values twice seems harmless) but it also might have undesired side effects (incrementing the same variable twice is not harmless). Especially if multiple page event listeners are active, the effects might be irritating.

    Thus, I would propose you leave some additional space at the top of the pages by means of margins and fill that space in an onEndPage instead.

    PS: Additionally there is a FAQ on the use of onStartPage() on page 150 of iText in Action — 2nd Edition:

    FAQ Why is it not advised to add content in the onStartPage() method? You'll remember from section 5.2.4 that iText ignores newPage() calls when the current page is empty. This method is executed — or ignored — when you call it explicitly from your code, but it's also invoked implicitly from within iText on multiple occasions. It's important that it's ignored for empty pages; otherwise you'd end up with plenty of unwanted new pages that are unintentionally left blank. If you add content in an onStartPage() method, there's always a risk of having unwanted pages. Consider it more safe to reserve the onEndPage() method for adding content.