I wanted to play with Groovy’s AST Transformation in Grails. I thought naively that it would be enough to put the AST Transformation code into the source folder, like in a pure groovy project. I run the grails-app and it didn’t worked. So I searched for help in the world-wide-web. Some guys said that the AST code need to be precompiled and there is no way to do it with one compile run. Sadly I couldn’t find an example or a tutorial how to do the precompiling. After some frustrating hours of searching and trying I got a working solution. Now I am going to share my knowledge and hope that I can help you with this post.

At first I give you an explanation what an AST Transformation is.
When the Groovy compiler compiles Groovy scripts and classes, at some point in the process, the source code will end up being represented in memory in the form of a Concrete Syntax Tree, then transformed into an Abstract Syntax Tree. The purpose of AST Transformations is to let developers hook into the compilation process to be able to modify the AST before it is turned into bytecode that will be run by the JVM.
In simple words it means that you can modify programmable your code at compile time.Groovy’s documentation provides a simple example what you can do with AST. In this example a new Annotation @WithLogging is created. If you add this Annotation to a method then the AST Transformation adds at the beginning and at the end of the method a print line statement with “Starting” and “Ending” and the method name. Now I will show you how to get this example running in grails.

The first thing i had done was creating a new source-folder (src/ast) and put all files in it which needs to be precompiled => all AST related files. In this case WithLogging.groovy and WithLoggingASTTransformation.groovy

WithLogging.groovy
1: @Retention(RetentionPolicy.SOURCE)
2: @Target([ElementType.METHOD])
3: @GroovyASTTransformationClass(“astexample.WithLoggingASTTransformation”)
4: public @interface WithLogging {
5: }
Here we define the Annotation and bind it to the WithLoggingASTTransformation class. It’s important to use the full path to the class.

WithLoggingASTTransformation.groovy
1: @GroovyASTTransformation(phase = CompilePhase.CANONICALIZATION)
2: class WithLoggingASTTransformation implements ASTTransformation {
3: private static HashSet set = new HashSet()
4: public void visit(ASTNode[] nodes, SourceUnit sourceUnit) {
5: sourceUnit.getAST()?.getClasses().each { ClassNode classNode ->
6: classNode.getAllDeclaredMethods().findAll { MethodNode method ->
7: method.getAnnotations(new ClassNode(WithLogging))
8: }.each { MethodNode method ->
9: if(!set.contains(method)) {
10: Statement startMessage = createPrintlnAst(“Starting method.name”)11:StatementendMessage=createPrintlnAst(“Endingmethod.name”) 11: Statement endMessage = createPrintlnAst(“Ending method.name”)
12: List existingStatements = method.getCode().getStatements()
13: existingStatements.add(0, startMessage)
14: existingStatements.add(endMessage)
15: set.add(method)
16: }
17: }
18: }
19: }
20: private Statement createPrintlnAst(String message) {
21: return new ExpressionStatement(
22: new MethodCallExpression(
23: new VariableExpression(“this”),
24: new ConstantExpression(“println”),
25: new ArgumentListExpression(
26: new ConstantExpression(message)
27: )
28: )
29: )
30: }
31: }
This class preforms the AST Transformation. The compiler automatically calls the visit-method. This method iterates over all methods of all classes and check if the method has the @WithLogging Annotation. If the method has this Annotation then it adds the println-statements to the method.

The next step is to tell the grails app that it needs to precompile those files. To do that you have to create a new file in /scripts called “_Events.groovy”. This file is a grant script and with it you can hook into the grails events. We need now a hook into the compiling of the app and it’s done like this.
1: eventCompileStart = {target ->
2: compileAST(basedir, classesDirPath)
3: }
4: def compileAST(def srcBaseDir, def destDir) {
5: ant.sequential {
6: echo “Precompiling AST Transformations …”
7: echo “src srcBaseDir{srcBaseDir} {destDir}”
8: path id: “grails.compile.classpath”, compileClasspath
9: def classpathId = “grails.compile.classpath”
10: mkdir dir: destDir
11: groovyc(destdir: destDir,
12: srcDir: “$srcBaseDir/src/ast”,
13: classpathref: classpathId,
14: verbose: grailsSettings.verboseCompile,
15: stacktrace: “yes”,
16: encoding: “UTF-8”)
17: echo “done precompiling AST Transformations”
18: }
19: }

At last we create a simple grails-controller to test the AST Transformation.
1: class AstController {
2: def index = {
3: loggedMethod()
4: render ‘i am just a dummy method to call the method..’
5: }
6: @WithLogging
7: def loggedMethod() {
8: println “i am doing some important stuff!”
9: }
10: }
When you run the app and call the index-handler than you will get this output:
1: Starting loggedMethod
2: i am doing some important stuff!
3: Ending loggedMethod

