Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

disable print causes nullpointer #375

Open
mahmutcanprehcm opened this issue Aug 30, 2024 · 12 comments
Open

disable print causes nullpointer #375

mahmutcanprehcm opened this issue Aug 30, 2024 · 12 comments
Assignees
Labels

Comments

@mahmutcanprehcm
Copy link

mahmutcanprehcm commented Aug 30, 2024

i have an html page which can be dynamically grow. i want to get one pdf page.

This code causes NullPointerException:

         ITextRenderer iTextRenderer = new ITextRenderer();
         iTextRenderer.setDocumentFromString(readHtmlFileAsString("foo.html"));
         SharedContext sharedContext = iTextRenderer.getSharedContext();
         sharedContext.setPrint(false);
         iTextRenderer.layout();

ITextRendere.java:

        public void createPDF(OutputStream os, boolean finish, int initialPageNo) throws DocumentException {
        List<PageBox> pages = _root.getLayer().getPages();
        RenderingContext c = newRenderingContext();
        c.setInitialPageNo(initialPageNo);
        PageBox firstPage = pages.get(0);
        ....

it this a bug, or wrong usage?

@asolntsev
Copy link
Contributor

@mahmutcanprehcm Please show the NullPointerException itself with full stacktrace.

@mahmutcanprehcm
Copy link
Author

mahmutcanprehcm commented Sep 2, 2024

java.lang.NullPointerException
	at org.xhtmlrenderer.layout.Layer.layoutPages(Layer.java:1066)
	at org.xhtmlrenderer.pdf.ITextRenderer.layout(ITextRenderer.java:232)
	at de.printer.service.pdf.DefaultTemplateBuilderService.xhtmlToPdf(DefaultTemplateBuilderService.java:72)
	at de.printer.service.pdf.DefaultTemplateBuilderService.dtoToByte(DefaultTemplateBuilderService.java:33)

@mahmutcanprehcm
Copy link
Author

#Created by Apache Maven 3.3.9
version=9.1.11
groupId=org.xhtmlrenderer
artifactId=flying-saucer-core

@asolntsev
Copy link
Contributor

@mahmutcanprehcm But version 9.1.11 is very old. Please try with the latest version 9.9.1.

@mahmutcanprehcm
Copy link
Author

mahmutcanprehcm commented Sep 2, 2024

the same with 9.9.1

java.lang.IndexOutOfBoundsException: Index 0 out of bounds for length 0
	at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:100)
	at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:106)
	at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:302)
	at java.base/java.util.Objects.checkIndex(Objects.java:385)
	at java.base/java.util.ArrayList.get(ArrayList.java:427)
	at org.xhtmlrenderer.pdf.ITextRenderer.createPDF(ITextRenderer.java:372)
	at org.xhtmlrenderer.pdf.ITextRenderer.createPDF(ITextRenderer.java:328)
	at com.solutionfactory.HtmlToPdfOpenPDF.main(HtmlToPdfOpenPDF.java:32)

"The problem occurs when you call setPrint(false) on SharedContext."

ITextRenderer.java
Line 372

  RenderingContext c = newRenderingContext();
        c.setInitialPageNo(initialPageNo);
        PageBox firstPage = pages.get(0);
        com.lowagie.text.Rectangle firstPageSize = new com.lowagie.text.Rectangle(0, 0, firstPage.getWidth(c) / _dotsPerPoint,
                firstPage.getHeight(c) / _dotsPerPoint);

@asolntsev
Copy link
Contributor

asolntsev commented Sep 3, 2024

@mahmutcanprehcm I would say, it's rather a wrong usage.

Why do you call setPrint(false)?

When you convert a web page to PDF, it's usually intended for printing. It means setPrint(true) would be reasonable, and it is the default value.

@asolntsev asolntsev self-assigned this Sep 3, 2024
@mahmutcanprehcm
Copy link
Author

I need a single page. It is an invoice that goes to a thermal printer and if the customer wants to download a PDF, he should not receive several pages.

@asolntsev
Copy link
Contributor

Ok, but how setPrint(false) is related to single/multiple pages?
It dictates "media: print" or "media: screen". It doesn't affect number of pages.

@mahmutcanprehcm
Copy link
Author

OK. Unfortunately I couldn't find any documentation about this method.

How can I then ensure that everything only ends up on one page?

@pbrant
Copy link
Member

pbrant commented Sep 4, 2024 via email

@mahmutcanprehcm
Copy link
Author

Bildschirmfoto vom 2024-09-04 13-34-59

this produces always a large pdf file

@pbrant
Copy link
Member

pbrant commented Sep 22, 2024

(Urk, sorry the late response here.)

Thanks, that makes sense. The behavior you're looking for (PDF output on a single page with page extents trimmed to the content extent) isn't something that's come up before. FS doesn't support it directly.

One fairly low effort way you could hack around this would be to use ITextRenderer#findPagePositionsByID(). It takes a regex that returns the content area of block-level elements with an id attribute set that match the pattern. With an empty <div id="content-end"></div> element you could use that to figure out where the content stops on the huge page. You could then use that to render the receipt a second time with the corrected page size.

This would have the negative that you'd be laying out the receipt twice (but only rendering the PDF once). FS is fast enough though that that may not matter.

If that is a problem, I can't think of an alternative beyond doing surgery on ITextRenderer itself to provide the option to adjust page sizes post layout.

Edit: Another option would be to use iText or PDFBox to update the crop box of the page after the fact (vs. doing a second layout). I'm not entirely sure which would be faster though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants