Thoughts after Tapestry Demonstration
August 26th, 2004Last night I attended the Wisconsin Java Users Group meeting and Erik Hatcher presented Tapestry. I have been working with web technologies a long time and I have experimented with many templating and web publishing systems, so I was curious how this fairly popular application works. I have mixed thoughts on it...
First off I am impressed and agree with the goals of the Tapestry project. The top goal is to integrate the work of the software developer with the graphic designer. Since web pages must work on many combinations of platforms browsers and versions it is critical to allow a graphic artist to construct a page and implement workarounds in a way that is natural to them and does not cause rework on the part of the software developer and vice versa. Too much time is typically wasted in the conversion effort.
Having to take an HTML template which has been revised by a graphic artist and then convert it into a JSP is an area which requires a good deal of work with traditional JSP development. Ideally it would be possible to leave in code snippets or markers in the code to allow for dynamic components to remain in place while the graphic artist works and perhaps shows a mock rendering of the dyamic component.
With Tapestry there is a clear attempt to preserve and reuse the HTML documents directly while still keeping the dynamic wiring in place. This is done with an attribute in any HTML element called jwcid or the Java Web Component ID which defines the behavioral mode of that element. During the presentation I found the syntax which fills in the value for the jwcid attribute to be confusing, but it was the first time I saw it. There are these ognl values and various other things you can implement in your code in order to produce the dynamic HTML. It seems you can avoid writing any non-Tapestry code in most cases. That is all fine and dandy for some people but to me it misses the point.
Tapestry seems to make the work of the graphic designer easier but then requires the programmer to learn and understand all of these jwcid and ognl values which does not leverage their existing skills in Java. If I were to implement a templating system which is friendly to graphic artists and wysiwyg tools I would instead use simple markers which provide no additional detail and allow all of the rest of the work to be done directly in the programming language. Then the programmer can simply write Java code to fill in the content in place of those markers.
For example, I would use div and span tags with the id attribute to mark that point in the HTML for the templates drawing engine. When the template renders that page it would remove that element and everything in it and replace it with the matching dynamic content. And the graphic artist could fill mock content inside that HTML element to provide a useful example for the programmer knowing the dynamic content will replace it. As an aside, the beauty of HTML these days is that the XHTML versions are well supported in modern browsers and are valid XML so manipulating the content can be done with existing XML tools which are improving all the time.
I can envision that there could also be other enhancements, like URL corrections for links references on a page since everything has to be relative to the root and the root can change. I personally like to make every URL for each link in a template to be absolute, meaning the reference to the logo for the website would be /images/logo.gif and not just images/logo.gif. I do this mainly because in several directories below it will not be necessary to change the reference to ../../../images/logo.gif. In link references it is often necessary to alter a reference to include the root context for the web application, so if it is deployed with the /articles context it will need to prefix the above absolute URL so that it is correct. Either all anchor , link, script and other such tags will have to be adjusted by the rendering engine. It does not seem like a trivial adjustment, but some W3C documentation may help identify the standard areas which will need adjusting.
Once the engine can map URLs to templates and that template to dyamic components I would have a pretty powerful template engine. I could even create a plugin for Eclipse and IDEA to make the management of those mapping files automatic. It almost seems too easy and perhaps it is rather easy. Afterall, we are just dealing with HTML and I would not attempt to integrate all of the bells and whistles into the template engine. If the design for the template engine is simple, flexible and just works there is no limit to what it could do. Now all I have to do is the work.

