Brain Flush

Grails and Eclipse: Not So Groovy

Posted in Software Development & Programming by Matthias Käppler on May 3, 2008

Grails is a Web application framework for rapid prototyping based on the Groovy scripting language, a Java dialect that compiles to Java byte code. Grails strongest advantage over similar frameworks (e.g. AppFuse, to name a more popular one) is its consequent use of the Convention Over Configuration paradigm, making it almost a no-brainer to set up a full featured Web app using Grails. Grails also relies heavily on the dynamic nature of Groovy to provide useful utility functionality or inject commonly used features such as logging objects and CRUD accessors for domain objects at runtime.

While Grails is an excellent piece of software, it is completely beyond me why apparently almost zero effort has been undergone to make it work flawlessly with one of the most (if not THE) widely used IDEs out there: the Eclipse IDE.

From day one, I had nothing but trouble running Grails applications in Eclipse. There is a document over at grails.org which has instructions for Grails + Eclipse, but it is erroneous and contradictory. While I still suggest to read that document, I will offer solutions to most of the problems you will probably still encounter, even after following that guide.

All instructions below worked for Grails 1.0.2 and Eclipse 3.3 on Ubuntu Linux 8.04.

The Groovy Eclipse Plugin

I assume that the Eclipse Groovy plugin has been installed.

By default, the output directory setting for Groovy compilations is left empty. That means your Groovy files in Eclipse will be compiled to your Grails project root. That is bad, as it confuses Grails. Set it to a different folder, e.g. bin-groovy. In any case, regardless what the Eclipse guide over at grails.org says, leave the “Disable Groovy Compiler Generating Class Files” box unchecked, but check “Disable Check Package Matches Source Directory”. Two reasons: If you check the first one, you won’t be able to debug your Groovy sources, but of course you want that. If you leave the second unchecked, you will get errors related to Groovy’s Spring DSL config in resources.groovy. This error is safe to ignore however.

Make sure to follow the instructions for debugging Groovy applications in Eclipse, too.

Fixing The Class-File Hell: 1st Try

Grails will generate an Eclipse .project file for you after issueing ‘grails create-app’. However, there are several issues with that file. First of all, Grails always compiles your Groovy and Java sources to the directory ~/.grails/<ver>/projects/<proj>/classes, but the generated project file sets the default output folder for Java class files to web-app/WEB-INF/classes. Furthermore, the Groovy plugin may compile to yet another directory, say bin-groovy. In other words, by default an imported Grails app is doomed to make you trouble, because the ‘grails’ command will always compile to a different folder than Eclipse does, and you will end up in a class-file mess where Eclipse will not recognize any changes made by Grails and vice versa.

The solution obviously is to make both Grails, the Eclipse Java compiler and the Groovy Eclipse plugin all compile to the same output directory. However, this is not as easy as it sounds. The best solution would be to tell Grails to compile to a different directory, but I haven’t found a way to do so.

The next best solution would be to create two symbolic links in your project root: bin and bin-groovy, both pointing to the Grails output directory (see above, it’s in your home directory under .grails/) and then tell the Eclipse Java compiler to compile to bin/ (via Project -> Properties -> Java Build Path -> Default Output Folder) and the Groovy plugin to compile to bin-groovy (via Project -> Properties -> Groovy Project Properties -> Groovy compiler output location).

While this solves the class-file hell, it leads to a weird problem: At least for me, I wasn’t able to run my Grails app from its Eclipse launcher anymore without the launch failing with a cryptic error message:

Failed to compile configuration file <proj_path>/grails-app/conf/Config.groovy: No signature of method: groovy.util.ConfigSlurper.parse() is applicable for argument types: (Config)

As of now, no one on the grails-user mailing list was able to say what is causing this, but of course it’s a show stopper, because you won’t be able to debug your application anymore (please note that this only affects Eclipse, your app would still start from the command line using ‘grails run-app’).

The third solution is somewhat ugly, but it works.

Fixing The Class-File Hell: 2nd Try

