Monday, July 02, 2007

Groovy Views in Spring MVC

I thought it might be fun to try and implement Groovy as a View technology in Spring MVC. Most people that use Spring MVC are familiar with the JstlView for Jsps, or the VelocityView for Velocity templates, and the far superior FreemarkerView for FreeMarker templates.

So, let's think about what we'd have to do to use Groovy to render views...
We'd need to be able to load a resource as a groovy script, bind some stuff to it (the request, response.getWriter as out), and evaluate it.

Well, it turns out it wasn't fun at all. In all of about 10 minutes I got it working and it was really boring...
Keep in mind that the code here is totally rudimentary, there's no caching or anything like that. Anyway, check it out...

public class GroovyView extends AbstractTemplateView {

private static final Logger log = Logger.getLogger(GroovyView.class);

protected void renderMergedTemplateModel(Map model, HttpServletRequest request, HttpServletResponse response)
throws Exception {

Binding binding = createBinding(model, request, response);

GroovyShell shell = createGroovyShell(binding, request, response);

Resource resource = loadViewResource(request, response);

if (log.isDebugEnabled()) {
log.debug("resource: [" + resource + "]");
}

evaluateViewResource(shell, resource);
}

protected Binding createBinding(Map model, HttpServletRequest request, HttpServletResponse response)
throws IOException {
Binding binding = new Binding(model);
binding.setVariable("request", request);
binding.setVariable("out", response.getWriter());

return binding;
}

protected GroovyShell createGroovyShell(Binding binding, HttpServletRequest request, HttpServletResponse response) {
return new GroovyShell(binding);
}

protected void evaluateViewResource(GroovyShell shell, Resource resource)
throws IOException {
shell.evaluate(resource.getInputStream());
}

protected Resource loadViewResource(HttpServletRequest request, HttpServletResponse response) {
return getApplicationContext().getResource(getUrl());
}
}

OK, there's the implementation, how would you use it in Spring? Well you can combine it with a UrlBasedViewResolver.

<bean id="groovyViewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="prefix" value="WEB-INF/views/">
<property name="suffix" value=".groovy"/>
<property name="viewClass" value="raykrueger.GroovyView"/>
</bean>

Really just follow any Spring MVC 101 example you can find on the internet and use the GroovyView here. Then you can create groovy scripts to use as views that look like...

builder = new groovy.xml.MarkupBuilder(out)

builder.html {
head {
title "Hi there"
}
body {
p "Hello from the GroovyView"
p "Neat Huh?"
a(href:'http://raykrueger.blogspot.com', "Ray Krueger's Blog")
}
}

Then you have all the power of Groovy at your fingertips to build views for your models. Accessing fields and looping iterators is a boatload easier in Groovy than in jstl. Though, honestly, you can do a lot of this stuff with Freemarker...

Now, I'm sure you can clean this up a bit and optimize the crap out of it (view caching and such). Really I just slapped this together as a thought.

Here's the source

4 comments:

robottaway said...

Have you checked out how Grails does this? I believe it uses Spring MVC behind the scenes somewhere.

Anonymous said...

Hey man, I guess you've missed the spot. Groovy should be used for controller logic, not for generating markup :) This gun does not fit well for the view task.

Ray Krueger said...

Aaah, says who?
Groovy has some pretty amazing capabilities. If Groovy "should be used for controller logic", why does it come with the MarkupBuilder?
:)

chris alme said...

i know this is an old post, but i see no issue in using groovy for the view. in our case we are using spring mvc to provide REST-ful web services, and you gotta love groovy's xml support for kicking out responses...