Review: We had to estimate a PDF generation task during our last sprint planning meeting. We received a rough layout template from our costumer and the service classes to provide the required data were also already present. Nevertheless, we estimated the associated tickets amazingly high. No developer in the team had experience with iText before. However, everyone had heard scary stories from other developers about iText. A qoute floated in our ears: “If you work with iText, sooner or later you have to read the specification of the pdf format.”
After some online research and several interviews with other project teams of codecentric I would like to describe a very simple, robust and primarily fast way to generate PDFs with iText. With this approach, the ticket mentioned above was solved in a quarter of the estimated time and the fear of iText in the team disappeared.
iText offers a lot of possibilities to create PDFs completly using its API, containing all lines, pictures, fixed texts and much more. But this approach may get very complex and generates a lot of error-prone code. It’s much easier to create a template with defined content-fields. This Template will be saved as a PDF with a formular and can be watched for example in the Adobe Reader at any time. Another advantage is the possibility to show your customer the empty pdf and discuss the layout before implementing the logic which fills in the data.
Part 1 – Creation of PDF-formulars
PDF-formulars can be created very easy with OpenOffice. I used OpenOffice Draw in my example, but the approach also works with OpenOffice Writer or Calc. Just create a new document and fill it with texts, colours or lines as desired. After the layout has been finished, you have to define the formular fields. Therefore it’s helpful to activate the toolbars for Formular Design und Formular Control Elements via View -> Toolbars (Sorry – I don’t know the exact english translations, because I use the german version of Open Office). You can activate the Formular Design Mode using one of the new icons. After that, you can choose for example a textfield from the Formular Control Elements and insert it into your document. The properties of the textfield can be changed with a right-click. The following properties are interesting:
- Name : This name will be used in the Java code to reference the control element and fill it with data.
- Border : Default is 3D-Look – In most cases the setting without Border should work better.
- Background-Colour, Alignment, Font: You can define the layout with these properties. Layout data in Java code is not necessary!
- Text-type: Default should be one-line, but if you need to fill in the field with line-breaks from Java code, you have to use multi-line.
It’s very hard to spot the formular fields as soon as they have no border. The Formular-Navigator helps to solve this problem.
After creating layout and formular fields the document can be exported to a PDF. This can be done by File –> Export as PDF. Be sure to activate the checkbox Create PDF-Formular in the following dialog.
Part 2 – Fill the PDF-Formular with iText
In my example I use iText in version 2.1.7, because in later versions iText has a more strict license.
First read the created PDF template…
PdfReader pdfTemplate = new PdfReader(pdfTemplateFile);
… and create a PdfStamper with a OutputStream.
ByteArrayOutputStream out = new ByteArrayOutputStream(); PdfStamper stamper = new PdfStamper(pdfTemplate, out);
We have to tell the PdfStamper to flatten the form, because there should be no formular fields in the created PDF.
To finish the work we can just fill the fields…
stamper.getAcroFields().setField("name", "Daniel Reuter"); stamper.getAcroFields().setField("adress", "Merscheider Str.1 – 42699 Solingen"); stamper.getAcroFields().setField("dates", "2008\n2009\n2010\n"); stamper.getAcroFields().setField("titles", "JAX\nDevoxx\nJavaOne\n");
…and close all the opened resources.
From my point of view, this is a very simple and easily understandable approach to create PDFs using iText. Certainly there will be scenarios in which the described way won’t work, for example if you have to implement dynamic layouts. However, I would always try to use a PDF template as a basis.