This approach is as follows: Instead of symlinking from bin and bin-groovy to the Grails output folder, we do it vice versa:

  1. leave the Java output folder to its default value: web-app/WEB-INF/classes
  2. the Groovy class files must also go there, so set a bin-groovy symlink to the same directory
  3. add bin-groovy to the build path: Project -> Properties -> Java Build Path -> Libraries -> Add Class Folder
  4. go to ~/.grails/<ver>/projects/<proj>, remove the classes/ folder and create a symlink “classes” to the full path of the web-app/WEB-INF/classes directory (e.g. ~/workspace/<proj>/web-app/WEB-INF/classes)

What we have done now is to turn around the sym-linkage: Grails will now compile to web-app/WEB-INF/classes. You may ask: What is the difference to the first approach?! Actually, there shouldn’t be any difference, but now you will notice that the ConfigSlurper error is gone, and you can run your app again from within Eclipse. THAT is why we do it (in lack of a better explanation…).

Unfortunately we’re still not 100% done. The reason is: As soon as you issue a ‘grails clean’, the symlink will become invalid and any “creational” follow-up commands like ‘grails compile’ will fail. The problem here is that ‘grails clean’ does not merely empty the ‘classes’ directory, but removes it alltogether. So we need to tell Grails not to remove the directory upon clean, but only its contents. A little background: Whenever you issue a command like this, you are effectively executing a Gant script (that’s the Groovy DSL for Apache Ant). These scripts reside in your Grails installation directory, in the scripts/ subfolder. Find the Clean.groovy script and perform the following changes:

  1. Find the target cleanCompiledSources
  2. Change the first call to Ant.delete to this code:
    Ant.delete(includeEmptyDirs:true) {
       fileset(dir:"${webInf}/classes", includes:"**/*")
    }
  3. Remove/comment the line Ant.delete(dir:classesDirPath)

save the file and exit. When you now run ‘grails clean’, only the content of classes/ will be removed, not the directory itself.

And that’s it!

Grails and Eclipse should now love each other. Ain’t that a happy ending?

23 Responses

