Loading...

Wednesday, June 1, 2011

Groovy Goodness: Add Imports Transparently to Scripts with ImportCustomizer

Since Groovy 1.8.0 we can easily setup import statements for a Groovy compilation unit (for example a Groovy script file) without adding the imports to the script source. For example we have created domain classes in our own package. The script authors shouldn't know about the packages and just pretend the classes are accessible from the 'default' package.

We define an ImportCustomizer and use the addImport methods to add packages, classes, aliases to our script. The configured ImportCustomizer is added to a CompilerConfiguration object. We will see in future blog posts how we can even add more customizers to the CompilerConfiguration. We use the configuration when we create a GroovyShell and the information is applied to scripts we run with the created shell.

First we create a class and enum in the com.mrhaki.blog package. We compile the code so we have class files we can add to a classpath of another application.

// File: Post.groovy
// Compile with groovyc Post.groovy
package com.mrhaki.blog

class Post {
    String title
    Type type = Type.BLOG
}

enum Type {
    BLOG, NEWS
}

Next we create a Groovy script that will execute the following code:

// File: sample.groovy
// Article is imported as alias for com.mrhaki.blog.Post
def article = new Article(title: 'Groovy Goodness')

assert article.title == 'Groovy Goodness'
// BLOG is statically imported from com.mrhaki.blog.Type.*
assert article.type == BLOG
assert article.class.name == 'com.mrhaki.blog.Post'

Now we are ready to create a small application that will execute sample.groovy. We must add the com.mrhaki.blog.Post and com.mrhaki.blog.Type compiled classes to the classpath if we run the following script:

// File: RunScript.groovy
// Run with groovy -cp . RunScript
import org.codehaus.groovy.control.customizers.ImportCustomizer
import org.codehaus.groovy.control.CompilerConfiguration

// Add imports for script.
def importCustomizer = new ImportCustomizer()
// import static com.mrhaki.blog.Type.*
importCustomizer.addStaticStars 'com.mrhaki.blog.Type'
// import com.mrhaki.blog.Post as Article
importCustomizer.addImport 'Article', 'com.mrhaki.blog.Post'

def configuration = new CompilerConfiguration()
configuration.addCompilationCustomizers(importCustomizer)

// Create shell and execute script.
def shell = new GroovyShell(configuration)
shell.evaluate new File('sample.groovy')

3 comments:

Anonymous said...

I regularly review your blog - very informative, succint and to the point. Lately I have been using Groovy for some ETL work but it turned out to be really slow. Given that I had spent a significant amount of time, I decided to employ groovy++ to get me some performance gains. It worked out well as I replaced method by method (not completely yet - still trying to nail some issues). Wondering if you could do a couple of posts on Groovy++ for those who love Groovy but can't live with its slowness because of other pressing demands.

Thanks,
Kris

mrhaki said...

@Anonymous: I haven't looked at Groovy++ yet. I am focusing on the languages features provided by Groovy. But as you mentioned, maybe Groovy++ can be of use as well. I will put this on my list for future topics on Groovy. Thank you for your comment.

Vee Eee Technologies said...

Thanks for sharing your info. I really appreciate your efforts and I will be waiting for your further write ups thanks once again.
Vee Eee Technologies

Post a Comment