August 30th, 2004 at 4:03 pm
Most users like the OGNL syntax. Simple OGNL expressions are just a sequence of property names, more complex OGNL expressions look like Java code with types stripped out.
OGNL frees you from the compile-build-deploy cycle ... using OGNL to connect your Java code to your HTML components is just plain easy.
What's hard to get across in a short presentation like mine or Erik's is all the things Tapestry does that go far, far beyond the templating angle. There's a huge amount of state management occuring for you when you use Tapestry. Further, nearly all of your wishlist are things already in Tapestry.
August 30th, 2004 at 4:18 pm
Your template engine idea comes close to the existing template engine in the RIFE framework, but instead of using DIV markers, it uses comment markers and it works with any content, not just html. Specific template factories are available for xhtml, html, xml, txt, java, sql, ... and the markers are all embedded in comments to remain invisible to the designer and still easily parseable by the framework without having to interprete an entire document model or having to require content snippets that validate. RIFE also defines two major marker kinds, blocks and values. Basically, blocks provide content and values are replaces by content. This provides the foundation for a bidirectional template engine (http://rifers.org/wiki/display/RIFE/Bidirectional+template+engine) that dramatically simplifies the template engine syntax and allows the logic to be done in plain java.
August 30th, 2004 at 6:49 pm
I should learn more about the RIFE framework. I am also interested in Cocoon. But as for the simplicity of using OGNL, I did suspect that Erik had so much to show in just one quick presentation. I think Tapestry would benefit from a more intuitive markup design. An XML snippet may be a bit easier to understand for novices. Perhaps an element named tp:table could represent a table control and various attributes in the element could provide necessary information to hook it into backend code. I do see the value in reducing the code, compile and deploy cycle down to fewer steps but the confusing syntax will put of many developers.
What I have been doing for years is leveraging the power of the Apache server to allow Server-Side Includes (SSI) to include content inside a template. I create a site with a static template then extract bits like the header, navigation and footer into fragment files. And since the SSIs also allow for including dynamic content I pull in reference to Perl scripts which have been tuned with mod_perl. It is actually a very powerful combination. it just so happens that Java provide a much richer and robust framework with the help of the Apache/Jakarta project. But like I described, the SSI directives simply acted as markers and did not have to pass along any arguments. Everything I needed could be extracted from the query string or the path info in the URL. It seems that some template engines add a bundle of features which may not be necessary.
August 30th, 2004 at 7:26 pm
Brennan - thanks for coming to my JUG presentation. There have been numerous discussions on how to tag the HTML, including the use of there standard 'id' attribute (there are issues with doing this that have surfaced) and also using XHTML and namespaces as you've mentioned in your later comment. It actually is possible to implement your own templating if you provide some low-level hooks, and I'd definitely like to see an implementation based on XHTML and namespaces be available.
There is way more involved with Tapestry than a simple SSI-like mechanism. These are true components that can interoperate with the page, visit state, and much more.
As Howard mentioned - OGNL isn't as bad as you make it sound. In fact, having light-weight expressions makes Tapestry very easy to work with and evolve applications with.
August 30th, 2004 at 10:39 pm
Erik, I agree that it would be beneficial to have an XHTML schema which would allow for a namespace for tags dedicated to inserting dynamic content, as well as including other XHTML fragments. XML already supports importing other XML fragments but editors and template engines need to support it.
For all that I have read about the evolution of HTML 3.1 to modern XHTML I do not recall anything about it simplifying the process of integrating dynamic content within HTML markup in mind. That seems like an oversight. I suppose breaking up the structure inside XHTML and exporting style and layout to CSS was the first step.
But it seems that with all of the turbulance of web standards there are now many different branches of thought which have lead to diverse techniques of web page creation. Many are still quite reliant on using TABLE tags for layout while very few seem able to promise the DIV/CSS layouts described by Jeffery Zeldman. His approach which is where XHTML is supposed to be heading lends itself to very different templating solutions.
As for the session support in Tapestry there is a great deal of value for many developers who need it but for a long time I had to rely on other means due to a load balanced server cluster which did not have any way of distributing a session across the cluster. So we developed other techniques which were sufficient and actually only took a single Class to support the solution. I always prefer the minimalist approach.
The JSF transition away from the existing JSP/JSTL approach a shame because I felt they were going down the right path. Now JSF seems like the event-based challenger to ASP.NET. And as I learn more about how classic ASP which was upgraded from a linear solution to the event-driven ASP.NET I see the very same could be done with JSPs instead of scrapping it all for JSF. Smart meta frameworks like Tapestry can layer themselves right on top of the solid base that Servlets already provide. To me the appeal of JSTL was that I could write real Java code with an well-known interface and simply configure the web application to use them. It is a simple an elegant approach which the current version of JSF has abandoned.
But now you got me going and I could keep writing on this all night, so I will just stop here. I am sure I will have much more blog entries along these lines as I learn more about ASP.NET and dig into more templating solutions in both Java and .NET. But I will be sure to give Tapestry another look. I am sure there are many hidden gems in there which make it very worthwhile. I would be very interested in decoupling some of those powerful gems so that other templating engines could leverage them and share the work in improving those components.
September 2nd, 2004 at 2:52 pm
I too was at the WJUG on Tapestry, and was reasonbly impressed with what was going on in it. However, I was dismayed to think that the HTML in the templates is totally rewritten by Tapestry. I know that whenever I've seen HTML re-written out by other tools, it whacks the structure pretty well, and ends up creating invalid HTML and non-semantic markup. And the way Tapestry encourages the programmer to write HTML by having to wrap everything you want to take action an in a 'span' tag is cumbersome and creates a lot of cruft in the HTML, not to mention it ends up also creating non-semantic HTML.
Also, the jwcid tags smacked too much of the 'tal:' syntax in Zope, which I've learned has many flaws in it which hamper regular development, despite it's other benefits. Again, you find yourself jamming programming code in non-semantic tags, even if you can later strip it out with more 'tal:'s. Similarly, Erik demonstrated how the page opened with a 'body' tag, which was then replaced with all the tags usually outside the body tag, like html, head, meta, etc., which to me seems like a dangerous tool which would allow for too many opportunities to make the code way too confusing. The programming should not be allowed to operate outside the tags which are meant to be templated.
At one point in the presentation, the there was some HTML with a tr tag, which should have been a td tag. Tapestry quietly replaced it with a td tag. This could potentially create an unmaintainable set of files, because it fails to encourage the programmers and producers to use good HTML. Say someone (not the original author) needed to edit this code, and wanted to put something on a tr tag. Well, there's one already there, so they add in the code and the page breaks because it has things which belong an the tr and on the td in the same tag. Now, since it's mixed, finding that error is more difficult.
I agree with Brennan that a great way to create a templating system would be to have it based on 'id' tags. Erik, I would like to hear what the issues that have come up with those might be. In the end, I think a template which has nothing but regular HTML that a designer/producer can manipulate would be the best method to have a presentation layer on top of business logic. Having been exposed to agency settings and seeing that designers and HTML producers usually don't want to know anything about the programming, divorcing them entirely from it is the best way to prevent mistakes, or the inevitable finger-pointing which comes up when a programmer and producer both work on a page and it doesn't work.
I would go one step further from Brennan, too. There's no need to use divs or spans exclusively. The DOM allows you to attach IDs to any element HTML. I could see how the table object in Tapestry could be applied directly to a table with an ID in HTML. In fact, it could even be applied to a tbody element, allowing the header information to be separate from the 'processed' output, if need be.
Over the last week, I've come up with this basic structure: An HTML page is created on the site. When it is called, the server searches for something like the Tapestry .page file or a Java class with the same name (say 'index.html' and 'index.class'. If found, the HTML is run through an XML parser and provided to the .class or .page file, where it could be traversed by the programmer to get to the IDs that need to be managed, leaving the rest of it alone. Information which needed to be applied to the whole page could be put in something like the applet init method (this is one place where the tal: tags in Zope page templates fall apart). There could still be a global file that would be used to maintain things like navigation, footers, breadcrumbs, etc.