Subscribe to comments with RSS.

  1. Eric said, on May 5, 2008 at 8:59 pm

    I’m struggling with the same problems as you regarding Grails and Eclipse. I got really excited to hear that your 2nd method works, but unfortunately it will *not* work on Windows. The “classes” symlink that you create in ~/.grails//projects/ is really a “.lnk” file in Windows, and unfortunately Grails won’t recognize it and create a regular classes directory right next to it. Maybe could be worked around with some more hacking the Clean script, but it’s just getting uglier…

    Anyway thanks for sharing your experience and some tips in this arena.

  2. Matthias said, on May 5, 2008 at 9:14 pm

    Hi Eric,

    yes that is unfortunate. I actually hoped this problem wouldn’t even appear on a Windows machine, but apparently it does. I am not aware of a similar solution for Windows right now.

    Unless of course, there would be a way to tell Grails not to compile to your home directory in the first place (on a Windows machine, I guess it will compile to your Documents And Settings folder?), which would make my hack redundant.

    Maybe dissecting Grails’ build.properties file will help to shed some light on this, but right now I am too tired of fighting with Grails’ build process. Maybe the people on the mailing list can help?

  3. Josh said, on May 24, 2008 at 4:13 pm

    I have not tried what you mention above yet but I have used “junction points” in place of symbolic links on windoze.

    here are a couple of helpful links
    http://technet.microsoft.com/en-us/sysinternals/bb545046.aspx
    http://shell-shocked.org/article.php?id=284
    http://www.rekenwonder.com/linkmagic.htm

    I’ll try it out today and let you know how it goes

  4. Matthias said, on May 24, 2008 at 5:29 pm

    Hey guys,

    I just sat down with a friend of mine who tried to compile my app under Windows, and after well over an hour of ripping out more hair, we figured out the solution for Windows (without any additional software required):

    1. Go to your scripts folder in your grails home and find Init.groovy. Change line 58 to e.g. this:
    projectWorkDir = “c:/workspace/${baseName}”

    where C:/workspace is your Eclipse workspace; this only works if your project name for your grails app is identical to the Eclipse project name for that same app.

    Then change line 59 to this:
    classesDirPath = System.getProperty(GrailsApplication.PROJECT_CLASSES_DIR) ?: “$projectWorkDir/web-app/WEB-INF/classes”

    2. Go to your Eclipse project settings and set both Java compiler output and Groovy builder output to web-app/WEB-INF/classes.

    3. Open your .classpath with a text editor and add this line (of course with brackets):
    classpathentry kind="lib" path="web-app/WEB-INF/classes"

    you have to do it this way, because you cannot add an output folder as a class folder via the GUI (will be filtered out).

    Of course editing the Ant.clean target has to be done as well, as outlined in my posting.

    That should do the job and it works for both Windows and Linux.

    Tell me if it works for you as well.

  5. Eric said, on May 26, 2008 at 10:38 pm

    Haven’t tried this new method, but I did want to report that like Josh I’ve had some success with the “2nd try” method listed above and junction magic (http://www.rekenwonder.com/linkmagic.htm). Been running it for a few weeks now without any snags.

  6. [...] to manually issue a “grails package” after each re-build. Plus, if you followed my hints on how to let Grails and Eclipse compile to the same directory structure, you won’t need to issue “grails clean” anymore. Simply running Project [...]

  7. Wayne Lund said, on July 6, 2008 at 6:37 pm

    I just walked through these issues this morning trying to get grails working for gorm classes. I still can’t seem to get past the:

    Severity and Description Path Resource Location Creation Time Id
    Invalid duplicate class definition of class Author : The source /Users/wxlund/library/workspace/grails-app/domain/Author.groovy contains at last two defintions of the class Author.
    One of the classes is a explicit generated class using the class statement, the other is a class generated from the script body based on the file name. Solutions are to change the file name or to change the class name.
    @ line 1, column 1. library/grails-app/domain Author.groovy line 1 1215365217511 1287

    I’ve been working passively on the problem for the past few weeks because it works fine in the Grails Console. However, since making the changes this morning I think that’s broken now as well.

    Thanks for the great explanation though. I’ve been trying to find this kind of explanation for awhile. I’m going to try IntelliJ again.

  8. Kristian Mandrup said, on July 11, 2008 at 11:32 am

    Hi there,

    Looks promising. I tried to use your suggestions ;)

    I made the following changes to Init.groovy and Clean.groovy to make them more generic and usable across platforms

    Init.groovy (from line 58 down)
    ========
    // fx c:\workspace
    grailsEclipseWorkspaceDirPath = System.getProperty(‘ECLIPSE_GRAILS_WORKSPACE’)
    // typically: web-app/WEB-INF/classes
    grailsEclipseClassesDirPath = System.getProperty(‘ECLIPSE_GRAILS_CLASSES_DIR’)
    eclipseEnabled = System.getProperty(‘Enable_Eclipse_Grails’) == “true”

    // default setting
    projectWorkDirDefault = “${grailsWorkDir}/projects/${baseName}”
    // eclipse specific
    projectWorkDirEclipse = “${grailsEclipseWorkspaceDirPath}/${baseName}”

    // set projectWorkDir depending on if eclipse for grails enabled
    projectWorkDir = eclipseEnabled ? projectWorkDirEclipse : projectWorkDirDefault

    // default setting
    classesDirPathDefault = System.getProperty(GrailsApplication.PROJECT_CLASSES_DIR) ?: “$projectWorkDir/classes”
    // eclipse specific
    classesDirPathEclipse = System.getProperty(GrailsApplication.PROJECT_CLASSES_DIR) ?: “$projectWorkDir/$grailsEclipseClassesDirPath”

    // set classesDirPath depending on if eclipse for grails enabled
    classesDirPath = eclipseEnabled ? classesDirPathEclipse : classesDirPathDefault

    classesDirPathEclipse = System.getProperty(GrailsApplication.PROJECT_CLASSES_DIR) ?: “$projectWorkDir/$grailsEclipseClassesDirPath”

    // set classesDirPath depending on if eclipse for grails enabled
    classesDirPath = eclipseEnabled ? classesDirPathEclipse : classesDirPathDefault

    Creating and running a default Grails app (eclipse_grails_enabled=false)

    C:\workspace\GrailsTest>grails run-app

    Welcome to Grails 1.0.3 – http://grails.org/
    Licensed under Apache Standard License 2.0
    Grails home is set to: C:\Program Files\Groovy\grails-1.0.3\grails

    Base Directory: C:\workspace\GrailsTest
    Note: No plugin scripts found
    Running script C:\Program Files\Groovy\grails-1.0.3\grails\scripts\RunApp.groovy
    Environment set to development
    [mkdir] Created dir: C:\Documents and Settings\zedbkma\.grails\1.0.3\projects\GrailsTest\classes
    [groovyc] Compiling 6 source files to C:\Documents and Settings\zedbkma\.grails\1.0.3\projects\GrailsTest\classes
    [mkdir] Created dir: C:\Documents and Settings\zedbkma\.grails\1.0.3\projects\GrailsTest\resources\grails-app\i18n
    [native2ascii] Converting 11 files from C:\workspace\GrailsTest\grails-app\i18n to C:\Documents and Settings\zedbkma\.grails\1.0.3\projects\GrailsTest\resources\grails-app\i18n
    Error starting Sun’s native2ascii:
    C:\workspace\GrailsTest>

    Why this native2ascii error???

    Clean.groovy
    ==========
    // line 28 down
    Ant.property(environment:”env”)
    grailsHome = Ant.antProject.properties.”env.GRAILS_HOME”
    eclipseGrailsEnabled = Ant.antProject.properties.”env.Enable_Eclipse_Grails”

    // line 45 down
    target ( cleanCompiledSources : “Cleans compiled Java and Groovy sources”) {
    def webInf = “${basedir}/web-app/WEB-INF”
    if (!eclipseEnabled) {
    Ant.delete(dir:”${webInf}/classes”)
    } else {
    Ant.delete(includeEmptyDirs:true) {
    fileset(dir:”${webInf}/classes”, includes:”*/”)
    }
    }

    The clean target works just fine under both scenarios

    And finally:

    Adding the lib entry to .classpath for all grails eclipse projects
    Go to grails\src\grails\templates\ide-support\eclipse\.classpath

    // line 14 down
    @grails.libs@
    @grails.jar@

  9. Matthias said, on July 11, 2008 at 11:41 am

    Hi Kristian,

    thanks for sharing this.

    As to the native2ascii error, this seems to happen an aweful lot. It has something to do with the i18n mechanism. If you get this error, just run “grails package” and it should go away.

  10. durp00 said, on August 12, 2008 at 10:36 pm

    On Win XP, I followed all the instructions in the “2nd Try” method and used http://www.nedprod.com/programs/Win32/SymLink/
    to create the symbolic link on windoze.

    Worked like a charm.

  11. James E. Ervin said, on September 2, 2008 at 8:48 pm

    The latest version of the plugin (well in SVN anyway) now eliminates the need for bin-groovy altogether. I will release the plugin to the beta site (later on tonight) and I would love to hear if it helps.

    http://dist.codehaus.org/groovy/distributions/updateDev/

    You may need to do some manual configuration of existing groovy/grails projects to remove the java builder (if you disable class file generation). The plugin should do it for you, but you never know right? Please feel free to ping me directly about this too. I am on twitter: http://twitter.com/GroovyEclipse

  12. Matthias said, on September 3, 2008 at 9:08 am

    That’s great news James, thanks for sharing. I’ll get to it as soon as I can.

  13. Nestor Urquiza said, on September 5, 2008 at 6:55 pm

    I tried “Fixing The Class-File Hell: 2nd Try” with the last http://dist.codehaus.org/groovy/distributions/updateDev/ and still but every time I try to insert a breakpoint in let us say a controller I get:
    “”"
    Unable to install breakpoint in due to missing line number attributes. Modify compiler options to generate line numbers attributes.”
    Reason:
    Absent Line Number Information
    “”"
    I have checked the debugging info is inside the generated class files. I can see the “LocalVariableTable” inside them.
    I have noticed though for the “$_closure.class” generated files I do have the line numbers in Eclipse Debug perspective (From Thread information there)

    I am trying all this now in Windows XP, using ‘junction’ utility (similar to linux ‘ln’)
    , Eclipse Ganymede.

    Groovy individual scripts can be debugged and run without any problem.

    Any thoughts?

    Best regards,

    -Nestor

  14. Nestor Urquiza said, on September 5, 2008 at 8:56 pm

    It seems like a bug reported as critical on JIRA http://jira.codehaus.org/browse/GROOVY-2208

    So the class files are missing LineNumberTable information and that is why Eclipse won’t be able to provide debugging capability for them.

    I am wondering if any of you guys found this problem so far? BTW this will affect any IDE and not just Eclipse.

  15. Matthias said, on September 15, 2008 at 10:04 am

    I only have problems debugging Groovy code after modifying it in a running session. The debugger is then unable to attach the source code to the compilation. I have to restart the servlet container for it to work again.

  16. Sachin Mittal said, on October 4, 2008 at 9:21 am

    To make a grails project integrate with eclipse on windows is simpler.
    set the output location for both java and groovy to:
    web-app/WEB-INF/classes
    This is mentioned in the post.
    change the Clean.groovy to not to delete the classes dir and its contents under web-inf/classes by commenting:
    target ( cleanCompiledSources : “Cleans compiled Java and Groovy sources”) {
    def webInf = “${basedir}/web-app/WEB-INF”
    /*Ant.delete(dir:”${webInf}/classes”)*/
    Ant.delete(file:webXmlFile.absolutePath, failonerror:false)
    Ant.delete(dir:”${webInf}/lib”)
    /*Ant.delete(dir:classesDirPath)*/
    Ant.delete(dir:resourcesDirPath)
    Ant.delete(dir:testDirPath)
    }

    note commenting this makes life easier because every time you deploy a war you don’t have to build the project again to repopulate classes dir.

    Thanks
    Sachin

  17. Laura said, on October 30, 2008 at 4:58 pm

    Great fix thank you … I have followed it through (2nd try method) and got rid of the original error.

    Unfortunately when running grails in Eclipse I now get an error relating presumably to the fact that the /classes directory already exists and was not expected (since i have commented out the delete. I am running OS X Leopard.

    Error is
    “Compilation error: Directory /Users/laurajtownsend/.grails/1.0.3/projects/testgrails/classes creation was not successful for an unknown reason
    : Directory /Users/laurajtownsend/.grails/1.0.3/projects/testgrails/classes creation was not successful for an unknown reason
    at org.apache.tools.ant.taskdefs.Mkdir.execute(Mkdir.java:64)….”

    Has anyone seen this or can help me fix (comment out?) the part that wants to make the classes directory again?

    Thanks

    Laura

  18. Paul at Work said, on November 29, 2008 at 1:41 pm

    HI

    Regarding the Build Error: “Failed to compile configuration file” … Config.groovy … “No signature of method: groovy.util.ConfigSlurper.parse()”

    I was able to fix by adding the JDK tools.jar to the project classpath:
    - Project Properties > Java Build Path
    - On Libraries tab, click Add External JARs, then select ‘..\jdkx.x.x\lib\tools.jar

    This is recommended in the instructions on how to setup the Eclipse IDE pluggin.
    See: http://grails.org/Eclipse+IDE+Integration

    I am now using Grails 1.0.4.

  19. Barnaby said, on December 8, 2008 at 8:58 pm

    It worked! … sort of. I was able to import a project and everything worked except the Acegi plugin, which refused to compile. I even imported the jar libraries that were inside of it and it still couldn’t find the classes for things like GrailsUser. Etc.

    I feel like it’s sssosooooo close. But alas, I just can’t use Eclipse with Grails. So, back to doing it with Vim, like it’s the 1980’s all over again.

  20. marcmit said, on February 24, 2009 at 1:08 am

    Remote debugging seems to work. I have enabled the “Disable Groovy Compiler Generation Class Files” checkbox. Start the app with “grails-debug run-app” instead of “grails run-app”. Then use remote debugging on eclipse by creating a run-config for “External Java Application”, select the correct project and port (normally 5005, check for the text “Listening for transport dt_socket at address: 5005″ in the grails windows) and connect your eclipse to the server.

  21. David said, on July 19, 2009 at 2:45 pm

    Very useful information, thanks!

  22. [...] Grails applications in Eclipse using the Groovy-Eclipse-Plugin was everything but enjoyable for me. Matthias Käppler summed it up best when he wrote: Grails and Eclipse: Not So [...]


Leave a Reply