Integrating Apache FOP with Java project to generate .PDF files
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
- xml-apis.jar
- jaxb-api-2.2.3.jar
- fop-1.0.jar
- avalon-framework-4.1.3.jar
- commons-io-2.0.1.jar
- commons-logging-1.0.3.jar
- 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(); } } }
Related posts:
-
a coder
-
rawat
