Question

I have written a Groovy AST Transformation which only runs for me when Grails auto-reloads the class it is to be applied to. If I clean the project and start the application using run-app, the AST transformation does not run. Touching the class so that grails auto-reloads results in the transformation running.

The annotation and ASTTransformation implementation are groovy classes located in the src/groovy directory in my Grails application. The annotation is used on domain classes, written in groovy in the domain directory.

Is it possible this is caused by the order the groovy files get compiled or when they are loaded by the classloader? If so, how do I ensure my ast transforamtion is compiled/loaded before the domain classes?

The annotation:

@Target([ElementType.TYPE])
@Retention(RetentionPolicy.RUNTIME)
@GroovyASTTransformationClass(["com.abc.annotation.SecuredObjectASTTransformation"])
public @interface SecuredObject {
}

The ASTTransforamtion implementation:

@GroovyASTTransformation(phase = CompilePhase.CANONICALIZATION)
class SecuredObjectASTTransformation implements ASTTransformation {

    @Override
    public void visit(ASTNode[] nodes, SourceUnit sourceUnit) {
        // add some new properties...
    }
}

The Grails version is 2.1.0.

Was it helpful?

Solution 2

The AST Transformations need to be compiled before your project code. The simplest way to do this is to hook into the grails compile event with a script. Check out this blog post for how to create a script with new ant task to precompile source in src/ast folder. http://reinhard-seiler.blogspot.com.au/2011/09/grails-with-ats-transformation-tutorial.html

If you only have a few AST Transformations then this is by far the best approach. Creating a plugin or separate project with compiled jar is too much work for my needs.

OTHER TIPS

All the various src/groovy, src/java and grails-app/* files get compiled together in one go so the AST transform isn't available to the compiler at the point where it compiles your domain classes. However plugins get compiled in a separate pass before the app so one option might be to create a very simple plugin just to contain the annotation and the AST transform class and declare that as an inline plugin in BuildConfig

grails.plugin.location.'secured-objects' = '../secured-objects'

The transform will then be built in the plugin compilation pass and will be on the compiler classpath when it comes to build your domains.

Also if you want to avoid the Annotations and apply it to every class possible, you can checkout my answer here!

The answer describes how to apply Global ASTTransforms. You can apply transform in all classes that get compiled after the Transformer.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top