Apache FOP Integration with Eclipse and OSGi
Apache FOP is an open source print processor driven by XSL formatting objects (XSL-FO). It can be quite useful to transform data objects into a PDF for example. However it turned out to be somewhat cumbersome to get it integrated into PDE and finally up and running as OSGi Service.
Because of this I provided a P2 repository that contains the necessary bundles within a single feature. This way PDE target setup got much easier. The following sections explain how to use it.
Apache FOP
As stated by the documentation Apache FOP ‘is a Java application that reads a formatting object (FO) tree and renders the resulting pages to a specified output. Output formats currently supported include PDF, PS, PCL, AFP, XML (area tree representation), Print, AWT and PNG, and to a lesser extent, RTF and TXT. The primary output target is PDF’.
Of course it is possible to embed the processor into a Java program. Based on on JAXP, Apache FOP relies on SAX events to receive the XSL-FO input document. A basic usage snippet looks somewhat like this:
InputStream in = ... // the fo tree to process OutputStream out = ... // pdf destination FopFactory fopFactory = FopFactory.newInstance(); try { Fop fop = fopFactory.newFop( MimeConstants.MIME_PDF, out ); TransformerFactory factory = TransformerFactory.newInstance(); Transformer transformer = factory.newTransformer(); Source source = new StreamSource( in ); Result result = new SAXResult( fop.getDefaultHandler() ); transformer.transform( source, result ); } finally { out.flush(); }
For a detailed explanation of Apache FOP embedded usage please refer to the online documentation.
Dependency Hell
While the snippet looks straight forward, integration in Eclipse/OSGi was not that easy. Maybe I behaved stupidly, but it took me almost two days to assemble a target definition, which eventually did the trick.
To avoid this problem in the future and give others who may run into the same trap a better start, I created the P2 repository mentioned at the beginning. In order to use it simply add the repository location as Software Site to your Eclipse target definition:
Now define the dependencies of the bundle that should contain the processor. These dependencies are org.apache.servicemix.bundles.fop
and org.apache.servicemix.bundles.xmlgraphics-commons
:
Once those are in place the code above compiles. It is easy to develope a service class having a format
method for PDF generation with a signature as shown here:
public class FopService { private final FopFactory fopFactory; public FopService() { this.fopFactory = FopFactory.newInstance(); } public void format( InputStream input, OutputStream output, InputStream stylesheet ) { [...] // similar transformation code like above } }
I knitted a simple usage example project that provides more details. The project contains an example.target that already integrates Apache FOP. After importing the project, resolve and set its target definition in your Eclipse workspace. Run the ‘FOP example’ launch configuration. Last but not least open a browser and go to the URL http://localhost:10080/services/pdf
.
A freshly created PDF should be ready for download:
The xml and xsl documents used to generate the PDF are the same as those processed by the ExampleXML2PDF class of the embedding Apache FOP examples. The PDF contains a simple listing of members of a fictive development team.
Be aware that ‘Apache FOP may currently not be completely thread safe’ (see the Multithreading FOP section, of the
Apache FOP: Embedding). Naturally a real world scenario must take this into account, in particular if running in a multithreaded server environment.
Wrap Up
Although the road was a bit bumpy at the beginning the Apache FOP integration works fine now. So if you want to checkout the example by yourself, it is located at https://github.com/fappel/FOP
The P2 repository is hosted at http://fappel.github.io/FOP/
In case you run into a problem or have any questions or suggestions you might add an issue at the GitHub project or leave a comment in the section below.
Reference: | Apache FOP Integration with Eclipse and OSGi from our JCG partner Frank Appel at the Code Affine blog. |