This is a technique for dynamically creating and serving PDF documents.
The client requirement was to take an input value, query a database, then use the values returned to display a PDF and the name of the PDF file had to be based on the input value.
While I could find many examples for doing this, they all seemed to be confusing, incomplete or both. As we were already using iText to work with PDF files, this seemed like an obvious tool to use as part of the solution.
This example uses Servlets and iText to display the PDF and their usage is described. The full source code is available (below). The example also uses JSP, Struts 2 and CSS; I am not discussing these in detail here – the reader is welcome to investigate the source code themselves.
There are several components to this example:
- DynamicPDF.java creates the PDF and sends it to the output stream
- PDFServlet.java is the servlet to serve PDFs
- DynamicPDF.jsp takes an input and displays the PDF
- web.xml is the Servlet configuration that connects all of these together
DynamicPDF.java
public void makePDF() throws DocumentException, IOException {
BaseColor COLOR = BaseColor.BLACK;
Font NORMAL = new Font(FontFamily.HELVETICA, 36);
NORMAL.setColor(COLOR);
// create new document
Rectangle PAGESIZE = new Rectangle(PageSize.A4);
Document document = new Document();
document.setPageSize(PAGESIZE);
PdfWriter writer = PdfWriter.getInstance(document, getOs());
writer.setPdfVersion(PdfWriter.VERSION_1_3);
document.open();
document.addAuthor(“Paul Shipley”);
document.addCreationDate();
document.addCreator(“iText library”);
document.addTitle(“Dynamic PDF Servlet”);
Phrase title = new Phrase(getText(), NORMAL);
document.add(title);
// complete and close document
document.close();
}
This takes the input text [getText()] and creates a PDF from it. In a real world application this could take a customer number, query a database and generate an invoice or some other useful document.
PdfServlet.java
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
response.setContentType("application/pdf");
try {
DynamicPDF dpdf = DynamicPDF.getInstance();
dpdf.setOs(response.getOutputStream());
dpdf.makePDF();
log.info(dpdf.toString());
} catch (Exception e) {
log.error(e);
log.error(Arrays.toString(e.getStackTrace()));
}
}
This servlet uses the makePDF class to serve requests for PDFs. Note that the output stream is set to the response output stream. I found examples on the web that suggested creating a PDF in the file system and then serving that. That is NOT the way to use a web server!
The Content Type is set to “application/pdf” which will ensure that the page will be treated as a PDF (usually by having the browser display it using a PDF viewer plug-in). This must be set first, before any other output is sent or the setting will be ignored.
DynamicPDF.jsp
<div class="input">
<s:form action="refresh" method="post">
<div class="optional">
<fieldset>
<legend>Enter the text message to display</legend>
<s:textfield label="Message" name="text" labelposition="left" />
<s:submit type="button" method="execute" key="label.refresh" />
</fieldset>
</div>
</s:form>
</div>
<div class=”pdfdisplay”>
<table>
<tr>
<td><iframe
name=”IframeName”
src=”/DynamicPDFServlet/pdf/<s:text name=”text” />.pdf#toolbar=0&navpanes=0&scrollbar=0″
width=”420″ height=”594″ style=”border: 0px;”>
<p>IFrames not enabled!</p>
</iframe>
</td>
</tr>
</table>
</div>
This JSP uses Struts 2 to accept an input text string (using RefreshAction.java) and displays the resulting PDF in an IFRAME so that everything is on one page (this is for convenience; it is not necessary).
Note that the source of the IFRAME is /DynamicPDFServlet/pdf/<s:text name=”text” />.pdf which will be handled by the PdfServlet (as described next).
Note also that if the Adobe Reader plug-in is being used by the client, the toolbars will be suppressed by using #toolbar=0&navpanes=0&scrollbar=0.
web.xml
<servlet>
<description></description>
<display-name>PdfServlet</display-name>
<servlet-name>PdfServlet</servlet-name>
<servlet-class>id.paulshipley.com.au.DynamicPDF.PdfServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>PdfServlet</servlet-name>
<url-pattern>/pdf/*</url-pattern>
</servlet-mapping>
This Servlet configuration has a url mapping that directs all requests in the form of /pdf/* to it. So a request like /pdf/testing.pdf will be directed to the PdfServlet to be dynamically created yet will appear to be a static file on the web server.
Resources
Download the complete source here DynamicPDFServlet.war
References
iText in Action 2E, Chapter 9: Integrating iText in your web applications http://itextpdf.com/book/chapter.php?id=9
What is servlet mapping? http://javapapers.com/servlet/what-is-servlet-mapping/
PDF Open Parameters PDFOpenParameters.pdf