Skip to content
Skip to breadcrumbs
Skip to header menu
Skip to action menu
Skip to quick search
Quick Search
Browse
Pages
Blog
Labels
Attachments
Mail
Advanced
What’s New
Space Directory
Feed Builder
Keyboard Shortcuts
Confluence Gadgets
Log In
Sign Up
Dashboard
Groovy
Copy Page
You are not logged in. Any changes you make will be marked as
anonymous
. You may want to
Log In
if you already have an account. You can also
Sign Up
for a new account.
This page is being edited by
.
Paragraph
Paragraph
Heading 1
Heading 2
Heading 3
Heading 4
Heading 5
Heading 6
Preformatted
Quote
Bold
Italic
Underline
More colours
Strikethrough
Subscript
Superscript
Monospace
Clear Formatting
Bullet list
Numbered list
Outdent
Indent
Align left
Align center
Align right
Link
Table
Insert
Insert Content
Image
Link
Attachment
Symbol
Emoticon
Wiki Markup
Horizontal rule
tinymce.confluence.insert_menu.macro_desc
Info
JIRA Issue
Status
Gallery
Tasklist
Table of Contents
Other Macros
Page Layout
No Layout
Two column (simple)
Two column (simple, left sidebar)
Two column (simple, right sidebar)
Three column (simple)
Two column
Two column (left sidebar)
Two column (right sidebar)
Three column
Three column (left and right sidebars)
Undo
Redo
Find/Replace
Keyboard Shortcuts Help
<p>With this new 2.1 release, Groovy:</p><ul><li>has <strong>full support for the JDK 7 “invoke dynamic”</strong> instruction and API,</li><li>goes beyond conventional static type checking capabilities with a <strong>special annotation for closure delegate based Domain-Specific Languages</strong> and <strong>static type checker extensions</strong>,</li><li>provides <strong>additional compilation customization</strong> options,</li><li>and features a <strong>meta-annotation facility</strong> for combining annotations elegantly.</li></ul><h2>Table of Content</h2><div><img class="editor-inline-macro" src="/plugins/servlet/confluence/placeholder/macro?definition=e3RvYzpleGNsdWRlPVRhYmxlIG9mIENvbnRlbnR9&locale=en_GB&version=2" data-macro-name="toc" data-macro-parameters="exclude=Table of Content"></div><h2 class="c2">Full invoke dynamic support</h2><p class="c2">With Groovy 2.0, we introduced support for JDK 7’s “invoke dynamic” bytecode instruction and API to benefit from the dedicated support and performance improvements for dynamic languages starting with JDK 7. Groovy 2.1 brings <span class="c5"><strong>full support for “invoke dynamic”</strong> </span>(aka<span class="c11"> “indy”</span>), completing the work introduced in 2.0.<span style="font-size: 10.0pt;line-height: 13.0pt;"> </span></p><p class="c2">In Groovy 2.0, most method calls were using the “invoke dynamic” instruction, but there have been exceptions: constructor calls or <span class="c11">“spread calls” (</span>where you pass arguments with the “spread operator”). Groovy 2.1 completes the implementation started in 2.0. Now, code compiled with the “invoke dynamic” JAR on JDK 7 will not be using the old “call site caching” code which served us well for getting good performance for Groovy prior to JDK 7. If you are lucky enough to be using JDK 7 in production, be sure to use the Groovy 2.1 “indy” JAR to benefit from the full “invoke dynamic” support. The “indy” version is bundled with the binary download package and can be obtained via Maven (all JARs with “invoke dynamic” support are postfixed with “-indy”).</p><p class="c2">You can <a class="confluence-link" href="/display/GROOVY/InvokeDynamic+support" data-linked-resource-id="230398416" data-linked-resource-type="page" data-linked-resource-default-alias="InvokeDynamic support" data-base-url="http://docs.codehaus.org">learn more about the invoke dynamic support</a>.</p><h2 class="c2"><a />GPars 1.0</h2><p class="c2">Groovy 2.1’s distribution <strong><span class="c5">bundles the recently released GPars 1.0</span></strong>, the one-stop shop for all your concurrency needs. This new version comes with various enhancements in the asynchronous functions, <span class="c6" style="color: rgb(17,85,204);text-decoration: underline;"><a class="c7" href="http://www.jroller.com/vaclav/entry/broken_promises" style="text-decoration: inherit;">promises</a></span>, parallel collections, actors, dataflow support, <span class="c6" style="color: rgb(17,85,204);text-decoration: underline;"><a class="c7" href="http://www.jroller.com/vaclav/entry/gpars_actors_and_dataflow_for" style="text-decoration: inherit;">Google App Engine support</a></span>, etc.</p><p class="c2">Be sure to check the <span class="c6" style="color: rgb(17,85,204);text-decoration: underline;"><a class="c7" href="http://www.jroller.com/vaclav/entry/i_like_the_smell_of" style="text-decoration: inherit;">release announcement</a></span> and read the “<span class="c6" style="color: rgb(17,85,204);text-decoration: underline;"><a class="c7" style="text-decoration: inherit;">what’s new section</a></span>” of the GPars user guide. You can also have a look at the detailed <span class="c6" style="color: rgb(17,85,204);text-decoration: underline;"><a class="c7" href="http://jira.codehaus.org/secure/ReleaseNote.jspa?projectId=12030&version=17007" style="text-decoration: inherit;">JIRA release notes</a></span>.</p><h2 class="c2"><a />@DelegatesTo annotation</h2><p class="c2">Authoring Domain-Specific Languages (DSLs) has always been a sweet spot for Groovy, and the availability of closures and the malleable syntax of the language has allowed DSL implementors to build nice mini-languages like “builders”, to represent configuration or hierarchical data.</p><p class="c2">Thanks to the various delegation strategies of the <code><span class="c0">groovy.lang.Closure</span></code> class, a range of very powerful techniques can be used when building DSLs. Due to different implementation techniques, inferring type information within the DSL has not been straightforward. This is especially an issue when DSLs should have proper IDE support (e.g. code completion).</p><p class="c2">The very popular and powerful <span class="c6" style="color: rgb(17,85,204);text-decoration: underline;"><a class="c7" href="http://www.gradle.org/" style="text-decoration: inherit;">Gradle</a></span> build automation system uses its own DSL for build script specifications. On the DSL implementation layer are various methods taking closures as arguments, and with special delegation strategies delegating to some other parameter passed to them. Providing good IDE support for Groovy DSLs — like the one in Gradle — has presented a few challenges. Hence the need for the <code><span class="c5 c0">@DelegatesTo</span></code><span class="c5"> </span>annotation.</p><p class="c2">Groovy 2.1 introduces the <strong><code><span class="c5 c0">@groovy.lang.DelegatesTo</span></code><span class="c5"> annotation</span></strong> as a <span class="c5"><strong>documentation mechanism</strong> </span>for DSL users and maintainers, as an <strong><span class="c5">IDE hint for providing better coding assistance</span></strong>, and as additional information that can be <span class="c5"><strong>taken into account by the static type checker and static compilation</strong> </span>introduced in Groovy 2.0. Let’s see that in action with some examples.</p><p class="c2">A closure delegate based method usage might look like the following:</p><table class="wysiwyg-macro" data-macro-name="code" data-macro-parameters="language=groovy" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGU6bGFuZ3VhZ2U9Z3Jvb3Z5fQ&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>exec { launch() }</pre></td></tr></table><p class="c2">The <code><span class="c0">exec()</span></code> method takes a closure as parameter, and the actual <code><span class="c0">launch()</span></code> call inside that closure is delegated to some particular object (the closure delegate), instead of being dispatched to the enclosing class. The above code would only fail at runtime (not at compile-time!), as the <code><span class="c0">launch()</span></code> method can not be found in the closure context. In order to delegate method calls within the closure’s code block to another object instance, we need to set the closure delegate.</p><p class="c2">Setting a closure delegate is as easy as invoking <code><span class="c0">Closure#setDelegate(Object)</span></code>:<span style="font-size: 10.0pt;line-height: 13.0pt;"> </span></p><table class="wysiwyg-macro" data-macro-name="code" data-macro-parameters="language=groovy" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGU6bGFuZ3VhZ2U9Z3Jvb3Z5fQ&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>void exec(Closure c) { c.delegate = new Executor() c() }</pre></td></tr></table><p class="c2">The delegate can be set to an arbitrary object instance (here, an instance of an <code><span class="c0">Executor</span></code> class that has a <code><span class="c0">launch()</span></code> method). When the delegate is set accordingly, we can execute the closure code.</p><p class="c2">Note that usually, to avoid odd behavior if the closure is used in multiple threads, we tend to clone that closure.</p><p class="c2">The problem with delegate objects are IDEs not knowing about them. Given our example, most IDEs will underline the <code><span class="c0">launch()</span></code> method as being an unknown method in this context.</p><p class="c2">This is where <code><span class="c0">@DelegatesTo</span></code> comes into play. By adding the <code><span class="c0">@DelegatesTo</span></code> annotation to DSL methods like <code><span class="c0">exec(Closure)</span></code>, IDEs get the actual delegate type and other meta-data.</p><p class="c2">A future update might let GroovyDoc show the details about the annotation usage to help users know what methods they can call, what properties they can access, etc.</p><p class="c2">Here’s what your <code><span class="c0">exec()</span></code> method will look like with the annotation:</p><table class="wysiwyg-macro" data-macro-name="code" data-macro-parameters="language=groovy" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGU6bGFuZ3VhZ2U9Z3Jvb3Z5fQ&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>void exec(@DelegatesTo(Executor) Closure c) { c.delegate = new Executor() c() }</pre></td></tr></table><p class="c2">Besides specifying the actual delegate type, <code><span class="c0">@DelegatesTo</span></code> can be used to hint at the actual resolve strategy. The resolve strategy determines the order in which non-closure method / property calls are looked up. In our example, <code><span class="c0">Closure.DELEGATE_FIRST</span></code> will be used. This indicates the closure will attempt to resolve against the given delegate object in first place, followed by the owner object:</p><table class="wysiwyg-macro" data-macro-name="code" data-macro-parameters="language=groovy" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGU6bGFuZ3VhZ2U9Z3Jvb3Z5fQ&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>import static groovy.lang.Closure.* // ... void exec(@DelegatesTo(strategy = DELEGATE_FIRST, value = Executor) Closure c) { c.delegate = new Executor() c.resolveStrategy = DELEGATE_FIRST c() }</pre></td></tr></table><p class="c2">IDE support is not the only reason to use <code><span class="c5 c0">@DelegatesTo</span></code><span class="c5">.</span> The <strong><span class="c5">static type checker and static compiler take the additional meta-data specified by the </span><span class="c5 c0">@DelegatesTo</span><span class="c5"> annotation into account</span></strong>. If there is a typo in the closure code block, the type checker will complain. And if you use the static compilation capability introduced in Groovy 2.0, the calls will be compiled statically.</p><p class="c2">Let’s say we wouldn’t call <code><span class="c0">launch()</span></code> but <span class="c0"><code>launchr()</code> </span>in the closure code block, we would get a message like:</p><table class="wysiwyg-macro" data-macro-name="code" data-macro-parameters="language=none" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGU6bGFuZ3VhZ2U9bm9uZX0&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>[Static type checking] - Cannot find matching method DelegatesToSamples#launchr(). Please check if the declared type is right and if the method exists.</pre></td></tr></table><p class="c2"><span class="c5"><strong>Static type checks for custom Domain-Specific Languages</strong> </span>is a very convenient feature in Groovy 2.1!</p><p class="c2">In addition, Groovy 2.1 features other abilities for even further type checking your DSLs, as you shall see in the following section.</p><p class="c2">Before moving on, let’s mention a few closing details about <code><span class="c0">@DelegatesTo</span></code>.</p><p class="c2"><code><span class="c0">@DelegatesTo</span></code> allows to specify the receiver calls are delegated to. For instance, when a delegate calls a method or property on another method parameter. Imagine our <code><span class="c0">exec()</span></code> method taking the <code><span class="c0">Executor</span></code> argument instance as delegate:</p><table class="wysiwyg-macro" data-macro-name="code" data-macro-parameters="language=groovy" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGU6bGFuZ3VhZ2U9Z3Jvb3Z5fQ&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>void exec(Executor ex, @DelegatesTo(Executor) Closure c) { c.delegate = ex c() }</pre></td></tr></table><p class="c2">In this example, the information is lost that the call is delegated to the <code><span class="c0">ex</span></code> parameter. Thanks to the <code><span class="c0">@DelegatesTo.Target</span></code> annotation we can specify <span class="c0">ex </span>as target for being the delegate object:</p><table class="wysiwyg-macro" data-macro-name="code" data-macro-parameters="language=groovy" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGU6bGFuZ3VhZ2U9Z3Jvb3Z5fQ&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>void exec(@DelegatesTo.Target Executor ex, @DelegatesTo Closure c) { c.delegate = ex c() }</pre></td></tr></table><p class="c2">What if we had several <code><span class="c0">Executor</span></code> parameters, how would we differentiate which one we’re targeting?</p><table class="wysiwyg-macro" data-macro-name="code" data-macro-parameters="language=groovy" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGU6bGFuZ3VhZ2U9Z3Jvb3Z5fQ&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>void exec( @DelegatesTo.Target('param1') Executor ex, @DelegatesTo(target = 'param1') Closure c) { ... }</pre></td></tr></table><p class="c2">The delegation “target” can be specified with an arbitrary id. In the example above it is <code><span class="c0">param1</span></code>.</p><p class="c2">One last very nice little feature: if you are using static type checking, you can omit the type of the parameter and <code><span class="c0">@DelegatesTo</span></code> combined with “flow typing” (the ability of following the current type of an untyped variable) would still know if method calls are valid:</p><table class="wysiwyg-macro" data-macro-name="code" data-macro-parameters="language=groovy" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGU6bGFuZ3VhZ2U9Z3Jvb3Z5fQ&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>void exec(@DelegatesTo.Target ex, @DelegatesTo Closure c) { c.delegate = ex c() } class Executor { void launch() {} } def ex = new Executor() exec(ex) { launch() }</pre></td></tr></table><p class="c2">We’ve seen that the <code><span class="c0">@DelegatesTo</span></code> helps documenting, tooling, and checking Domain-Specific Languages in the specific context of closure delegate based methods, but we hinted at the fact we can go beyond, in terms of static type checking for your DSLs.</p><p class="c2">For more details take a look at the <a href="http://docs.codehaus.org/display/GROOVY/The+@DelegatesTo+annotation">@DelegatesTo documentation</a>.</p><h2 class="c2"><a />Type checker extensions</h2><p class="c2">Static type checking was introduced in Groovy 2.0, but Groovy 2.1 goes beyond built-in type checks and offers a way <span class="c5">to <strong>create type checker extensions</strong></span>. This is great news for Groovy scripts, configuration files, or Domain-Specific Languages implementations as they can can be “type checked” with more advanced, domain-specific rules. As an example, it would be possible to create a custom DSL type checker that throws compilation errors when certain verbs of the DSL are not recognized, or tells this other noun is allowed even if it’s a dynamic name bound at runtime, or type checks literal strings containing SQL code to see if the syntax is correct, and more.</p><p class="c2">Imagine a script, where we define a small robot class and instantiate it:</p><table class="wysiwyg-macro" data-macro-name="code" data-macro-parameters="language=groovy" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGU6bGFuZ3VhZ2U9Z3Jvb3Z5fQ&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>class Robot { void move(String dist) { println "Moved $dist" } } robot = new Robot()</pre></td></tr></table><p class="c2">And we want to operate our robot in the <code><span class="c0">operate()</span></code> method, but we want this method to be type checked:</p><table class="wysiwyg-macro" data-macro-name="code" data-macro-parameters="language=groovy" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGU6bGFuZ3VhZ2U9Z3Jvb3Z5fQ&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>@groovy.transform.TypeChecked void operate() { robot.move "left" } operate()</pre></td></tr></table><p class="c2">The static type checker will complain as it doesn’t understand where the <code>robot</code> variable is coming from, as it’s going through the binding of the script — note that we could teach the type checker to figure out binding-bound variables. It will throw an error telling us that the <span class="c0">robot</span> variable was undeclared.</p><p class="c2">But by utilizing type checker extensions, we can hook into the type checking process to teach it how to handle unresolved variables! In order to do that, we’ll specify an extension script through the newly introduced <code><span class="c0">extensions</span></code> annotation parameter of the <span class="c0"><code>@TypeChecked</code> </span>annotation:</p><table class="wysiwyg-macro" data-macro-name="code" data-macro-parameters="language=groovy" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGU6bGFuZ3VhZ2U9Z3Jvb3Z5fQ&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>@TypeChecked(extensions = 'RobotMove.groovy') void operate() { robot.move "left" }</pre></td></tr></table><p class="c2">Now it’s time to define the type checker extension script called <code><span class="c0">RobotMove.groovy</span></code>. The type checker extension script is written by applying a new DSL — the “type checking DSL”. The DSL provides various hooks for type checker extensions to register to. Going back to the example above, we register for unresolved variables using the <code><span class="c0">unresolvedVariable</span></code> hook:</p><table class="wysiwyg-macro" data-macro-name="code" data-macro-parameters="language=groovy" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGU6bGFuZ3VhZ2U9Z3Jvb3Z5fQ&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>unresolvedVariable { VariableExpression var -> if ('robot' == var.name) { def robotClass = context.source.AST.classes.find { it.name == 'Robot' } storeType(var, robotClass) handled = true } }</pre></td></tr></table><p class="c2">The type checker extension script needs to be on the classpath. If this is the case, the script gets notified during compile-time when the static type checker encounters an unresolved variable. The unresolved variable closure is handed over a <code><span class="c0">VariableExpression</span></code>.</p><p class="c2">The <code><span class="c0">VariableExpression</span></code> is an object directly from Groovy’s AST (Abstract Syntax Tree). It is a representation of the unresolved variable expression. The script checks if the variable is named <code><span class="c0">robot</span></code>, if this is the case, we lookup a <code><span class="c0">ClassNode</span></code> representing the <code><span class="c0">Robot</span></code> class, and store the type of that variable back in the AST. At the end, the <code><span class="c0">handled</span></code> property is set to true, to indicate the type checker already managed that variable. As a consequence, you won’t get the compilation error about that undeclared variable.</p><p class="c2">To continue the journey, let’s consider the case where the user enters a wrong direction string. We could of course use an enum or some other class containing direction constants, but for the sake of the example, we’ll have a look at how we can teach the type checker to inspect strings and how you can actually throw your own compilation errors.</p><p class="c2">For that purpose, let’s say a robot can only move left, right, forward and backward. And now, let’s change our robot move instruction to:</p><table class="wysiwyg-macro" data-macro-name="code" data-macro-parameters="language=groovy" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGU6bGFuZ3VhZ2U9Z3Jvb3Z5fQ&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>robot.move "sideways"</pre></td></tr></table><p class="c2">The robot is not allowed to move sideways, so we should instruct the type checker to throw a compilation error if it encounters a direction the robot will not be able to understand. Here’s how we can achieve our goal, by adding a new event handler to our <code><span class="c0">RobotMove.groovy</span></code> script:</p><table class="wysiwyg-macro" data-macro-name="code" data-macro-parameters="language=groovy" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGU6bGFuZ3VhZ2U9Z3Jvb3Z5fQ&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>afterMethodCall { MethodCall mc -> def method = getTargetMethod(mc) if (mc.objectExpression.name == 'robot' && method.name == 'move') { def args = getArguments(mc) if (args && isConstantExpression(args[0]) && args[0].value instanceof String) { def content = args[0].text if (!(content in ['left', 'right', 'backward', 'forward'])) { addStaticTypeError("'${content}' is not a valid direction", args[0]) } } } } </pre></td></tr></table><p class="c2">This handler receives a <code><span class="c0">MethodCall</span></code> expression. We are using the <code><span class="c0">getTargetMethod()</span></code> utility method to retrieve the corresponding <code><span class="c0">MethodNode</span></code>. We check that the method call is a call to our <code><span class="c0">robot</span></code>, and that the name of the method corresponds to the<span class="c0">move</span> method. Then, we fetch the arguments passed to that method call, and if we’re passed a direction in the form of a string constant, we are checking that the direction is an actual allowed direction. If this is not the case, we are adding a new static typing compilation error into the mix, so that the compiler will yell at the poor user because he used a direction which is forbidden and not understood by our robot.</p><p class="c2">This second example is also interesting in a way that it shows how you can even add compilation checks on things like literal strings on a domain-specific level, paving the way for possible checks on sprintf strings, on SQL or HQL code in strings, etc, allowing you to go even further that what the Java compiler actually checks.</p><p class="c2">The extension script can make use of various event oriented extension points and utility methods coming from the <code><span class="c0">TypeCheckingExtension</span></code> class from Groovy, such as:</p><ul><li class="c3 c2" style="margin-left: 36.0pt;">unresolvedVariable</li><li class="c3 c2" style="margin-left: 36.0pt;">unresolvedProperty</li><li class="c3 c2" style="margin-left: 36.0pt;">unresolvedAttribute</li><li class="c3 c2" style="margin-left: 36.0pt;">methodNotFound</li><li class="c3 c2" style="margin-left: 36.0pt;">incompatibleAssignment</li><li class="c3 c2" style="margin-left: 36.0pt;">beforeVisitMethod</li><li class="c3 c2" style="margin-left: 36.0pt;">afterVisitMethod</li><li class="c3 c2" style="margin-left: 36.0pt;">beforeVisitClass</li><li class="c3 c2" style="margin-left: 36.0pt;">afterVisitClass</li><li class="c3 c2" style="margin-left: 36.0pt;">beforeMethodCall</li><li class="c3 c2" style="margin-left: 36.0pt;">afterMethodCall</li><li class="c3 c2" style="margin-left: 36.0pt;">onMethodSelection</li><li class="c2 c3" style="margin-left: 36.0pt;">setup</li><li class="c3 c2" style="margin-left: 36.0pt;">finish</li></ul><p class="c2">The two examples are just the tip of the iceberg, but we will work out more complete documentation of the various extension points and utility methods going forward.</p><p class="c2">For more details take a look at the <a href="http://docs.codehaus.org/display/GROOVY/Type+checking+extensions">type checking extensions documentation</a>.</p><h2 class="c2"><a />Compile-time Meta-annotations</h2><p class="c2">Annotations are a great way to add supplementary meta-data to classes, methods, fields, and other source code elements, thus frameworks, libraries, and even Groovy’s homegrown AST transformations can take advantage of them to do some special treatments to the corresponding AST nodes. Every now and then the use case arises to reuse a combination of annotations, potentially at the expense of a galore of at-signs that obscure the general intent of that particular combination.</p><p class="c2">To group annotations together, to make the intent clearer or to streamline your code, Groovy 2.1 offers a <strong><span class="c5">meta-annotation system, which allows to combine other annotations into one “alias” annotation</span></strong>.</p><p class="c2">Imagine we are using some annotations defining constraints on properties of your class, like <code><span class="c0">@NotNull</span></code>, <code><span class="c0">@Length</span></code>, or <code><span class="c0">@Pattern</span></code>, which could be defined as follows:</p><table class="wysiwyg-macro" data-macro-name="code" data-macro-parameters="language=groovy" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGU6bGFuZ3VhZ2U9Z3Jvb3Z5fQ&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>@interface NotNull {} @interface Length { int value() default 0 } @interface Pattern { String value() default ".*" } </pre></td></tr></table><p class="c2">An example of how to annotate an <code>ISBN</code> property with those annotations could look like this:</p><table class="wysiwyg-macro" data-macro-name="code" data-macro-parameters="language=groovy" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGU6bGFuZ3VhZ2U9Z3Jvb3Z5fQ&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>class Book { @NotNull @Length(10) @Pattern(/\d{9}(\d|X)/) String isbn10 }</pre></td></tr></table><p class="c2">For a single property, that’s quite a bit of annotation overload! And it could be the case of other domain classes with properties having the same validation rules as the ISBN property, where we would need to duplicate that pattern.</p><p class="c2">As of Groovy 2.1, <code><span class="c0">@groovy.transform.AnnotationCollector</span></code> can be used to solve code duplication for this use case. <code><span class="c0">@AnnotationCollector</span></code> can be specified on annotation types and acts as meta-annotation. Whenever an annotation marked with it is found, it is replaced with its own annotations. Let’s illustrate this with our ISBN example.</p><p class="c2">We will create a new annotation combination for the 13-digit ISBN standard, but this time, using the <code><span class="c0">@AnnotationCollector</span></code> meta-annotation:</p><table class="wysiwyg-macro" data-macro-name="code" data-macro-parameters="language=groovy" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGU6bGFuZ3VhZ2U9Z3Jvb3Z5fQ&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>@NotNull @Length(13) @Pattern(/\d{12}(\d|X)/) @groovy.transform.AnnotationCollector @interface ISBN13 {}</pre></td></tr></table><p class="c2"><span class="c0"><code>@ISBN13</code> </span>as a single annotation<span class="c0"> </span>can now be applied on code elements, instead of applying the entire annotation gang::</p><table class="wysiwyg-macro" data-macro-name="code" data-macro-parameters="language=groovy" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGU6bGFuZ3VhZ2U9Z3Jvb3Z5fQ&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>class Book { // ... @ISBN13 String isbn13 }</pre></td></tr></table><p class="c2">What is particularly interesting with such <strong><span class="c5">meta-annotations</span></strong> is that they are actually <strong><span class="c5">replaced at compilation time with the </span><em><span class="c5 c11">real</span></em><span class="c5"> annotations</span></strong>. So if you counted the number of annotations on the <code><span class="c0">isbn13</span></code> property, you would count 3 (<code><span class="c0">@NotNull</span></code>, <code><span class="c0">@Length</span></code> and <code><span class="c0">@Pattern</span></code>). Thus, your underlying framework doesn’t need to know about that meta-annotation solution and act accordingly.</p><h3 class="c2"><a />Alternate notation</h3><p class="c2">In our example above, we annotated our meta-annotation with the annotations that are then combined together. But for annotations for which you don’t need to specify arguments, you could have also passed the names of the annotations to combine as parameters to the annotation collector:</p><table class="wysiwyg-macro" data-macro-name="code" data-macro-parameters="language=groovy" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGU6bGFuZ3VhZ2U9Z3Jvb3Z5fQ&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>import groovy.transform.* @groovy.transform.AnnotationCollector([ToString, Singleton]) @interface ChattySingleton {}</pre></td></tr></table><p class="c2">In the above case, we combine the <code><span class="c0">@Singleton</span></code> and <code><span class="c0">@ToString</span></code> transformation into a meta-annotation called <code><span class="c0">@ChattySingleton</span></code>.</p><h3 class="c2"><a />Passing parameters</h3><p class="c2">If you need to pass some specific parameter to one of the underlying annotations which are combined, you can still do so by passing the parameter to the meta-annotation.</p><p class="c2">Let’s assume we need to combine the following annotations:</p><table class="wysiwyg-macro" data-macro-name="code" data-macro-parameters="language=groovy" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGU6bGFuZ3VhZ2U9Z3Jvb3Z5fQ&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>@interface Service {} @interface Transactional { String propagation() default "required" }</pre></td></tr></table><p class="c2">We define the meta-annotation combining both the above annotations:</p><table class="wysiwyg-macro" data-macro-name="code" data-macro-parameters="language=groovy" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGU6bGFuZ3VhZ2U9Z3Jvb3Z5fQ&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>@groovy.transform.AnnotationCollector([Service, Transactional]) @interface TransactionalService {}</pre></td></tr></table><p class="c2">But we want to change the propagation strategy for the underlying <code><span class="c0">@Transactional</span></code> annotation, we do so by passing the parameter to the meta-annotation:</p><table class="wysiwyg-macro" data-macro-name="code" data-macro-parameters="language=groovy" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGU6bGFuZ3VhZ2U9Z3Jvb3Z5fQ&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>@TransactionalService(propagation = "mandatory") class BankingService { }</pre></td></tr></table><p class="c2">Note that if two combined annotations share the same parameter name, the last annotation declared wins and gets the parameter passed to the meta-annotation.</p><h3 class="c2"><a />Custom processor</h3><p class="c2">If you need even more flexibility, meta-annotations allow you to define custom processors. The role of the custom processor is to go beyond the simple exchange of the meta-annotation with the combined annotations, to further customize the logic of that transformation.</p><p class="c2">Custom processors must be precompiled to take action, so we’ll create our processor, and then evaluate our final example with <code>GroovyShell</code>, but first, let’s talk about the use case.</p><p class="c2">We have two validation annotations for defining a minimum and maximum value for an integer property:</p><table class="wysiwyg-macro" data-macro-name="code" data-macro-parameters="language=groovy" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGU6bGFuZ3VhZ2U9Z3Jvb3Z5fQ&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>@interface Min { int value() default 0 } @interface Max { int value() default 100 }</pre></td></tr></table><p class="c2">If we want to define a range of values, with a lower and an upper bound, we could define a new annotation and implement the associated validation logic, or we could use custom meta-annotation processors to <span class="c11">replace</span> a range annotation with a minimum and a maximum one.</p><p class="c2">So instead of writing:</p><table class="wysiwyg-macro" data-macro-name="code" data-macro-parameters="language=groovy" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGU6bGFuZ3VhZ2U9Z3Jvb3Z5fQ&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>class Room { @Min(1) @Max(4) int numberOfPersons }</pre></td></tr></table><p class="c2">We could write:</p><table class="wysiwyg-macro" data-macro-name="code" data-macro-parameters="language=groovy" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGU6bGFuZ3VhZ2U9Z3Jvb3Z5fQ&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>class Room { @Range(from = 1, to = 4) int numberOfPersons }</pre></td></tr></table><p class="c2">With the normal replacement logic, there’s no way we can map the lower and upper bound values to the minimum and maximum annotation element default values. That is where custom processors come into play.</p><p class="c2">Our meta-annotation definition will look like this:</p><table class="wysiwyg-macro" data-macro-name="code" data-macro-parameters="language=groovy" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGU6bGFuZ3VhZ2U9Z3Jvb3Z5fQ&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>@Min @Max @AnnotationCollector(processor = 'RangeAnnotationProcessor') @interface Range {}</pre></td></tr></table><p class="c2">Notice how we specify that the <code><span class="c0">@Range</span></code> annotation is a combination of <code><span class="c0">@Min</span></code> and <code><span class="c0">@Max</span></code>, and more importantly, how we pass a processor parameter to the <code><span class="c0">@AnnotationCollector</span></code> to instruct it about our custom meta-annotation processing logic.</p><p class="c2">In order to create a custom processor, you have to extend the <code><span class="c0">AnnotationCollectorTransform</span></code> class and override the <code><span class="c0">visit()</span></code> method:</p><table class="wysiwyg-macro" data-macro-name="code" data-macro-parameters="language=groovy" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGU6bGFuZ3VhZ2U9Z3Jvb3Z5fQ&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>import org.codehaus.groovy.transform.AnnotationCollectorTransform import org.codehaus.groovy.ast.* import org.codehaus.groovy.control.SourceUnit class RangeAnnotationProcessor extends AnnotationCollectorTransform { List<AnnotationNode> visit(AnnotationNode collector, AnnotationNode usage, AnnotatedNode annotated, SourceUnit src) { def minExpr = usage.getMember('from') def maxExpr = usage.getMember('to') def (minAnno, maxAnno) = getTargetAnnotationList(collector, usage, src) minAnno.addMember('value', minExpr) maxAnno.addMember('value', maxExpr) usage.members.remove('from') usage.members.remove('to') return [minAnno, maxAnno] } }</pre></td></tr></table><p class="c2">A few words about the parameters : the <code><span class="c0">collector</span></code> corresponds to the <code><span class="c0">@Range</span></code> annotation definition, <code><span class="c0">usage</span></code> to the actual usage of the <code><span class="c0">@Range</span></code> annotation, <code><span class="c0">annotated</span></code> is the annotated class, and <code><span class="c0">src</span></code> is script being compiled.</p><p class="c2">We start our implementation of the processor by retrieving the numeric expressions of the bounds defined as the <span class="c0">from</span> and <span class="c0">to</span> annotation parameters, because we’ll pass those values back to the underlying <code><span class="c0">@Min</span></code> and <code><span class="c0">@Max</span></code> combined annotations. In order to do that, we retrieve the <code><span class="c0">@Min</span></code> and <code><span class="c0">@Max</span></code> combined annotations thanks to the <code><span class="c0">getTargetAnnotationList()</span></code> method. We then set the <span class="c0">value</span>s of the <code><span class="c0">@Min</span></code> and <code><span class="c0">@Max</span></code> annotations to the expressions we’ve retrieved before. We remove the <span class="c0">from</span> and <span class="c0">to</span> bounds from the <code><span class="c0">@Range</span></code> meta-annotation since those parameters aren’t <span class="c11">really</span> defined on a real annotation but on a meta-annotation. And last, we return the two <code><span class="c0">@Min</span></code> and <code><span class="c0">@Max</span></code> annotations. If you wanted the Groovy compiler to do its usual replacement logic, you could have also called <code><span class="c0">super.visit(...)</span></code>, but in our case it wasn’t needed.</p><p class="c2">The full example can be found in this Gist on Github: <span class="c6" style="color: rgb(17,85,204);text-decoration: underline;"><a class="c7" href="https://gist.github.com/4563430" style="text-decoration: inherit;">https://gist.github.com/4563430</a></span></p><p class="c2">Additional details can be found in the <a href="http://docs.codehaus.org/display/GROOVY/Meta-annotations">meta-annotations documentation</a>.</p><h2 class="c2">Compilation customization</h2><h3 class="c2"><a />Custom base script class flag</h3><p class="c2">When integrating and evaluating Groovy scripts in an application for business rules or Domain-Specific Languages, it is often valuable to define a base script class, in order to add various utility methods, properties, or interception mechanisms for missing methods or properties.</p><p class="c2">The <code><span class="c0">CompilerConfiguration</span></code> object, that you can pass to <code><span class="c0">GroovyShell</span></code> and other integration mechanisms, allows you to specify a base script class with the <code><span class="c0">setScriptBaseClass()</span></code> method.</p><p class="c2">As of Groovy 2.1, we introduce the ability to define a base script class reference for your scripts via an additional command-line option <code><span class="c0">-b</span></code> / <code><span class="c0">--basescript</span></code> for the <code><span class="c0">groovyc</span></code> command, as well as for the <code><span class="c0">groovy</span></code> command.</p><p class="c2">Here’s an example using a script called <code><span class="c0">businessRule.groovy</span></code>:</p><table class="wysiwyg-macro" data-macro-name="code" data-macro-parameters="language=groovy" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGU6bGFuZ3VhZ2U9Z3Jvb3Z5fQ&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>assert lookupRate(EUR, USD) == 1.33</pre></td></tr></table><p class="c2">In the above script, we notice two things: the usage of a <code><span class="c0">lookupRate()</span></code> method, and two undeclared variables: <code><span class="c0">EUR</span></code> and <code><span class="c0">USD</span></code>. Neither the method, nor the variables have been defined in our script. Instead, they are provided by a base script class, which can look like the following <code><span class="c0">ExchangeRateBaseScript.groovy</span></code> class:</p><table class="wysiwyg-macro" data-macro-name="code" data-macro-parameters="language=groovy" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGU6bGFuZ3VhZ2U9Z3Jvb3Z5fQ&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>abstract class ExchangeRateBaseScript extends Script { def lookupRate(String currency1, String currency2) { if (currency1 == 'EUR' && currency2 == 'USD') return 1.33 else return 1 } def getProperty(String name) { name } }</pre></td></tr></table><p class="c2">The <code><span class="c0">lookupRate()</span></code> method used in our script is declared in the the base class, and the two currencies are retrieved via the <code><span class="c0">getProperty()</span></code> method.</p><p class="c2">Now it’s time to wire them together, by instructing the <span class="c0">groovyc </span>compiler or the <span class="c0"><code>groovy</code> </span>command line launcher to use our base script class for all <code><span class="c0">groovy.lang.Script</span></code> descendants:</p><table class="wysiwyg-macro" data-macro-name="code" data-macro-parameters="language=bash" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGU6bGFuZ3VhZ2U9YmFzaH0&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>groovy --basescript ExchangeRateBaseScript.groovy businessRule.groovy</pre></td></tr></table><h3 class="c2"><a />Compiler configuration script</h3><p class="c2">Similarly to the <code><span class="c0">--basescript</span></code> flag, there’s another new option for the <code><span class="c0">groovy</span></code> and <code><span class="c0">groovyc</span></code> commands: the <code><span class="c0">--configscript</span></code> flag. Its purpose is to let you further configure the compiler, in a configuration script, by parameterizing the <code><span class="c0">CompilerConfiguration</span></code> object used for the compilation.</p><p class="c2">With a <code><span class="c0">CompilerConfiguration</span></code>, you can customize the various aspects of the Groovy compilation process. For example, you can specify various compilation customizers introduced in Groovy 1.8. Imagine you want to add a new default import to your classes, like importing all <code><span class="c0">java.lang.Math</span></code> functions and constants, so that your scripts and classes don’t have to prefix those functions and constants all the time, and to avoid having to do that import wherever needed. Here’s how you can proceed.</p><p class="c2">At first, your script, <code><span class="c0">mathFormula.groovy</span></code>, contains the following lines:</p><table class="wysiwyg-macro" data-macro-name="code" data-macro-parameters="language=groovy" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGU6bGFuZ3VhZ2U9Z3Jvb3Z5fQ&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>import static java.lang.Math.* assert sin(PI/2) == 1 </pre></td></tr></table><p class="c2">For evaluating such math expressions, you wish to make the static import implicit, so that the final script will actually look like this:</p><table class="wysiwyg-macro" data-macro-name="code" data-macro-parameters="language=groovy" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGU6bGFuZ3VhZ2U9Z3Jvb3Z5fQ&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>assert sin(PI/2) == 1</pre></td></tr></table><p class="c2">If you’d run it as is, you’d get an error message saying:</p><table class="wysiwyg-macro" data-macro-name="code" data-macro-parameters="language=none" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGU6bGFuZ3VhZ2U9bm9uZX0&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>No such property: PI for class: mathFormula</pre></td></tr></table><p class="c2">We need to use <code><span class="c0">CompilerConfiguration</span></code> to do add an <code><span class="c0">ImportCustomizer</span></code>. We’ll create a<span class="c0">i <code>mportConfigurer.groovy</code></span> script with the content below:</p><table class="wysiwyg-macro" data-macro-name="code" data-macro-parameters="language=groovy" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGU6bGFuZ3VhZ2U9Z3Jvb3Z5fQ&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>import org.codehaus.groovy.control.customizers.ImportCustomizer def importCustomizer = new ImportCustomizer() importCustomizer.addStaticStar('java.lang.Math') configuration.addCompilationCustomizers(importCustomizer)</pre></td></tr></table><p class="c2">We import and then instantiate an <code><span class="c0">ImportCustomizer</span></code>, on which we ask for a static star import of the methods and constants of the <code><span class="c0">java.lang.Math</span></code> class. Eventually, we pass that customizer to the <code><span class="c0">configuration</span></code> variable, which is an instance of <code><span class="c0">CompilerConfiguration</span></code> that will be used for the compilation of your math formula.</p><p class="c2">Now, we are able to execute your formula with the following command-line:</p><table class="wysiwyg-macro" data-macro-name="code" data-macro-parameters="language=bash" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGU6bGFuZ3VhZ2U9YmFzaH0&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>groovy --configscript importConfigurer.groovy mathFormula.groovy</pre></td></tr></table><h3 class="c2"><a />Source-aware customizer</h3><p class="c2">If you use the groovy compiler to compile all your classes, one drawback of the approach above is that the customization applies globally to all classes that are going to be compiled. You may want to add certain default imports only in certain classes (ie. scripts containing math), but you might want to do something different for other classes, like adding a <code><span class="c0">@ToString</span></code> transformation to all the domain classes of your application. For that purpose, a new customizer was created, the <code><span class="c0">SourceAwareCustomizer</span></code>, to let you filter which classes should be impacted by particular compilation customizations, such as filtering by class name, by file extension, or by a custom logic.</p><p class="c2">Coming back to our previous example, let’s add the default import to our <code><span class="c0">mathFormula.groovy</span></code> script, but add a <code><span class="c0">@ToString</span></code> transformation to the <code><span class="c0">MyDomain.groovy</span></code> class:</p><table class="wysiwyg-macro" data-macro-name="code" data-macro-parameters="language=groovy" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGU6bGFuZ3VhZ2U9Z3Jvb3Z5fQ&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>import org.codehaus.groovy.control.customizers.* import groovy.transform.ToString def importCustomizer = new ImportCustomizer() importCustomizer.addStaticStar('java.lang.Math') configuration.addCompilationCustomizers( new SourceAwareCustomizer(new ASTTransformationCustomizer(ToString)) { boolean acceptBaseName(baseName) { baseName ==~ 'MyDomain' } }, new SourceAwareCustomizer(importCustomizer) { boolean acceptBaseName(baseName) { baseName ==~ 'mathFormula' } })</pre></td></tr></table><h3 class="c2"><a />Compiler customization builder</h3><p class="c2">The more complex the customization becomes, the more cumbersome the above configuration becomes to write too, that’s why Groovy 2.1 also provides a builder for building these types of configurations.</p><p class="c2">The builder allows you to use a familiar declarative syntax and saves you from adding manually various imports. Let’s adapt our example above with the builder:</p><table class="wysiwyg-macro" data-macro-name="code" data-macro-parameters="language=groovy" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGU6bGFuZ3VhZ2U9Z3Jvb3Z5fQ&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>withConfig(configuration) { source(basenameValidator: { it.endsWith('MyDomain') }) { ast(ToString) } source(basenameValidator: { it.endsWith('mathFormula') }) { imports { staticStar 'java.lang.Math' } } }</pre></td></tr></table><p class="c2">The configuration code is easier to read and maintain, thanks to the clarity brought by the <span class="c11">builder</span> approach. But we’ve only seen a couple examples of customization, and you should have a look at the other customizations available in the<span class="c0"> org.codehaus.groovy.control.customizers.builder</span> package to learn more about them.</p><p class="c2">More details can be found in the <a href="http://docs.codehaus.org/display/GROOVY/Advanced+compiler+configuration">advanced compiler configuration documentation</a>.</p><h2><span>Other Minor Enhancements</span></h2><h3><span>Additional DGM methods</span></h3><p>There are now <code>leftShift</code> and <code>withFormatter</code> methods for <code>Appendable</code> objects.<br />There are now methods for creating temporary directories and determining the total size of all files in a directory.<br />There is now a <code>collectMany</code> for maps (has been backported to earlier versions of Groovy too).<br />There is now a <code>closeStreams()</code> method for <code>Process</code> objects.</p><h3>GroovyDoc</h3><p>You ca now explicitly set a file encoding.</p><h3>Command-line</h3><p>There is support for using a "jar:" prefix when running a script from a URL, in addition to the "file:" and "http:".</p><h3>XML Processing</h3><p>There is a method for escaping / encoding XML entities in Strings.<br />There is a convenience method for serializing <code>Elements</code> objects. <br />You can now clone <code>Node</code> and <code>NodeList</code> objects. <br />The name() method now works for all <code>Node</code> objects, not just <code>Element</code> objects. </p><h3>ConfigSlurper</h3><p>Multiple environments blocks are now supported and merged.</p><h3>@Delegate</h3><p>Can now carry over annotations if desired for methods and method parameters.</p><h3>@ToString</h3><p>You can now cache the <code>toString</code> value. This is useful for immutable objects.</p><h3>@EqualsAndHashCode</h3><p>You can now cache the calculated hashCode value. This is useful for immutable objects.</p><h3>@Immutable</h3><p>You can now specify <code>knownImmutables</code>. This is useful when you know you are using an immutable object, but its type isn't one of the known immutable types.</p><h3>@AutoClone</h3><p>There is now a <code>SIMPLE</code> <code>AutoCloneStyle</code> which avoids some annoyances with Java's cloning behavior from <code>Object</code>. Those who need to clone Grails domain objects might find this useful.</p><p> </p>
Please type the word appearing in the picture.
Attachments
Labels
Location
Watch this page
< Edit
Preview >
Loading…
Save
Cancel
Next hint
search
attachments
weblink
advanced