That’s it. The most important thing for the AST transformation in Grails is the /scripts/_Events.groovy file. The rest is just normal AST transformation code or Grail’s code.

You can download the whole tutorial code as a STS project with includes a running AST Grails app here.

I hope you enjoyed the tutorial and you are welcome to leave some feedback.

Grails with ATS Transformation tutorial with a demo example相关推荐

  1. 我的Go+语言初体验——Demo游戏体验篇(直男程序员的真实体验)

    目录 前言 环境说明 项目实测 Weather Dragon Clone Bullet Animation 总结 前言 接着我的上一篇:我的Go+语言初体验--语法验证/性能测试篇(直男程序员的真实体 ...

  2. Java 线上问题排查神器 Arthas 快速上手与原理浅谈

    [Arthas 官方社区正在举行征文活动,参加即有奖品拿哦~点击投稿] 作者 | 杨桢栋,笔名叫蛮三刀把刀,是一名一线互联网码农,留美访学一年,主要关注后端开发,数据安全,爬虫,物联网,边缘计算等方向 ...

  3. ASP.NET Core 入门教程 6、ASP.NET Core MVC 视图布局入门 1

    ASP.NET Core 入门教程 6.ASP.NET Core MVC 视图布局入门 原文:ASP.NET Core 入门教程 6.ASP.NET Core MVC 视图布局入门 一.前言 1.本教 ...

  4. learnopengl——HDR——完结

    原文网址:https://learnopengl.com/Advanced-Lighting/HDR HDR brightness and color values by default are cl ...

  5. 编译可在Android上运行的qemu

    本文在ubuntu20.04上对qemu进行交叉编译 注意:NDK编译器工具API级别要在30以后,最好用33 因为只有30以后的版本支持函数memfd_create,详情请看http://t.csd ...

  6. Knockout JS 示例

    五个小例子,来自Knockout JS官方网站. //tutorial 1 //following codes uses to demonstrate observable values and ta ...

  7. line-bot-Tutorial

    原文地址:line-bot-Tutorial line-bot-Tutorial 教你建立自己的 line-bot 使用 python flask line-bot-tutorial use pyth ...

  8. Java线上问题排查神器Arthas快速上手与原理浅谈

    前言 当你兴冲冲地开始运行自己的Java项目时,你是否遇到过如下问题: 程序在稳定运行了,可是实现的功能点了没反应. 为了修复Bug而上线的新版本,上线后发现Bug依然在,却想不通哪里有问题? 想到可 ...

  9. rn ios Android适配,rn-mobx-starter

    Simple, detailed, quick tutorial. Attach a demo. 前言 开发一款产品,通常来说你需要做三件事情:搭建开发环境 -> 写代码 + 调试 -> ...

最新文章

  1. apt-mirror is already running(已运行)错误解决方案
  2. 计算机网络 第一章 计算机网络和因特网
  3. go语音protobuf_总结一下protobuf安装-Go语言中文社区
  4. 7.3(java学习笔记)网络编程之UDP
  5. Dynamics 365 Customer Engagement中插件的调试
  6. 冯诺依曼提出的三个计算机改进理论,冯诺依曼体系结构的计算机..docx
  7. python读取二进制文件,转成十六进制格式
  8. 爱好-超级IP:超级IP
  9. 比特红:万物可直播、人人能带货
  10. 天翼云主机安装php环境,使用PHP空间和天翼云盘搭建私人云盘
  11. 速求CAD序列号和密钥
  12. Postgres SQL函数获取首字母缩写
  13. Java-TreeSet与Comparable的详讲与实现
  14. UML用例图-软件需求分析与设计(很详细,很详细,很详细)
  15. 泰克示波器TBS2000B 在大学基础实验室的应用
  16. Java中一次对象的自我拯救探究
  17. 使用docsify+markdown+vditor构建gitlab pages文档库
  18. Fire (poj 2152 树形dp)
  19. Unity替换 图集
  20. 点击复制微信号并跳转到微信

热门文章

  1. 上海python培训比较好的机构-上海Python培训机构推荐
  2. python好学吗mooc中文网-2020年大学mooc用Python玩转数据作业答案
  3. python爬虫赚钱途径-如何利用python爬虫挣钱
  4. 学python要多少钱-python学习费用多少合适
  5. python正规教育机构-长沙python培训机构哪家好
  6. python工作-Python自动化运维|Python语言工作岗位待遇如何?
  7. 在哪里能收到python实例代码-python实例代码
  8. python 基础命令-详解python常用命令行选项与环境变量
  9. python快速编程入门例题-python编程入门知识练习
  10. python入门教程非常详细-Python 基础教程