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 ...
byte bohemian
who am I
Hi, my name is Niclas. I am a passionate software engineer working at Europes leading publisher of MMO games new challenges and certified internet and video games addict with an academic degree. I created this blog to share some of my thoughts with anyone who is interested.
I suppose most of this stuff will be internet and java related, but we will see. Critics and other kinds of feedback will be greatly appriciated.
Tweeting
- Nice to know that I am not the only one, that still isn't truly happy that Java is owned by Oracle http://j.mp/anIAyG #java #oracle 6 Stunden her
- Avoiding Nulls with Polymorphic Dispatch http://j.mp/asTd67 #Java #Programming 28.07.2010
Bookmarks
- Intuitive Time Tracking Software for Mac and Windows. 05.06.2010
- Stack Overflow 03.06.2010
- ZURB – Super Awesome Buttons with CSS3 and RGBA 18.05.2010
- Pro Git - Pro Git Book 11.03.2010
- "The Raid" Promo 12.01.2010
Blogroll
- Fischmarkt
- Frau IKO
- Massenpublikum
- scoyo Corporate Blog
- Tapestry Central
- try-catch-finally
- www.radicalmonday.de