3

I have problem to display StreamedContent PDF in DocumentViewer from Primefaces Extensions (6.2.9) with PrimeFaces 6.2 and MyFaces 2.2.12. I read the same question, but it's an other situation.

Message: Missing PDF in PrimeFaces Extensions DocumentViewer

This is my xhtml code

<p:commandButton icon="fa fa-print" actionListener="#{bean.onPrerender}" />

Dialog code

<p:dialog id="dvDialog" widgetVar="dv_dialog" dynamic="true" header="Document" width="1200px" height="700px" modal="true">
     <pe:documentViewer cache="true" height="500" value="#{bean.content}" download="report.pdf" />
</p:dialog>

This is my java code

private StreamedContent content;

public void onPrerender(ActionEvent actionEvent) {

    try {

        ByteArrayOutputStream out = new ByteArrayOutputStream();

        Document document = new Document();
        PdfWriter.getInstance(document, out);
        document.open();

        for (int i = 0; i < 50; i++) {
            document.add(
                  new Paragraph("All work and no play makes Jack a dull boy"));
        }

        document.close();
        // content = new DefaultStreamedContent(
        // new ByteArrayInputStream(out.toByteArray()), "application/pdf");
        content = new ByteArrayContent(out.toByteArray(), "application/pdf");
    } catch (Exception e) {
        e.printStackTrace();
    }

    PrimeFaces.current().executeScript("PF('dv_dialog').show()");

}

public StreamedContent getContent() {
    return content;
}

public void setContent(StreamedContent content) {
    this.content = content;
}

The error message

PDF.js v1.10.88 (build: c62a1938)
Message: Missing PDF "http://localhost:8080/hoft/javax.faces.resource/dynamiccontent.properties.xhtml?ln=primefaces&v=6.2&pfdrid=1a55ef4c9448951fae5f493579cf80e1&pfdrt=sc&pfdrid_c=true&download=report.pdf".

have anyone clue, what is wrong with my code? it is actually the code in demo showcase Primeface-Extensions with modification.

My project use iframe and the documentviewer will display in a popup dialog. I also tried with @SessionScoped and @ViewScoped, but have no luck.

If I try it in stand alone project, it works (without iframe). May be someone can give clues, how to debug to find the problem.

Please help.... Thank you.

I get error message

pdf.viewer.js.xhtml?ln=primefaces-extensions&v=6.2.9:17581 GET http://localhost:8081/hoft/javax.faces.resource/dynamiccontent.properties.xhtml?ln=primefaces&v=6.2&pfdrid=3c954d24c76c30714a581092c23e1489&pfdrt=sc&pfdrid_c=true&download=report.pdf 404
PDFFetchStreamReader @ pdf.viewer.js.xhtml?ln=primefaces-extensions&v=6.2.9:17581
getFullReader @ pdf.viewer.js.xhtml?ln=primefaces-extensions&v=6.2.9:17527
(anonymous) @ pdf.viewer.js.xhtml?ln=primefaces-extensions&v=6.2.9:4388
(anonymous) @ pdf.viewer.js.xhtml?ln=primefaces-extensions&v=6.2.9:1002
resolveCall @ pdf.viewer.js.xhtml?ln=primefaces-extensions&v=6.2.9:1001
_createStreamSink @ pdf.viewer.js.xhtml?ln=primefaces-extensions&v=6.2.9:1266
MessageHandler._onComObjOnMessage @ pdf.viewer.js.xhtml?ln=primefaces-extensions&v=6.2.9:1094
pdf.viewer.js.xhtml?ln=primefaces-extensions&v=6.2.9:19633 Uncaught (in promise) Error: Missing PDF file.
    at pdf.viewer.js.xhtml?ln=primefaces-extensions&v=6.2.9:19633
