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

Did you just notice that your IntelliJ editor is very slow all of a sudden? Is scrolling clumsy and do the animations crawl? Did you recently change your editor settings, by chance?

When this happened to me the other day my first impulse was to jump into the animation settings and then configuration files to tune the JVM memory settings as described in most Google results for ‘IntelliJ performance’. This was a red herring, though. I was way off.

It was my friggin font setting!

As part of a configuration overhaul, I had changed the editor font from the default to Lucida Sans Typewriter, one of my favorite fixed width fonts. This was the culprit for some mysterious reason! IntelliJ IDEA font config To fix this problem change your editor font. I found that Courier, Monospaced, and OCR A Std all performed very well.

0 Votes

Java collections, like List and Map, are great. In fact they’re probably the most used part of the Java core APIs. They do lack one feature, though: easy to use conversion into a string representation. This is a surprisingly common task for error messages and logging. In neither of these cases is the default toString() sufficient.

Typical solutions include usage of a static utility class to convert them, iterating through them in your code, or creating a subclass of your own. None of these have ever made me happy, though. They’re either too verbose or clunky and the way I want to represent a collection as a string often varies considerably from one instantiation to another.

I had never thought about it before, but Java anonymous classes provide a great solution. You can simply specify a toString function when you create a collection by subclassing it anonymously.

Here’s a simple example. I have a class which contains a map. In logs and error messages I want to simply dump the keys.

public class MyClass {
  private Map map;

  public MyClass() {
      map = new HashMap<String, Stuff>() {
          public String toString() {
              String stringForm = new String();
              for(String key : this.keySet()) {
                  stringForm += key + ", ";
              }
              //remove the trailing ", "
              stringForm.substring(0, stringForm.length()-2);
              return stringForm;
          }
      };
  }
}

Later in my code I can simply run map.toString() to see a comma separated list of the keys in my map.

Of course, this pattern only helps when you need a flexible way to represent each collection as a String and when that collection is only created in one place. If you’re creating the collection in many methods a non-anonymous inner class may be a better fit.

0 Votes

If you’re new to Solaris, like me, you may have noticed an annoying limitation of the default ps program built into Solaris. It truncates the commands at 80 characters! To make matters worse, the man pages don’t mention anything about this issue.

The reason the man pages offer no help is because this is a kernel issue. It was decided back in 1994 that 80 characters should be enough. Since the kernel does not store more than 80 characters, ps has no way of accessing this information. Ironicly, later that decade the same company invented their “language to end all languages”, Java. Unfortunately Java’s design typically resulted in CLASSPATH values much longer than 80 characters prepended to many commands.

There is an easy solution, though. Rather than fixing the problem Sun left us the old ps tool. While this does not use their new fancy API and is probably much less efficient, it somehow has access to the full command for all running processes. It’s officially deprecated, so use at your own risk, but here’s the equivalent of ps -ef:

/usr/ucb/ps axww

Note the different path to the command. Time to set up an alias.

0 Votes