Beta 3 for Groovy 2.4

The Groovy development team is happy to announce the release of a third beta for Groovy 2.4.

This release contains various bug fixes and minor improvements.

I'll highlight the fact that you can now use multiple labels on your statements (instead of just one).

With beta-3 now, many of the unneeded synthetic methods generated by Groovy are not generated anymore, reducing the number of methods nicely yielding smaller bytecode. 
This is of particular interest for Android developers limited in the overall number of methods used in Android applications

You can read the JIRA release notes and go straight to the download area!

Disable @Grab with a global AST transformation

On the Groovy mailing-list, we had an interesting question about how to disable annotations like @Grab, to prevent users from downloading third-party dependencies.
There are a few possibilities for that, but my favorite was to create a global AST transformation that would generate a compilation error if the @Grab annotation is found on an import.

I created a first small prototype within a script, but I used an injected local transformation to get everything working with a simple script. So I decided afterwards to do it for real this time, using a real project on Github with a proper global AST transformation this time.

If you checkout the project from Github, with:
git clone git@github.com:glaforge/disable-grab-sample.git
You then 'cd' in the disable-grab-sample directory, and you can run the following command to launch the Spock test showing the transformation in action:
./gradlew test
So what's inside that project? First of all, we need to create our AST transformation (I'll skip the imports for brevity):
@GroovyASTTransformation(phase = CompilePhase.CANONICALIZATION)
class DisableGrabTransformation implements ASTTransformation {
    void visit(ASTNode[] nodes, SourceUnit source) {
        def imports = source.AST.imports
        
        if (imports) {
            imports.each { anImport ->
                anImport.annotations.each { anno ->
                    if (anno.classNode.name in ['groovy.lang.Grab', 'groovy.lang.Grapes']) {
                        source.errorCollector.addError(
                            new SyntaxErrorMessage(
                                new SyntaxException('@Grab and @Grapes are forbidden',
                                anImport.lineNumber, anImport.columnNumber), 
                            source))
                    }
                }
            }
        }
    }
}
We create a class implementing the ASTTransformation class with its visit() method. In that method, we access the "module" imports, and if there are any import, we iterate over each of them, checking if there are annotations put on them. If those imports are annotated with @Grab or @Grapes (ie. if the annotation class node's fully qualified class name are the FQN of the Grab and Grapes annotations), we then use the error collector to add a new syntax error, so that a compilation error is thrown by the Groovy compiler if ever someone uses @Grab in a Groovy script or class.

We need to wire in that global transformation. As they are not triggered by annotations like local transformations, we need do declare the transformation in a specific META-INF / services / org.codehaus.groovy.transform.ASTTransformation file, that will just contain one line: the fully qualified class name of the AST transformation that needs to be applied to each script and classes that will be compiled when this transformation is on the classpath. So our services file will just contain:
disablegrab.DisableGrabTransformation
Now we need to see if our transformation is applied, and works as expected. For that purpose, we'll create a Spock test:
class DisableGrabSpec extends Specification {
    def "test"() {
        given:
        def shell = new GroovyShell()
        when:
        shell.evaluate '''
            @Grab('org.apache.commons:commons-lang3:3.3.2')
            import org.apache.commons.lang3.StringUtils
            println "hi"        
        '''
        then:
        def e = thrown(MultipleCompilationErrorsException)
        e.message.contains('@Grab and @Grapes are forbidden')
    }
}
We are using the GroovyShell class to evaluate (and thus compile) a script that contains a @Grab instruction. When evaluating that script, a compilation error should be thrown, and we indeed assert that it's the case, and that our compilation error contains the message we've crafted.

Done!

Let's step back a little with a couple words about our build file:
apply plugin: 'groovy'

repositories {
    jcenter()
}
dependencies {
    compile 'org.codehaus.groovy:groovy-all:2.3.6'
    testCompile 'org.spockframework:spock-core:0.7-groovy-2.0'
    testCompile 'org.apache.ivy:ivy:2.4.0-rc1'
}
Not much to see here actually! We're just applying the groovy plugin, use the jcenter repository from Bintray. We're using Groovy-all, the Spock library for our test scope, as well as the Ivy library that's needed by the grape infrastructure for fully functioning, for retrieving artifacts.

With our Gradle build file, we can call the jar task to create a JAR that will contain the META-INF/services file, and as soon as you'll have that JAR on your classpath with that AST transformation, any script or class compiled with it will get compilation errors if @Grab is used.

Groovy Weekly #33

You probably remember Groovy and Gradle being selected in RebelLabs’ report as part of the 10 “kick-ass” technologies developers love? But I’m also happy to report that Groovy won the Geek Choice Award, showing how groovy Groovy is!


GR8Conf US 2014 last week is delivering tons of great videos and materials from all the speakers that came to the conference, and I hope you’ll find time to watch a few. My personal highlight was the great Q&A talk by Scott Hickey and Jim McGill on looking back into 9 years of using Groovy at a big US insurance company. Don’t miss it!


Also, if you missed GR8Conf US 2014, remember there’s SpringOne2GX fast approaching, and the early bird price for registering to the conference ends August 9th, so be quick!


Last but not least, the Groovy Weekly schedule will slow down a little this month, as I’ll take some vacations! So I might be skipping a beat or two in the agenda, but fear not, Groovy Weekly will come back in full force in September!

Releases

News

Articles

Presentations

Google+ posts

Tweets

Code snippets

Events

Groovy receives Geek Choice Award

RebelLabs launched an annual study and awards to select 10 "kick-ass" technologies that developers love, and both Gradle and Groovy were among the winners!

You can learn more about this "kick-ass" technology study in the PDF report they crafted and which can be downloaded there (form filing required to download the PDF).

Details are available for:

It's always nice to see such reports and awards recognizing the great work and energy the Groovy and Gradle teams have been put into developing those technologies, and making developers around the world delighted to work with them.

Groovy Weekly #32

Live from GR8Conf US 2014, in Minneapolis, MN, USA! The code samples and slides of presentations are already flowing and are listed below in the presentations section. Lots of great content and talks to learn from.

Releases

News

Articles

Presentations

Mailing-list posts

Tweets

Code snippets

Books

Events

Jobs

 
© 2012 Guillaume Laforge | The views and opinions expressed here are mine and don't reflect the ones from my employer.