Recently in Groovy on Grails Category

The Problem

The other day I was doing some bulk file operations on a grails project. I was moving some classes in bulk from a plug-in into an application. After I made the move I ran into a puzzling issue: grails kept restarting in a loop. Each time the plugin scanner ran (every 5 seconds after startup), grails would complain that it needed to compile 1 file. This went on for a few minutes until my app ran out of PermGen and crashed. To make matters worse, grails would not tell me which file it was recompiling even with logging set to trace!

This seems to be a classic grails issue that is rare, but frustrating.

The Cause

The likely cause is a groovy file outside the correct package or with a file name that does not match the case name. The latter can happen when tinkering around between case sensitive and case insensitive file systems as is common when developing with OS X.

The Fix

To fix it you need to find the messed up class and fix it. The below method is crude, but works.

  1. If your app crashes quickly due to PermGen issues, provide more PermGen space. You’ll need at least 2 or 3 minutes of run time for this to work. Use the JVM argument -XX:MaxPermSize=1024m if you have to.
  2. Let your app run for a few minutes. Let it recompile that file a few times.
  3. If your app has not already crashed, stop it
  4. Now to find the compiled class file. Go to the directory where grails claims to be compiling the file. In my case it was in ~/.grails/1.2.0/projects/fooApp/classes
  5. Run this shell command to see when most of the files were updated: find ./ | xargs ls -al The vast majority of the listed files should all have an updated time within the same minute. In my case it was 15:17 Lets fileter those out and see what’s left behind.
  6. Run another find command and see the newer files: find ./ | xargs ls -al | grep -v 15:17. I saw a few files and headers that had to be ignored, but in the middle I found the class name which was compiled from a .groovy file of a different name.
  7. Go back to your app code and resolve the conflicted state of your groovy file(s)
  8. Quit cursing under your breath and go have a beer if you need one
0 Votes

Maybe you just upgraded Groovy on Grails, or maybe you’re doing a fresh install. Either way you may be confronted with this curious error message:

$ grails test
Exception in thread "main" java.lang.NoClassDefFoundError: org/codehaus/groovy/grails/cli/support/GrailsStarter

What’s wrong? You have a grails mismatch. Your GRAILS_HOME environment variable is not pointing to the same place as the grails in your PATH. Make them agree and try your grails command again.

0 Votes

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

This is an older one. I’ve only verified it with Grails v1.1, but it may still exist. It’s frustrating enough that it warrants a post, though.

Is your app slowing to a crawl due to an amazing Permgen leak? I mean big like 400+ MB of Permgen usage and 50k loaded classes. Well if you happen to be abusing ConfigSlurper, I may have a solution for you.

Are you doing something like this?

for (int i = 0; i < 50000; i++) { 
    ConfigObject config = new ConfigSlurper().parse("foo = bar"); 
    print " ${i}" 
} 

Well stop doing it. You’re leaking classes. Anything that you need to update at runtime that often should not be in the configuration file. Use JMX MBeans or a rest web service to allow updates instead.

Thanks to everyone on this email chain for resolving this issue.

0 Votes

Since Grails v1.1.1 has come out, there has been a strange issue. It seems to sneak up on me every time something important happens, like a production release. Grails throws an exception and I see an error page on my web browser. The exception always looks something like this:

2009-07-16 21:10:16,923 ERROR   org.codehaus.groovy.grails.web.errors.GrailsExceptionResolver:60        groovy.lang.MissingPropertyException: No such property: save for class: foo.Bar
org.codehaus.groovy.runtime.InvokerInvocationException: groovy.lang.MissingPropertyException: No such property: save for class: foo.Bar
        at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:92)
       ...
Caused by: groovy.lang.MissingPropertyException: No such property: save for class: foo.Bar
        at foo.BarController$_closure8.doCall(BarController.groovy:105)
        at foo.BarController$_closure8.doCall(BarController.groovy)

Research has revealed that other people face this issue as well. Some solutions that people have proposed:

  • Wait a few minutes and try again
  • Restart your application server (this seems to work well for me)
  • run MyDomainClass.count in your Bootstrap.groovy
  • run MyDomainClass.get(-1) before you attempt save

These all seem like black magic to me, though. I wanted to actually understand what was going on. I found the related JIRA (GRAILS-4580) and even the commit that Graeme made to fix it (which will be available in grails 1.2).

After everything I’ve read it seems like it’s another problem with Hibernate proxy objects not getting initialized correctly. This, however, does not explain why it’s been fixed with an application server restart for me each time, or if there’s anything I can do to avoid it while I’m still using Grails v1.1.1.

My plan going forward: Do not change my approach. When I see this issue in the future I’ll continue to attempt black magic. If I have a show stopper issue, I’ll apply the fix to grails v1.1.1.

0 Votes