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
<h1>Extension modules for extension methods</h1><h2>What is an extension method?</h2><p>Since version 2.0, Groovy supports the notion of extension module. Basically, an extension module allows you to plugin extension methods to existing classes, just like regular Groovy does. For example, when you write:</p><table class="wysiwyg-macro" data-macro-name="code" data-macro-parameters="language=groovy|linenumbers=true|title=Standard extension method" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGU6dGl0bGU9U3RhbmRhcmQgZXh0ZW5zaW9uIG1ldGhvZHxsaW5lbnVtYmVycz10cnVlfGxhbmd1YWdlPWdyb292eX0&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>def file = new File(...) def contents = file.getText('utf-8')</pre></td></tr></table><p>The <em>getText</em> method doesn't exist on the <em>File</em> class. However, Groovy knows it because it is defined in a special class <em>ResourceGroovyMethods</em> (formely, the method was defined in <em>DefaultGroovyMethods</em>):</p><table class="wysiwyg-macro" data-macro-name="code" data-macro-parameters="language=java|title=ResourceGroovyMethods.java" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGU6dGl0bGU9UmVzb3VyY2VHcm9vdnlNZXRob2RzLmphdmF8bGFuZ3VhZ2U9amF2YX0&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>public static String getText(File file, String charset) throws IOException { return IOGroovyMethods.getText(newReader(file, charset)); }</pre></td></tr></table><p>You may notice that the extension method is defined using a static method in a "helper" class (where various extension methods are defined). The first argument of the <em>getText</em> method corresponds to the receiver, while additional parameters correspond to the arguments of the extension method. So here, we are defining a method called <em>getText</em> on the <em>File</em> class (because the first argument is a File), which takes a single argument as a parameter (the encoding <em>String</em>).</p><h2>Definining your own module</h2><h3>Concept</h3><p>Thanks to improved modularity, Groovy 2 now adds support for your custom extension methods. For that, you only have to write two things:</p><ol><li>your extension class, just like <em>DefaultGroovyMethods</em>, <em>IOGroovyMethods</em>, ...</li><li>a descriptor file for your module</li></ol><p>Then you just need to pack your extension module into a jar file and add it to the classpath! Groovy will automatically recognize the module at startup.</p><h3>Writing your extension class</h3><p>As we saw before, adding methods to an existing class is as simple as writing a helper class which will only contain static methods. Imagine we want to add a method called <em>reverseToUpperCase</em> on the <em>String</em> class. This method would reverse the string then turn it to upper case. Then, you can write the following helper class:</p><table class="wysiwyg-macro" data-macro-name="code" data-macro-parameters="language=java|title=StringExtension" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGU6dGl0bGU9U3RyaW5nRXh0ZW5zaW9ufGxhbmd1YWdlPWphdmF9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>package com.example; /** * An extension class for the String class. */ public class StringExtension { public static String reverseToUpperCase(String self) { StringBuilder sb = new StringBuilder(self); sb.reverse(); return sb.toString().toUpperCase(); } }</pre></td></tr></table><p>That's all! Now imagine that you want to extend a class with a static method. For example, we would like to add an <em>randomUUID</em>() method to the <em>String</em> class which would return a random UUID string. Then, we must declare another extension class. The important thing to understand is that instance extension methods and static extension methods must be defined in two separate files. The only thing that will make a difference is the descriptor (see below). Then, the static extension helper class would look like this:</p><table class="wysiwyg-macro" data-macro-name="code" data-macro-parameters="language=java|title=StringStaticExtension.java" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGU6dGl0bGU9U3RyaW5nU3RhdGljRXh0ZW5zaW9uLmphdmF8bGFuZ3VhZ2U9amF2YX0&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>import java.util.UUID; /** * Static extension methods for the String class */ public class StringStaticExtension { public static String randomUUID(String selfType) { return UUID.randomUUID().toString(); } }</pre></td></tr></table><h3>The module descriptor</h3><p>For Groovy to be able to load your extension methods, you must declare your extension helper classes. You must create a file named <strong>org.codehaus.groovy.runtime.ExtensionModule</strong> into the <strong>META-INF/services</strong> directory:</p><table class="wysiwyg-macro" data-macro-name="code" data-macro-parameters="language=none|title=org.codehaus.groovy.runtime.ExtensionModule" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGU6dGl0bGU9b3JnLmNvZGVoYXVzLmdyb292eS5ydW50aW1lLkV4dGVuc2lvbk1vZHVsZXxsYW5ndWFnZT1ub25lfQ&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>moduleName=string-module moduleVersion=1.0-test extensionClasses=com.example.StringExtension staticExtensionClasses=com.example.StringStaticExtension</pre></td></tr></table><p>The module descriptor requires 4 keys:</p><ul><li><em>moduleName</em> : the name of your module</li><li><em>moduleVersion</em>: the version of your module. Note that version number is only used to check that you don't load the same module in two different versions.</li><li><em>extensionClasses</em>: the list of extension helper classes for instance methods. You can provide several classes, given that they are comma separated.</li><li><em>staticExtensionClasses</em>: the list of extension helper classes for static methods. You can provide several classes, given that they are comma separated.</li></ul><p>Note that it is not required for a module to define both static helpers and instance helpers, and that you may add several classes to a single module. You can also extend different classes in a single module without problem. It is even possible to use different classes in a single extension class, but it is recommended to group extension methods into classes by feature set.</p><h1>Advanced modules</h1><p>Technically, the previous description about how to add extension methods to an existing class is a user-friendly way of doing it, but Groovy doesn't force you to use this standard mechanism. If you want to, you can write your own extension module implementation class, given that a module returns a list of MetaMethods to be added to a class. However, implementing such a module is not easy, and won't be covered by this tutorial. If you need to do that, please refer to the <em>org.codehaus.groovy.runtime.m12n.ExtensionModule</em> and <em>org.codehaus.groovy.runtime.m12n.ExtensionModuleRegistry</em> classes.</p><h1>FAQ</h1><blockquote><p>Are extension modules compatible with type checking?</p></blockquote><p>Yes, if the extension descriptor and the extension class is found on compilation classpath.</p><blockquote><p>Are extension modules compatible with static compilation ?</p></blockquote><p>Yes, if the extension descriptor and the extension class is found on compilation classpath.</p><blockquote><p>When I compile my project using Gradle and @CompileStatic, my code using an extension module fails compilation.</p></blockquote><p>As of Gradle 1.4, Gradle's native Groovy compiler integration doesn't seem to be compatible with extension modules. A fix is available in Groovy 2.1.2. As a workaround, you can use the Ant compiler integration:</p><table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>compileGroovy.groovyOptions.useAnt = true compileTestGroovy.groovyOptions.useAnt = true</pre></td></tr></table><p>See <a href="https://jira.codehaus.org/browse/GROOVY-6008">https://jira.codehaus.org/browse/GROOVY-6008</a><br /><br /></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