byte bohemian

21Aug/090

Creating dynamic PDF, or another reason to like Apache Tapestry

I am using Apache Tapestry 5 on my job since February of this year. Today was another of these days when I am pretty sure why it is a good idea to use this framework.
Last week we started the new sprint for the scoyo feature release which will be release on end of September. A website feature may require the dynamic creation of PDF files so I evaluated the possibilities of the "The Flying Saucer Project", a XML/XHTML/CSS 2.1 rendering engine.

I already made some experiences with the Flying Saucer on another job and it is still a very nice framework for PDF creation. For me, a major advantage of "The Flying Saucer" over other PDF creation frameworks, like XSLT and FOP, in the Web world is the homogenous technology mix.

"The Flying Saucer Project" create PDF from XML/XHTML pages using CSS style sheets. All technologies known to the web designer that gives your web site this pretty look. I guess it's okay when you say, that XSLT and FOP is the more powerful technology mix, but styling pages on this technology mix is not a simple task to do.

So back to the initial topic: A basic ingredient which is needed to create PDFs with the "The Flying Saucer Project" is some XHTML. In our project at scoyo we wanted to use Apache Tapestry to create this XHTML.

After taking a closer look to the Apache Tapestry rendering pipeline I found out, that the PageResponseRenderer is the perfect place to hook up the PDF creation into the rendering process. On the one hand the PageResponseRenderer uses a MarkupWriter to create the (X)HTML content from the current Page instance. On the other hand the PageResponseRenderer is responsible for writing the generated content into the server response.

Using the Apache Tapestry own IoC mechanism it's quite an easy task to decorate the Tapestry PageResponseRenderer implementation. It's a beautiful mechanism when you understood how it works. Okay I guess using the 5.1 version of tapestry it would be better to advice the renderPageResponse(...) method, but I had not enough time to get familiar with it yet.

One real big plus on Apache Tapestry is the implementation. Every function is well encapsulated into separate services. And the service implementing classes are very short and almost always on consistent level of abstraction. So you easily understand how a service works and you are able to copy and extend the service functions. So I extended PageResponseRenderer to determine if a page creates XHTML output which should be transformed to PDF. If no PDF should be created my PageResponseRenderer simply delegates to the original Tapestry instance.

When the page wants to create PDF my PageResponseRenderer buffers the created content and redirects it into the ITextRenderer of the a href="https://xhtmlrenderer.dev.java.net/">"The Flying Saucer". Okay this sounds more nice, than it actually is. The content is stored into a ByteArrayOutputStream and re-parsed by the standard JDK XML parser for further processing by the ITextRenderer. But I guess the we will live with the performance impact until it gets a real issue.

So long explanation short story. The whole thing worked out great! It took me like two to three hours to implement a first prototype. In out web application. This also includes the embedding of custom fonts into the PDF and a nice discovery of pages to render into PDF, via custom annotations using the component model meta-data facilities and a ClassTransformationWorker.

Web development can be so easy when you are using Apache Tapestry. On an earlier project we used a similar architacture with JSP and the "The Flying Saucer". I guess it took us ten times the effort to establish an equal infrastructure using JSF and the Java Servlet API ...

Kommentare (0) Trackbacks (0)

Zu diesem Artikel wurden noch keine Kommentare geschrieben.


Kommentar schreiben


Trackbacks are disabled.

Search engine optimization by SEO Design Solutions