Render JavaServer Faces xhtml for string on server

I am working with a Liferay portlet that uses PrimeFaces 5 for its user interface. A typical request renders some XHTML template and sends the resulting HTML to the client. I would like to display an XHTML file of my choice for a line in the context of a commandButton action handler.

To illustrate what I need, suppose I have the following commandButton definition:

<h:form>
    <p:commandButton value="Export as PDF" ajax="false" action="#{myBean.exportPDF}" />
</h:form>

      

Clicking on it executes the exportPDF method to support the bean. Inside this method, I am loading the content of another xhtml file into a string. This part is done and working. Now my guess is that I need to parse a string in the UIComponent hierarchy and then display that hierarchy using the current FacesContext. This is where I am now stuck.

The FacesContext has {get, set} ViewRoot methods. The current view root is what the client sees in their browser. How can I replace this view root with one generated from an arbitrary string?

As the name of the button suggests, the desired action is to send a PDF to the client. I am getting an HttpServletResponse instance, outputting the correct headers and generating the actual PDF content. I am using Flying Saucer to generate PDF and I am basically trying to generate input XHTML from JSF template. Everything already works except for the template bits. Relevant code below:

public void exportPDF() throws DocumentException, IOException {
    FacesContext ctx = FacesContext.getCurrentInstance();

    ByteArrayOutputStream buf = new ByteArrayOutputStream();
    ITextRenderer r = new ITextRenderer();
    r.setDocumentFromString(getExportXHTML(ctx));
    r.layout();
    r.createPDF(buf);

    HttpServletResponse sr = PortalUtil.getHttpServletResponse(
            (PortletResponse)ctx.getExternalContext().getResponse());
    sendPDF(sr, buf);
    ctx.responseComplete();
}

private String getExportXHTML(FacesContext ctx) throws IOException {
    StringBuilder s = new StringBuilder(4096);
    PortletRequest pr = (PortletRequest)ctx.getExternalContext().getRequest();
    PortletContext pc = pr.getPortletSession().getPortletContext();
    InputStream is = pc.getResourceAsStream("/views/pdf.xhtml");
    try {
        InputStreamReader r = new InputStreamReader(is, "utf-8");
        char[] buf = new char[4096];
        int n;
        while ((n = r.read(buf)) != -1) {
            s.append(buf, 0, n);
        }
    } finally {
        is.close();
    }
    String template = s.toString();

    return ??? // TODO: How do I render template with ctx?
}

      

solved

Found the following links that brought me closer to a working solution:

The only remaining problem was that I couldn't do anything in the action handler. ctx.getExternalContext (). getResponse () returned an ActionResponse instance, not a MimeResponse required for rendering. To get around this, I just rendered the XHTML during initial page load, but waited for the action handler to be called before converting the XHTML to PDF. A bit ineffective if the user doesn't want the PDF, but seems to work otherwise.

+3


source to share





All Articles