Search code examples
jsfprimefacesitext

Layout change in iText doesn't affect first page with PrimeFaces' preprocessor


I would like to export a data table to PDF using iText from JSF. For that, I used the Prime Faces' implementation.

Everything works fine, but I would like to change the PDF's layout. First of all, the page orientation to landscape. For that I used the preprocessor method, suggested by PrimeFaces.

My issue is that the first page of the PDF isn't affected by the changes, just the next ones.

Am I understanding well, that this is a Prime Faces related issue? I didn't find on Google any solutions regarding this issue. I think maybe I configure something wrong, but I didn't see where.

Thank you for kindly help.

The xhtml:

<p:dataExporter type="pdf" target="tbl" fileName="#{resourceHandler.getString('attendance.filename')}" preProcessor="#{presenceController.preProcessPDF}" />

The (simplified) 'context' of the code above:

<!DOCTYPE html>
<f:view xmlns="http://www.w3.org/1999/xhtml"
   xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
   xmlns:h="http://xmlns.jcp.org/jsf/html"
   xmlns:f="http://xmlns.jcp.org/jsf/core"
   xmlns:c="http://xmlns.jcp.org/jsp/jstl/core"
   xmlns:p="http://primefaces.org/ui" encoding="UTF-8">
   <html>
      <h:head></h:head>
      <h:body>
         <ui:composition template="layout.xhtml">
            <ui:define name="contentWrap">
               <h:form id="display">
                  <p:commandButton
                     value="#{resourceHandler.getString('attendance.get')}"
                     action="#{presenceController.populate()}" update="display tbl" />
                  <p:dataTable id="tbl" var="pdto"
                     value="#{presenceController.presenceList}"
                     paginatorTemplate="{CurrentPageReport}  {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {Exporters}"
                     paginator="true" rows="10" style="margin-bottom:20px">
                     <f:facet name="{Exporters}">
                        <h:commandLink>
                           <p:graphicImage value="assets/img/pdf.png" width="24" />
                           <p:dataExporter type="pdf" target="tbl"
                              fileName="#{resourceHandler.getString('attendance.filename')}" preProcessor="#{presenceController.preProcessPDF}" />
                        </h:commandLink>
                     </f:facet>
                     <p:column id="lastName"
                        headerText="#{resourceHandler.getString('attendance.lastname')}">
                        <h:outputText value="#{pdto.lastName}" />
                     </p:column>
                  </p:dataTable>
               </h:form>
            </ui:define>
         </ui:composition>
      </h:body>
   </html>
</f:view>

The method:

public void preProcessPDF(Object document) throws IOException, BadElementException, DocumentException {
    Document pdf = (Document) document;
    pdf.open();
    pdf.setPageSize(PageSize.A4.rotate());
}

The output: The result of the above code


Update:

The PDFOptions is working on the first page, but the preprocess still doesn't.

private PDFOptions pdfOpt;
        
 @PostConstruct
 public void setupPdf() {
     pdfOpt = new PDFOptions();
     pdfOpt.setCellFontSize("1");
 }

with

<p:dataExporter type="pdf" target="tbl"
                                fileName="#{resourceHandler.getString('attendance.filename')}"
                                preProcessor="#{presenceController.preProcessPDF}"
                                options="#{presenceController.pdfOpt}" />

Solution

  • I solved the issue by modifying the preprocess code:

    we should change the page size, then open the document.

        public void preProcessPDF(Object document) throws IOException, BadElementException, DocumentException {
               Document pdf = (Document) document;
               pdf.setPageSize(PageSize.A4.rotate());
               pdf.open();
    }