<img alt="" src="https://secure.leadforensics.com/150446.png " style="display:none;">

Integrating Apache FOP with Java project to generate .PDF files

Debasmita Sahoo Apr 11, 2012

Apache FOP Java Technology

Apache FOP

FOP (Formatting Objects Processor) is from the apache group. It is said to be the print formatter driven by XSL formatting objects (XSL-FO). FOP can be downloaded from http://xmlgraphics.apache.org/fop/

Its ability to convert XSL files (*.fo) to PDF certainly makes it worth mention. Basically FOP is great for template based PDF generation. Simple programs can fetch data from any data source and populate such a template, and generate PDF’s on the fly !

XSL-FO (Extensible Stylesheet Language Formatting Objects)

XSL-FO is a language for formatting XML data for output to screen, paper or other media

Required Jars

  1. xml-apis.jar
  2. jaxb-api-2.2.3.jar
  3. fop-1.0.jar
  4. avalon-framework-4.1.3.jar
  5. commons-io-2.0.1.jar
  6. commons-logging-1.0.3.jar
  7. xmlgraphics-commons-1.4.jar

Steps to generate PDF

Step 1: Create the template(.xsl) for formatting the output in resource folder

Step 2: Convert the java object to XML

Step 3: call the transformer code to convert the xml source to pdf using the xsl template.

Example Code:

template.xsl

<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.1"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format"
                xmlns:barcode="org.krysalis.barcode4j.xalan.BarcodeExt" xmlns:common="http://exslt.org/common"
                xmlns:xalan="http://xml.apache.org" exclude-result-prefixes="barcode common xalan">
                <xsl:template match=" EmployeeData">
                                <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
                                                <fo:layout-master-set>
                                                                <fo:simple-page-master master-name="simple"
                                                                                page-height="20cm" page-width="10.5cm" margin-left="0.2cm"
                                                                                margin-right="0.2cm">
                                                                                <fo:region-body margin-top="0.5cm" />
                                                                </fo:simple-page-master>
                                                </fo:layout-master-set>
                                                <fo:page-sequence master-reference="simple">
                                                                <fo:flow flow-name="xsl-region-body">

                                                                                <fo:block font-family="Arial" font-size="7pt" font-weight="normal">
                                                                                                <fo:table>
                                                                                                                <fo:table-column column-number="1" column-width="3cm" />
                                                                                                                <fo:table-column column-number="2" column-width="2cm" />
                                                                                                                <fo:table-column column-number="3" column-width="5cm" />
                                                                                                                <fo:table-body  height="10cm">
                                                                                                                                <xsl:for-each select="./employeeList/employee">
                                                                                                                                                <fo:table-row border="solid 0.1mm black">

                                                                                                                                                                <fo:table-cell text-align="left">
                                                                                                                                                                                <fo:block>
                                                                                                                                                                                                <xsl:value-of select="name" />
                                                                                                                                                                                </fo:block>

                                                                                                                                                                </fo:table-cell>
                                                                                                                                                                <fo:table-cell text-align="center">
                                                                                                                                                                                <fo:block>
                                                                                                                                                                                                <xsl:value-of select="employeeId" />
                                                                                                                                                                                </fo:block>

                                                                                                                                                                </fo:table-cell>
                                                                                                                                                                <fo:table-cell text-align="left">
                                                                                                                                                                                <fo:block>
                                                                                                                                                                                                <xsl:value-of select="address" />
                                                                                                                                                                                </fo:block>

                                                                                                                                                                </fo:table-cell>

                                                                                                                                                </fo:table-row>
                                                                                                                                </xsl:for-each>

                                                                                                                </fo:table-body>
                                                                                                </fo:table>
                                                                                </fo:block>

                                                                </fo:flow>
                                                </fo:page-sequence>
                                </fo:root>
                </xsl:template>
</xsl:stylesheet>

EmployeeData.java

import java.util.List;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;

/**
 *
 */

/**
 * @author Debasmita.Sahoo
 *
 */
@XmlRootElement(name="EmployeeData")
public class EmployeeData {
	public EmployeeData () {
	}

	private List employeeList;

	@XmlElementWrapper(name = "employeeList")
	@XmlElement(name = "employee")
	public List getEmployeeList() {
		return employeeList;
	}
	public void setEemployeeList (List employeeList) {
		this.employeeList = employeeList;
	}

}

Employee.java

/**
 * @author Debasmita.Sahoo
 *
 */
