Usability - Productivity - Business - The web - Singapore & Twins

Extracting data from Domino into PDF using XSLT and XSL:FO (Part 2)

This entry is part of the series Domino, XSL:FO and XSLT that dives into the use of XSLT and XSL:FO in IBM Lotus Domino.

In Part 1 I discussed the process of getting data from Domino to PDF using only open standards. In this part I want to start backwards: If I have valid XSL:FO, how do I get the PDF output? In a later installment I will discuss what XSL:FO is capable of and how to create it using XSLT. Finally I will discuss how to extract XML from your data source (Domino or others).
I choose the backwards approach since it is easier to understand walking from the desired output towards a stylesheet than creating a stylesheet if the result isn't clear. Bear with me for this approach.
I will use Apache FOP as my rendering engine. The Quickstart compresses the needed steps neatly into 1-2-3 (pun intended):
  1. Download
    This is the easy part. Pick one of the mirror servers and get fop-1.0-bin.zip (24M) - check if you read this later if there is a newer version. Extract it to a directory of your choice, we will import/copy what we need from there
  2. Configure
    You have choices:
    • copy the Fop files into jvm/lib/ext (bad idea)
    • import it into an NSF (twice: once for agents, once for XPages)
    • create a plug-in (good for sidebar and XPages, not good for agents)
    Having coined the term XAgent I will stick to the XPages version with import into the NSF. Time permitting I'll add a plug-in approach to this little series.
  3. Run
    The FOP website provides a good overview on general Java use as well as servlet specifics. Using that information as template it is not too hard to implement a managed bean that takes a XMLDocument and an optional Stylesheet and returns the rendered PDF as result
Since our output will be rendered by a managed bean, we need to configure it in the faces-config.xml:
    <managed-bean-name>PDF </managed-bean-name>
    <managed-bean-class>com.notessensei.fop.PDFReport </managed-bean-class>
    <managed-bean-scope>session </managed-bean-scope>
The XAgent follows the usual pattern:
var exCon = facesContext. getExternalContext ( ) ;
var response = exCon. getResponse ( ) ;
var out = response. getOutputStream ( ) ;
response. setContentType ( "application/pdf" ) ;
response. setHeader ( "Content-disposition" , "inline; filename=result.pdf" ) ;
response. setHeader ( "Cache-Control" , "no-cache" ) ;
// In this example the text in sessionScope.longText will be rendered
var written = sessionScope. longText != "" ? "<text>" +sessionScope. longText + "</text>" : null ;
// Writes the default rendering out
PDF. fopReportFromString (out ,written , null ) ;
// Stop the page from further processing;
facesContext. responseComplete ( ) ;
out. close ( ) ;
To get the Java class working I needed to import:
  1. avalon-framework-4.2.0.jar
  2. batik-all-1.7.jar
  3. commons-io-1.3.1.jar
  4. fop.jar
  5. serializer-2.7.0.jar
  6. xmlgraphics-commons-1.4.jar
The class for the PDFReport contains just some wrapper code to render "FO" or "XML with XSLT" into a PDF. It is demo code, you want to add more robust error handling. Next stop: more about FO
As usual YMMV.

Posted by on 26 April 2012 | Comments (2) | categories: Show-N-Tell Thursday XPages


  1. posted by Jeroen on Wednesday 14 August 2013 AD:
    I have been using FO to make PDF's since Notes version 5. Nowadays it is a servlet which enables you to post either a document reference or the raw data. The hard work is not so much the (java) code. It is the XSLT!!???
  2. posted by Stephan H Wissel on Wednesday 14 August 2013 AD:
    @Jeroen I 100% agree. The pattern matching way of XSLT and FO are the real challenges.

    If all you have done in your development is objects and functions, it can drive you mad. This is why a good debugger is gold (see also Part5)