Ndrik7
  • 103
  • 13
  • result code 404 – Ndrik7 Oct 24 '18 at 05:33
  • Does the message occure on page load or button press? If present, please provide the Exceptio with full stack trace. Where's the IFrame you mentioned in braces? – Selaron Oct 24 '18 at 06:31
  • it come after button press. I paste the error message. – Ndrik7 Oct 24 '18 at 08:11
  • This looks like the error log from the web Browser. Does the servlet container (server side) output or log Java Exceptions with stack traces when pressing the button? – Selaron Oct 24 '18 at 08:48
  • I don't think you can do what you are doing. If you look at the DocumentViewer component it actually renders and IFRAME to put the doc viewer in. You using an IFRAME now inside an IFRAME which must be messing it up? If it works standalone then you have to keep removing one variable at a time until you figure out what is breaking it. – Melloware Oct 24 '18 at 11:13
  • @Selaron I can not find any useful information in log file. – Ndrik7 Oct 24 '18 at 11:44
  • @Melloware how about using `` from PrameFaces? will it work for me? Actually I just want to display generated report in PDF. Until now it works to display PDF in a new window, but the URL of the new window shows the full xhtml path. To this reason, I want to hide this URL for security. Do you have any advice? or may be someone else? Thank you. – Ndrik7 Oct 24 '18 at 11:44
  • I try to use `` and it give me same output, 404 not found. – Ndrik7 Oct 24 '18 at 11:50
  • I don't think, it is iframe problem. I try documentviewer and media in iframe and stand alone project, it works. May be any advice why don't work in my project? – Ndrik7 Oct 24 '18 at 12:43
  • I would say go from a working project that works with DocumentViewer, and keep adding 1 variable at a time until you narrow down what causes the error. – Melloware Oct 25 '18 at 11:02
  • After work for hours and days and still no luck, I decided to use PrettyFaces. So I can hide the url to display report pdf in new window / tab. – Ndrik7 Nov 04 '18 at 20:50

1 Answers1

-1

I tried this using:

  1. Java EE 7
  2. GlassFish 4.1.2
  3. PrimeFaces 6.2
  4. PrimeFaces-Extensions 6.2.9

At the bean (class) code:

@ManagedBean
@ApplicationScoped
public class DocumentViewerController {

The scope is @ApplicationScoped. I have a private StreamedContent attribute. And two main public methods:

First method: It's called from actionListener attribute of a p:commandButton. The method receive a parameter (in my case).

public void onPrerender(Tramite tramite) {    
    tramiteSelected = tramite;
    numeroTramite = tramite.getNumero();
    contrato = tramite.getContrato();
} 

Second method: It's used from a pe:documentViewer inside a dialog component, like this:

<pe:documentViewer id="certificadoViewer"
                   height="500px"
                   width="750px"
                   cache="false"
                   value="#{documentViewerController.certificado}"
                   download="certificado_#{documentViewerController.numero}_#{documentViewerController.contrato}.pdf" />

Note: The 2nd method works like a property (getter and setter). THAT'S THE TRICK.

The final code from my project is:

# Bean (DocumentViewerController.java):

package com.epmrpsd.certificado.consulta.controladores;

import com.epmrpsd.certificado.consulta.controladores.util.JsfUtil;
import com.epmrpsd.certificado.consulta.entidades.Tramite;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import javax.faces.bean.ApplicationScoped;
import javax.faces.bean.ManagedBean;
import org.primefaces.model.DefaultStreamedContent;
import org.primefaces.model.StreamedContent;

/**
 *
 * @author pbonilla
 */
@ManagedBean
@ApplicationScoped
public class DocumentViewerController {

    private StreamedContent content;
    private Integer numeroTramite;
    private Integer contrato;
    private Tramite tramiteSelected;

    // Path where the file exists
    private String pdfPathDirectory = "C:\\Users\\<user>\\certificados\\";

    public void onPrerender(Tramite tramite) {

        tramiteSelected = tramite;
        numeroTramite = tramite.getNumero();
        contrato = tramite.getContrato();
    }

    public StreamedContent getCertificado() {

        InputStream stream = null;
        try {
            File file = new File(pdfPathDirectory + numeroTramite + "_" + contrato + ".pdf");

            if (file.exists()) {
                stream = new FileInputStream(file);
            } else {
                JsfUtil.addErrorMessage("Error", "No se ha encontrado el archivo");
            }
            this.content = new DefaultStreamedContent(stream, "application/pdf");
        } catch (FileNotFoundException fnfex) {
            JsfUtil.addErrorMessage("Error", "No se ha encontrado el archivo. Error: " + fnfex.getMessage());
            fnfex.printStackTrace();
        } catch (Exception e) {
            JsfUtil.addErrorMessage("Error", "Se ha generado un error al cargar el certificado. Error: " + e.getMessage());
            e.printStackTrace();
        }

        return content;
    }

