Inspired by Cagatay Civici’s idea of having a phase listener rendering images I decided to replace my PDF rendering servlets from a product that I’m currently working on.

At the end of the RESTORE_VIEW phase the listener would decode the request URL and extract a managed property reference expression, create an EL expression and get the byte array for the binary document.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 public void afterPhase(PhaseEvent event) {
      String viewId = event.getFacesContext().getViewRoot().getViewId();
      if (viewId.startsWith(PDF_STREAM_VIEW_ID_PREFIX)) {
          String streamExpression = StringUtils.substringAfter(viewId, PDF_STREAM_VIEW_ID_PREFIX);
          ELContext elContext = event.getFacesContext().getELContext();

          byte[] bytes = (byte[]) event.getFacesContext().getApplication().getExpressionFactory()
                  .createValueExpression(elContext, "#{" + streamExpression + "}", byte[].class).getValue(elContext);
          if (bytes != null) {
              HttpServletResponse response = (HttpServletResponse) event.getFacesContext().getExternalContext()
                      .getResponse();
              response.setContentType("application/pdf");
              response.setContentLength(bytes.length);

              try {
                  response.getOutputStream().write(bytes);
              } catch (Exception exception) {
                  LOG.error(exception.getMessage());
              }
          }
          event.getFacesContext().responseComplete();
      }
  }

To display the binary document a matching URL needs to be generated. Here the <object> tag is used for displaying a PDF document. The URL part after /pdf/stream/ is used as a part of a value expression for referencing the actual PDF binary document (here it is managedBeanName.propertyName).

1
2
3
4
5
<p:panel>
  <object
      data="#{facesContext.externalContext.requestContextPath}/#{facesContext.externalContext.requestServletPath}/pdf/stream/managedBeanName.propertyName"
          type="application/pdf" />
</p:panel>

Comments