How to Create PDF Reports Using Atlassian JIRA

The Brief – Enhancing Atlassian JIRA plugins with PDF export functionality using Apache FOP

Enhancing Atlassian JIRA plugins

Clearvision were approached by a client to write a custom Atlassian JIRA reporting plugin which would allow them generate a report from JIRA as a PDF. They also requested that PDF to have specific page formatting; such as page breaks between sub headings; not present in the generated HTML report displayed within JIRA.

It should be said that Atlassian JIRA is a great platform to extend (the best platform I’ve worked with) and the JIRA reports functionality is no exception.

However, the current JIRA reports plugin module has one major drawback. It only allows initial output as an HTML web page embedded within the JIRA interface, with an additional option (if it is enabled for the report) to be downloaded as an Excel spreadsheet. Great for your CFO, but what about the rest of us? We want the swanky HTML report as an even swankier PDF download!

Finding the right technology
With this in mind, the Clearvision development team set about finding a suitable PDF rendering technology that would both fit the clients specification needs and to allow multi-discipline development – such as the use of a front-end developer to mark-up the PDF document just like an HTML web page.

The technology the development team decided upon was Apache’s FOP (Formatting Objects Processor) Java library.

Apache FOP takes XSL-FO (Extensible Stylesheet Language Formatting Objects) files as input and produces among other formats, PDF documents as output.

XSL-FO is an XML style language used to format XML data, and thus, is natural to pick up by those already familiar with XML/HTML. It also allows developers to maintain an MVC (Model–view–controller) design pattern, with the XSL-FO acting as the “view” and the FOP processor acting as the “controller”. And just as with HTML output XSL-FO elements can be included in an Apache Velocity file, allowing you to insert any “model” data in at runtime.

Example XSL-FO
[xml]

Example XSL-FO Title

[/xml]

Using Apache FOP within your Atlassian JIRA plugin
In order to use Apache FOP within your plugin during development, add the following dependency to your pom.xml file.

pom.xml dependency
[xml]

org.apache.xmlgraphics
fop
0.94
compile

[/xml]
Apache FOP can then be used in the following manner. Where “foo.fo” is the XSL-FO input mentioned above. In this case a file name reference, but could just as easily be an Apache Velocity parser output.

Apache FOP example code (taken from the Apache FOP website)
[java]
private FopFactory fopFactory = FopFactory.newInstance();
private TransformerFactory tFactory = TransformerFactory.newInstance();

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException {
try {
response.setContentType(“application/pdf”);
Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF,
response.getOutputStream());
Transformer transformer = tFactory.newTransformer();
Source src = new StreamSource(“foo.fo”);
Result res = new SAXResult(fop.getDefaultHandler());
transformer.transform(src, res);
} catch(Exception ex) {
throw new ServletException(ex);
}
}
[/java]

Getting it to work once the plugin is installed in Atlassian JIRA!
Assuming you have written a version 2 plugin for a recent version of JIRA and installed it via the UPM (Universal Plugin Manager), chances are it installed and enabled OK and you were able to continue using JIRA as normal.

However you will invariably discover the same issue that the Clearvision development team did. Chances are the moment you take any sort of action, such as clicking on a relevant link, to produce the required PDF, you will be presented with the following error message. Hardly the swanky PDF we were expecting!

JIRA runtime error when using Apache FOP
[raw]
java.lang.LinkageError: loader constraint violation: when resolving method “javax.xml.transform.sax.SAXResult.(Lorg/xml/sax/ContentHandler;)V”
the class loader (instance of org/apache/felix/framework/ModuleImpl$ModuleClassLoader) of the current class, com/clearvision/jira/reports/CustomerReport,
and the class loader (instance of ) for resolved class, javax/xml/transform/sax/SAXResult, have different Class objects for the type orm.sax.SAXResult.
(Lorg/xml/sax/ContentHandler;)V used in the signature
[/raw]
This error essentially means that there has been a conflict between some XML processing classes that already existed as part of JIRA and those that were introduced by our plugin as part of the Apache FOP dependency.

In order to resolve the conflict, we need to instruct our plugin to use the XML processing classes that JIRA already knows about. This can be achieved using the OSGi bundle instruction which can be added directly to your atlassian-plugin.xml plugin descriptor file by nesting it inside a element, which itself is nested inside the element. The full declaration is shown below. Make sure to use *;resolution:=optional at the end of the declaration so as not to produce ClassNotFoundException‘s relating to other class dependencies within the plugin when it is installed into JIRA.

declaration
[xml]

javax.xml.parsers,javax.xml.transform,javax.xml.transform.sax,org.xml.sax,
javax.xml.transform.dom,javax.xml.namespace,org.xml.sax.ext,org.w3c.dom,

*;resolution:=optional

[/xml]
Now your plugin should run smoothly and produce the PDF export you always wanted.

Future developments
Currently this approach has only been tested in recent versions of JIRA. I.e. 5.2 +. But I see no reason why this approach wouldn’t work in any other Atlassian product such as Confluence that used the version 2 plugin framework, that is OSGi compatible.

Finally this approach currently only works with Apache FOP version 0.94. Upgrading the Apache FOP dependency to a newer version introduces the following runtime exception:

Runtime exception when upgrading to newer versions of Apache FOP
[raw]
javax.xml.transform.TransformerException: Can’t transform a Source of type javax.xml.transform.stream.StreamSource
[/raw]

Conclusion
With this functionality exporting to PDF should be simple; producing beautiful, accessible reports from JIRA. This is yet another example of how Clearvision were given a problem and through our agile software development process delivered a concise solution that was on time and within budget. For more on how Clearvision can help with the development of custom plugins like this one for Atlassian JIRA please visit our custom plugin development page.

Atlasssian expert resources

Visit our blog for expert news and articles from the Atlassian world. On our resources page you will find recorded webinars, white papers, podcasts, videos and more.

The Software Blog

Read our blog for articles offering best practice advice written by Atlassian experts, as well as the latest news concerning your software.

Software White Papers and Guides

Dive deep into Atlassian software with our white papers and guides on individual tools, partner products, services, and best practices, written by the experts.

Expert Webinars

All of our webinars are pre-recorded and available to watch on-demand. Enjoy everything from partner features to application demos and updates from Atlassian experts.

Subscribe to our Newsletter

Subscribe to our Newsletter