Decorators are the HTML page processing pipelines things that wrap pages in other pages to make more of a site experience. You’d use them to typically add masthead stuff at the top of a page, navigation panels at the left and/or right, and standardized footer stuff. It substantially works at a page-source level (on text, perhaps in streams). It also happens on the server side, before the finished page arrives in a browser, and in real-time as a page request is made (GET typically).

The idea became a framework with SiteMesh (Java) in 1998. SiteMesh borrowed from the Gang of Four design pattern Decorator for it’s implementation verbiage.

Server Side Includes

Before decorator technologies, there was Server Side Includes (SSI).

Before the likes of SiteMesh, people did these things with SSIs of which there were a few of solutions. Apache’s conventions are shown here (I assume you can read rudimentary HTML source and imagine how that’s rendered in the browser):

I’ve used colors to show where parts of the final decorated page originally came from.

Note that the snippets are not integral bits of HTML. For example a <div> may be present in the includes without a closing </div> and vice versa. That’s also not just for <div> elements. You can imagine that being hard to follow and maintain. Also the particular strategy I’ve show for SSIs (page includes “1” files which include “2” files) isn’t the only way to get the same result.

How SiteMesh works

We mentioned SiteMesh, but did not drill into what it does. It’s templates are typically complete HTML pages (whether JSP, FreeMarker, StringTemplate etc) as well as integral. It means that the first <html> element in the template and the last is </html>. That’s also true of the page being decorated, which could be successfully deployed to a browser as is (without any decoration), and if designed right should run as intended. Decoration, you could say, is transparent. Each template will contain two or three replacement variables. Again, I’ll assume you have mind-90’s understanding of HTML, and show you the flow of a single page through two decorators (with template variables ‘title’, ‘head’ and ‘body’ to become the finished product:

As before, the final finished page is complete HTML, and I’ve used colors to show where parts of the final page came from.

Full page parsing

SiteMesh uses a page-parser to perform this. It picks out the title, the rest of the <head/> element that’s not the title, and the bits between the <body> and </body> elements. It uses them to inject into the template (variable interpolation). Page parsing isn’t cost-free of course. SiteMesh will also work at run time, on undecorated pages that may have been served up non-Java technologies, despite SiteMesh being written in Java.

How does SiteMesh choose decorators?

These are classically in an external XML file, and matches to resources are made via globbing. That said, SiteMesh has alternates to that: it will obey a meta-element in the HTML, or cal be controlled programmatically.

Contrasting SiteMesh to SSIs

The critical difference between decorators as SiteMesh had it, and SSIs was that the former were integral HTML sources, and the latter were potentially just arbitrary snippets. Integral, in this context, means that the first identifiable HTML element had a matching close element in template, and in the source being decorated. The include strategy, when used for this style of site-stitching often meant mis-matched elements in each of the source files. We can’t really say that SSIs are a thing of the past, as there is still much fine-grained use of them.

Liquid

Liquid is a newer technology that does decoration, but with a slightly different technique. I’m going to discuss Liquid specifically, but it represents a range of alternates in terms of their approach.

It’s pages are integral but not complete HTML though. This design allows for the page-parsing stage to be skipped, but it prevents the page being deployed without being decorated. Actually that’s not true, most modern browsers will try to render the right thing if presented with integral HTML even if outside the HTML specification(s).

Here’s the flow of a page snippet. The bit at the top is called Front Matter, and contains a number of directives for use in the use in the production of the HTML. That’s what happens with Jekyll & Liquid together, which is the tool-chain I’m most familiar with presently. The flow of a page through templates:

As before, the final finished page is complete HTML, and I’ve used colors to show where parts of the final page came from.

Other Technologies

Tiles (an offshoot of Java’s Struts) came along in 2001, that has external declarations for which decorator to choose for a page in question.

Django (Python) has something similar to Liquid (Decorators named in the HTML to be decorated), but is more around ‘template inheritance’, which is very powerful, and outside the scope of this blog entry.

Python’s Flask does the an template inheritance thing again, and the formal marking of a $head section (making parsing easier). Decorators are named in the HTML to be decorated.

Groovy’s Grails uses SiteMesh under the hood. Indeed Java has an ecosystem of many other languages on the JVM, and dozens of templating or web-framework technologies. Many are going to work with SiteMesh as is.

Ruby on Rails has nested layouts which is ‘pull’ and similar but terser to the Front-Matter way we highlighted.

Yesod (Haskell) has Hamlet which is ‘embedded templates’ and like SiteMesh in that the decorator choice is external to the page being decorated. Yesod also introduces its own, shorter, HTML grammar, which I don’t like but many do.

.Net has Master Pages and Nested Master Pages. Joe blogged about the (then) new Master Pages stuff from Microsoft in 2004, and compared it to a port of SiteMesh for .net. Unfortunately the SiteMesh for .Net didn’t flourish. The Master Pages way, names the decorator in the page being decorated.

Push Versus Pull, Pros and Cons.

We could say that the technologies that have “which decorator” specified externally to the “to be decorated” page, are in a Push style, and the ones that somehow specify which decorator from within the page (a comment, a header, a template-grammar reference) are Pull style. There’s a second dynamic that concerns page-parsing or mere stitching of if incomplete HTML fragments.

You could argue that dealing with decorators that are whole pages, while developing the ‘surrounding’ site is much more appropriate that in would be for mere fragments. You can load them up in a real browser, if you’re willing to look past $content and $title appearing in the page, in place of real titles and content taking more space than a fraction of an inch.

There’s also a WYSIWYG point around the likes of Dreamweaver, that favors complete-HTML (parsing) types, that I’ll not drill into that, as not many people use Dreamweaver for UI work these days.

It is true that page-parsing way of sitemesh is going to handle more varied content in the <head/> section, and the hoops you have to jump through for the Liquid way are somewhat harder. But Django & Flask (if not more), have a way of marking arbitrary sections for later variable interpolation into the decorator template.

We’ve not touched on functional testing. What would be nice for any or all of these technologies, would be to swap decorators or remove decoration during an automated functional testing run.

SiteMesh versus SSI?

Easy - SiteMesh is definitely a huge advance. It’s sad to see many CMS packages today still using include strategies.

SiteMesh versus Liquid (and all like it)?

That’s not so easy. There are benefits to a lighter weight, non-parsing pipeline. You get the design-ability of integral HTML templates. Orthogonal decoration is powerful, as is the ability to flip a hypothetical switch and deploy without decoration. As mentioned before, that’s easier to implement when pages being decorated are complete, and decoration places pertinent parts of that page in another page. I’d like to see more frameworks for things the SiteMesh way, for more languages & web frameworks.

Unexplored in this blog entry

The inheritance implementations that allow more more participation in terms of the iterative cutting up of pages for injection into other templates in the pipeline.

Thanks to Joe Walnes for contributions to this blog entry :)

Feb 12, 2013: This article was syndicated by DZone



Published

February 11th, 2013
Reads:

Tags

Categories