    public void setCertificado(StreamedContent contenido) {
        content = contenido;
    }

    public Tramite getTramiteSelected() {
        return tramiteSelected;
    }

    public void setTramiteSelected(Tramite tramiteSelected) {
        this.tramiteSelected = tramiteSelected;
    }

    public Integer getNumero() {
        return numeroTramite;
    }

    public void setNumero(Integer numeroTramite) {
        this.numeroTramite = numeroTramite;
    }

    public Integer getContrato() {
        return contrato;
    }

    public void setContrato(Integer contrato) {
        this.contrato = contrato;
    }

}

# View (index.xhtml):

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://xmlns.jcp.org/jsf/html"
      xmlns:f="http://xmlns.jcp.org/jsf/core"
      xmlns:p="http://primefaces.org/ui"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:pe="http://primefaces.org/ui/extensions">
    <h:head>
        <title>Consulta de Certificados Digitales</title>
        <h:outputStylesheet library="css" name="epmrpsd.css" />
        <h:outputStylesheet library="webjars" name="font-awesome/5.5.0/css/all-jsf.css" />
        <h:outputStylesheet library="css" name="jsfcrud.css"/>
        <h:outputScript library="js" name="jsfcrud.js"/>
        <link rel="shortcut icon" type="image/png" href="#{resource['images/logo.png']}"/>
    </h:head>
    <h:body>
        <div id="background" style="position: fixed;">
            <h:form id="formCertificados">

                <div class="ui-g" style="margin-top: 25px;">
                    <div class="ui-g-1"></div>
                    <div class="ui-g-10">
                        <p:growl id="mensajes" />

                        <Extra code> ...

                        <p:outputPanel id="pnlCertificado">
                            <p:dataTable id="tramitesTable"
                                         value="#{tramiteController.items}"
                                         var="tramite"
                                         rowKey="#{tramite.id}"
                                         selectionMode="single"
                                         selection="#{tramiteController.selected}"
                                         emptyMessage="No se encontraron trámites con los criterios dados"
                                         rows="10"
                                         rowsPerPageTemplate="10,20,30,40,50">

                                <p:column headerText="Número Trámite" >
                                    <h:outputText value="#{tramite.numero}" />
                                </p:column>

                                <p:column headerText="Descripción" >
                                    <h:outputText value="#{tramite.tipo.descripcion}" />
                                </p:column>

                                <p:column headerText="Número Contrato" >
                                    <h:outputText value="#{tramite.contrato}" />
                                </p:column>

                                <p:column style="text-align: center" headerText="Acción" >
                                    <center>
                                        <p:commandButton id="viewCertificado"
                                                         styleClass="ui-priority-primary"
                                                         value="Ver certificado"
                                                         actionListener="#{documentViewerController.onPrerender(tramite)}"
                                                         update=":ViewCertificadoForm"
                                                         oncomplete="PF('ViewCertificadoDialog').show()" />
                                    </center>
                                </p:column>
                            </p:dataTable>
                        </p:outputPanel>
                    </div>
                    <div class="ui-g-1"></div>
                </div>
            </h:form>

            <ui:include src="ViewCertificado.xhtml"/>
        </div>
    </h:body>
</html>

And the final component for the view is (ViewCertificado.xhtml):

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html>
<html 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:p="http://primefaces.org/ui"
      xmlns:pe="http://primefaces.org/ui/extensions">

    <ui:composition>

        <p:dialog id="ViewCertificadoDlg"
                  widgetVar="ViewCertificadoDialog"
                  modal="true"
                  resizable="false"
                  appendTo="@(body)"
                  header="Certificado #{documentViewerController.contrato}">
            <h:form id="ViewCertificadoForm">
                <h:panelGroup id="display">
                    <p:panelGrid columns="1" rendered="#{documentViewerController.tramiteSelected != null}">
                        <pe:documentViewer id="certificadoViewer"
                                           height="500px"
                                           width="750px"
                                           cache="false"
                                           value="#{documentViewerController.certificado}"
                                           download="certificado_#{documentViewerController.numero}_#{documentViewerController.contrato}.pdf" />
                    </p:panelGrid>
                    <p:commandButton value="Cerrar" onclick="ViewCertificadoDialog.hide()"/>
                </h:panelGroup>
            </h:form>
        </p:dialog>

    </ui:composition>
</html>