Java: June 2008 Archives

Faster FreeMarker

|

If Spring's MVC framework has a failing, it is its lack of opinion. Unlike the new breed of web application frameworks led by Ruby on Rails, Spring refuses to tell you what technologies you should use. You want JSP? That's fine. JSF will work too. Maybe Velocity? No problem. Excel, PDF, even old school print statements.

The default view technology still seems to be JSP, although these days you won't get far without also using the annoyingly verbose JSTL tag libraries. I must admit that the concept of JSP pages has always appealed to me. Flip the coding problem inside out. Focus on the large blocks of static text and throw in a dash of dynamic functionality when needed. Once you're done, the compiler will create the servlet that you would have written.

For some reason, however, I've never been impressed with the results of JSP. The code generated by the compiler seems a little too clunky. The class loader behaves in unexpected ways. And the performance just doesn't seem to be there.

Templating languages like Velocity and FreeMarker, on the other hand, seem like exactly the wrong approach. Too much introspection, too much wrapping, too much dynamicism, too much magic. And yet, strangely, it doesn't seem to matter. After putting FreeMarker through its paces, I finally was able to come to believe that I could be happy using it.

Why choose FreeMarker over Velocity? Performance must be key to Velocity, shouldn't it? Speed is in its name? I haven't used Velocity enough to really give it a fair chance. FreeMarker's syntax just seemed a little more robust, and a little more powerful. I'm a programmer, after all, and I don't need my view technology to shield me from programming. Separation of concerns is a nice enough ideal, but I'm not willing to sacrifice power or performance to get it.

And so, with a view technology finally chosen, I can start confidentally down the path of building the next great web application. Spring's support of FreeMarker isn't quite up to its support for JSP, but it isn't a bad starting point. And the lack of structure means there's less framework to get in my way and keep me from doing what I want to do.

I very quickly, however, discovered what seemed to be a noticeable flaw in the default FreeMarker view. Spring chooses to render the view directly into the servlet's output stream. This is probably the safest thing to do, especially if you want to stream extremely large views to the client, but there are at least a few downsides to this approach. First, since the final output is unknown, the Content-Length header cannot be sent before the beginning of the output is flushed to the client. And since the output is being streamed directly to the servlet's output stream, each fragment of template output potentially must wait on an expensive network call. Most visibly, however, if an error interrupts the generation of content, there's no way to throw what's already been rendered.

Fortunately, Spring's lack of guidance works in your favor here. A very simple subclass of the FreeMarker view can enable fully buffered rendering out the output. Here's the start of my custom FreeMarker view:

public final class FreeMarkerViewImpl extends FreeMarkerView {
  private static final int INITIAL_BUFFER_SIZE = 8*1024;

@Override
@SuppressWarnings("unchecked")
protected final void processTemplate(Template template, Map model,
HttpServletResponse response) throws IOException, TemplateException {
ByteArrayOutputStream out = new ByteArrayOutputStream(INITIAL_BUFFER_SIZE);
template.process(model, new OutputStreamWriter(out));

response.setContentLength(out.size());
out.writeTo(response.getOutputStream());
}
}

Hooking the custom view into the Spring servlet configuration is just as easy. A single line in the definition of the view resolver is all that it takes:

<bean id="freeMarkerViewResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
    <property name="viewClass" value="com.mobileduo.web.mvc.FreeMarkerViewImpl"/>
    ....
</bean>