Groovy on Grails: November 2009 Archives

Ever used WordPress? It has that cool feature that allows users to heavily customize their blogs by editing templates. If you’re trying to do something like that in Groovy on Grails, you’ve found the right blog entry. It’s quite easy as of Grails v1.1.1, although it does have some quirks and caveats.

First, we’ll need to import a few classes for this to work. Add these imports to your controller:

import org.codehaus.groovy.grails.web.pages.GroovyPagesTemplateEngine
import org.springframework.web.context.request.RequestContextHolder
import org.codehaus.groovy.grails.web.servlet.mvc.GrailsWebRequest

Next, in our controller we’ll need the template engine. Luckily just like our grails services the framework will inject this in for us. To let it know what to inject, add this to the top of your controller:

    GroovyPagesTemplateEngine groovyPagesTemplateEngine // allows us to call the Groovy page-rendering stuff within the controller

Now for the fun part. To render a template from a string just add this private method to your controller:

    private void renderTemplate(String content, Map model) {
        groovy.text.Template template = groovyPagesTemplateEngine.createTemplate(content, groovyPagesTemplateEngine.getCurrentRequestUri(request))
        def renderedTemplate = template.make(model)
        GrailsWebRequest webRequest = (GrailsWebRequest) RequestContextHolder.currentRequestAttributes()

        /**
         * There are extra characters rendered into my page:
         * ServletWebRequest: uri=/app_name/grails/controller/actionname.dispatch;client=127.0.0.1;session=xgjq4afedjry
         * this is a hack to keep that stuff from being rendered into the page
         */
        def crapAtTheBeginningLength = webRequest.out.toString().length()
        renderedTemplate.writeTo(webRequest.out)
        def stringToRender = webRequest.out.toString()
        render stringToRender.substring(crapAtTheBeginningLength)
    }

Simply call this function from any action like you’d call render, except pass in the String version of the template as the first argument:

    def index = {
       String templateString = "..."; //get the template string somehow
       //... code to build out the model to be passed into the template ...
        renderTemplate(templateString, [foo: "bar", stuff: listOfStuff])
    }

This should work pretty well. Now for the caveats:

  • I haven’t done any load testing yet, but there may be performance implications due to the way the GSP caching works. This technique appears to have circumvented some parts of it and may have significant negative performance impact.
  • GSP code can never be made completely safe. Never render GSP code that was created by untrusted people. Although you are passing a model in, the GSP can run any Groovy code that it wants to run and could result in a serious security breech.

Also, no I didn’t come up with this code on my own. Credit goes to a bunch of grails mailing list threads that I’ve lost links to, help from people in #grails on irc.freenode.net, and this other blog entry on the same topic and yet another related blog entry.

Update: Here’s another example that’s a bit more refined.

0 Votes

About this Archive

This page is an archive of entries in the Groovy on Grails category from November 2009.

Groovy on Grails: August 2009 is the previous archive.

Groovy on Grails: December 2009 is the next archive.

Find recent content on the main index or look in the archives to find all content.