RSS feed
<< Lucene gets a performance boost | Home | Yes, cross-platform Single Sign-On for Java Webapps is possible. >>

Implementing decorator templates with Apache Velocity

A couple of years ago I started replacing JSPs with Apache Velocity for generating  HTML in my web applications. The simplicity and speed of Velocity was very appealing to me compared to the complex beast that JSP is.

Compiling JSP to Java, then to byte code and then loading and running it as class obviously must have seemed like a good idea to those who came up with it. For me, it's always been crazy talk.

When designing HTML templates reusability is always an important goal. You want to define your header, menu and footer once and then reuse them for both your front page, article page or about page.

The no-brainer solution to this is to use tags or directives to include common snippets of HTML into the final page. JSP supports this with the @include syntax  or the <jsp:include/> tag:



Like any no-brainer solution this one is not very smart. You end up with brittle and inflexible templates where you need to touch all your templates to do any kind of structural changes to your main design.

A much better solution is to apply the decorator pattern. Instead of pulling in common pieces of HTML everywhere you need them you just specify what's special with this particular page and then apply a decorator template to it. This template will take care of creating the actual design.

There's no built in support for creating decorator templates in JSP, so what used to do was to create a small taglib that would let me define a snippet of HTML as a section and then output that snippet in the design template. I know a lot of people use Sitemesh for this, but I found the taglib solution worked very well for my purpose.



Like JSP, Velocity has no built in support for creating decorator templates. At first I just accepted this situation as a trade-off. With Velocity being so simple, I'd just have to learn to live with all the #incude directives right?

That was until I discovered that Velocity actually has support for custom directives. So now all I had to do was to create a directive that rendered it's body into a string and stored that in the context for later use. This turned out to be very easy:

public class Section extends Directive {
    public String getName() {
        return "section";
    }

    public int getType() {
        return BLOCK;
    }

    public boolean render(InternalContextAdapter context, Writer writer, Node node) throws IOException, ResourceNotFoundException, ParseErrorException, MethodInvocationException {
        ASTReference nameNode = (ASTReference) node.jjtGetChild(0);
        String name = nameNode.getRootString();
        StringWriter sw = new StringWriter();
        node.jjtGetChild(1).render(context, sw);
        context.put(name, sw.toString());
        return true;
    }
}

Now I can create templates like this:

#section($content)
<h1>Content here</h1>
<p>Hello World</p>
#end

#parse("design.vm")  

Registering my #section directive with Velocity was easy. Adding a userDirective property with the name of the directive class did the trick.

Seeing how easy this is and how much better it made my template system I'm amazed that Velocity doesn't already have something like this in its core.


Re: Implementing decorator templates with Apache Velocity

What's wrong with Velocity's layout? I am using layouts together with templates and it does the trick

Re: Implementing decorator templates with Apache Velocity

I'm not sure I understand what you're referring to with "Velcoity's templates".

Perhaps you could share a bit more details about how you go about creating layouts with Velocity?


Add a comment Send a TrackBack