public class Employee {
	private String name;
	private String employeeId;
	private String address;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
	public String getEmployeeId() {
		return employeeId;
	}

	public void setEmployeeId(String employeeId) {
		this.employeeId = employeeId;
	}
	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}

}

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URL;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.stream.StreamSource;

import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.apps.Fop;
import org.apache.fop.apps.FopFactory;
import org.apache.fop.apps.MimeConstants;

public class PDFHandler {
	public static final String EXTENSION = ".pdf";
	public String PRESCRIPTION_URL = "template.xsl";

	public String createPDFFile(ByteArrayOutputStream xmlSource, String templateFilePath) throws IOException {
		File file = File.createTempFile("" + System.currentTimeMillis(), EXTENSION);
		URL url = new File(templateFilePath + PRESCRIPTION_URL).toURI().toURL();
		// creation of transform source
		StreamSource transformSource = new StreamSource(url.openStream());
		// create an instance of fop factory
		FopFactory fopFactory = FopFactory.newInstance();
		// a user agent is needed for transformation
		FOUserAgent foUserAgent = fopFactory.newFOUserAgent();
		// to store output
		ByteArrayOutputStream pdfoutStream = new ByteArrayOutputStream();
		StreamSource source = new StreamSource(new ByteArrayInputStream(xmlSource.toByteArray()));
		Transformer xslfoTransformer;
		try {
			TransformerFactory transfact = TransformerFactory.newInstance();

			xslfoTransformer = transfact.newTransformer(transformSource);
			// Construct fop with desired output format
			Fop fop;
			try {
				fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent, pdfoutStream);
				// Resulting SAX events (the generated FO)
				// must be piped through to FOP
				Result res = new SAXResult(fop.getDefaultHandler());

				// Start XSLT transformation and FOP processing
				try {
					// everything will happen here..
					xslfoTransformer.transform(source, res);

					// if you want to save PDF file use the following code
					OutputStream out = new java.io.FileOutputStream(file);
					out = new java.io.BufferedOutputStream(out);
					FileOutputStream str = new FileOutputStream(file);
					str.write(pdfoutStream.toByteArray());
					str.close();
					out.close();

				} catch (TransformerException e) {
					e.printStackTrace();
				}
			} catch (FOPException e) {
				e.printStackTrace();
			}
		} catch (TransformerConfigurationException e) {
			e.printStackTrace();
		} catch (TransformerFactoryConfigurationError e) {
			e.printStackTrace();
		}
		return file.getPath();
	}

	public ByteArrayOutputStream getXMLSource(EmployeeData data) throws Exception {
		JAXBContext context;

		ByteArrayOutputStream outStream = new ByteArrayOutputStream();

		try {
			context = JAXBContext.newInstance(EmployeeData.class);
			Marshaller m = context.createMarshaller();
			m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
			m.marshal(data, outStream);
		} catch (JAXBException e) {

			e.printStackTrace();
		}
		return outStream;

	}

}

Call the PDF handler Code

TestPDF.java

import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
/**
 * @author Debasmita.Sahoo
 *
 */
public class TestPDF {
	public static void main(String args[]){
		System.out.println("Hi Testing");
		ArrayList employeeList = new ArrayList();
		String templateFilePath ="D:/Projects/Sample/pdftest/src/";

		Employee e1= new Employee();
		e1.setName("Debasmita1 Sahoo");
		e1.setEmployeeId("10001");
		e1.setAddress("Pune");
		employeeList.add(e1);

		Employee e2= new Employee();
		e2.setName("Debasmita2 Sahoo");
		e2.setEmployeeId("10002");
		e2.setAddress("Test");
		employeeList.add(e2);

		Employee e3= new Employee();
		e3.setName("Debasmita3 Sahoo");
		e3.setEmployeeId("10003");
		e3.setAddress("Mumbai");
		employeeList.add(e3);

		EmployeeData data = new EmployeeData();
		data.setEemployeeList(employeeList);
		PDFHandler handler = new PDFHandler();

		try {
			ByteArrayOutputStream streamSource = handler.getXMLSource(data);

			handler.createPDFFile(streamSource,templateFilePath);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

Similar Blog

e-Zest is a leading digital innovation partner for enterprises and technology companies that utilizes emerging technologies for creating engaging customers experiences. Being a customer-focused and technology-driven company, it always helps clients in crafting holistic business value for their software development efforts. It offers software development and consulting services for cloud computing, enterprise mobility, big data and analytics, user experience and digital commerce.