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 ...
- Empfehle diesen Artikel bei del.icio.us
- Digg this!
- Twittere diesen Artikel!
- Empfehle diesen Artikel bei Reddit
- Buzz up!
- Bei StumbleUpon einstellen
- Empfehle diesen Artikel bei Technorati
- Sende dies zu MySpace
- Füge hinzu zu Mister Wong
- Empfehle diesen Artikel bei Facebook
- Veröffentliche dies bei Diigo
- Empfehle diesen Artikel bei Blinklist
- Empfehle diesen Artikel bei Mixx
- Empfehle diesen Artikel bei Linkedin
- Füge hinzu zu Google Bookmarks
- Empfehle diesen Artikel bei FriendFeed
- Sende diesen Artikel einem Freund per Email
- Empfehle diesen Artikel ToMuse
- Abonniere die Kommentare für diesen Beitrag
- Sende dies zu Newsvine
- Empfehle diesen Artikel bei Devmarks
- Füge hinzu zu Izeby
- Empfehle diesen Artikel bei Tipd
- Empfehle diesen Artikel bei PFBuzz
- Sende dies nach BlogMarks
- Empfehle diesen Artikel bei Twittley
- Empfehle diesen Artikel bei Fwisp
- Moo dies bei DesignMoo!
- Sende diese Seite zu Druckerfreundlich
- Bump dies bei DesignBump
- Füge hinzu zu Ning
- Sende dies zu Identica
- Speichere diese Seite bei Xerpi
- Empfehle diesen Artikel bei Wikio
- Empfehle diese Seite bei TechMeme
- Empfehle diese Seite bei Sphinn
- Sende dies zu Posterous
- Empfehle diese Seite bei Global Grind
- Empfehle diese Seite bei Ping.fm
- Empfehle diesen Artikel bei NUjij
- Empfehle diesen Artikel bei eKudos
- Empfehle diesen Artikel bei Netvibes
- Empfehle diesen Artikel bei Fleck
- Empfehle diesen Artikel bei Blogosphere News
byte bohemian
who am I
Hi, my name is Niclas. I am a passionate software engineer working at an innovative e-learning, an 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
- @helgri Dann aber von deinen Wassergebühren ;-) 15.03.2010
- @astielau Auch blöd, dann gibt ja nix mehr zu berichten ;-) 12.03.2010
Bookmarks
- Pro Git - Pro Git Book 11.03.2010
- "The Raid" Promo 12.01.2010
- 15 Best Places for Designers to Get Free Stock Photos Online 30.11.2009
- tapestry5examples 19.11.2009
- nzakas's CSSEmbed 17.11.2009