Saturday, January 23, 2010

Scala + Spring + Templates - the story so far

I've been writing a fairly simple web app with Scala and Spring that will be running on Google's App Engine. I've been trying to decide which template language (or even languages) to write my views in. I'll be rendering a lot of non-HTML and non-XML and over the years I've noticed some template engines are better at this than others. Also, I'm looking for first class Scala support (so anything you can do with a Java Bean you can do with a Scala object) - ideally built in and at worst trivial to add. Here's what I've come across so far:

Closure Templates

I like Google's Closure Template, but there's no "out of the box" support for it in Spring. If I can't find another template engine I like then I will come back and look at how to add some support.

FreeMarker

I will start at the point where my experiments ended - apparently FreeMarker doesn't currently work on GAE, as FreeMarker uses some swing classes that aren't available in GAE. This is a show stopper. I didn't run in to this during my experiments as it was working on the local dev server and I wasn't aware of this problem until I was submitting a bug for another problem I found.

During my experiments, I found several other issues, one of which calls into question using FreeMarker with Spring and Java, let alone Scala.

First, there isn't built in object wrapping for Scala objects. By default, FreeMarker will treat Scala objects as Java objects, but as plain Scala objects don't follow JavaBeans conventions access to getters ceases to be trivial. I was able to whip up a Scala specific FreeMarker Model and ObjectWrapper with relative ease, but then I ran into another problem - there doesn't appear to be an easy way in Spring to configure FreeMarker with an alternative ObjectWrapper.

The answer was to create a subclass of org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer and modifying one of the Configuration related methods to return a Configuration with an ObjectWrapper property set to my Scala specific ObjectWrapper. However, I then ran into a problem that I eventually traced to what appears to be a bug in FreeMarker. When Spring sends a model to FreeMarker it uses FreeMarker's AllHttpScopesHashModel - unfortunately AllHttpScopesHashModel's constructor doesn't let it's super class know about the ObjectWrapper that was passed in (it just stores it in a final variable that is private to AllHttpScopesHashModel). This means inherited methods fall back to using Fremarker's default ObjectWrapper - so Scala objects don't work. While working with the FreeMarker source code to make sure this is what was going wrong (it was), I ran into two more issues with FreeMarker.

As I was using the trunk from FreeMarker's SVN repository I assume I was using what will be the 2.4 release of FreeMarker. The first problem I ran into with this was that Spring's FreeMarkerView imports freemarker.core.ParseException, unfortunately ParseException has been moved to freemarker.core.parser.ParseException which obviously breaks Spring 3. As I said above, I have doubts about about using FreeMarker with Spring and any language - this is the reason why. At some point this backwards incompatible API change is going cause someone, somewhere a lot of pain and I don't want to be that person.

While mucking about with FreeMarker's source, I ran into another problem. FreeMarker 2.4 will have some new security features which seemed to cause no end of trouble with GAE. While you should be able turn these features off in the Configuration object, setting the secure property to false had no impact on getting FreeMarker to work with GAE. While I had pretty much given up on FreeMarker by this point, I still wanted to make sure that the reason why my ObjectWrapper wasn't working was because of AllHttpScopesHashModel's constructor so I commented out some security related lines in FreeMarker and eventually got it all working.


Summary

I won't be using FreeMarker. There are still a few more template engines to look at before I'll fall back to forcing Closure Templates to work with Spring (I would be astounded if it doesn't work GAE). So, I'll carry on my search (Velocity is probably next).

4 comments:

James Strachan said...

BTW I've been hacking on Scala Server Pages lately: see the ssp home page.

The documentation needs lots of work - but try running the sample web application (via mvn jetty:run).

Web design Company said...

Hi

Great information in this post and the first problem I ran into with this was imports.

James Parker.
Web design Firm

Anonymous said...

Since then FreeMarker 2.3.x releases has a GAE variant which is GAE-compatible. Also 2.4.x will be GAE compatible (no two variants anymore). As of the incompatible API changes, 2.4 won't have them, and what was once called 2.4 is now called 3.0 (and 3.0 might wont become to a release ever).

Tom Akehurst said...

I have just released an initial version of my integration library for Closure Templates and Spring MVC: https://github.com/tomakehurst/spring-closure-templates

If you're interested, see the wiki for some brief instructions on how to include in your project, and the example app in the source project for a complete example.

Any feedback, feature suggestions would be much appreciated.