<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;AkUDQXo_eyp7ImA9WhRUFkQ.&quot;"><id>tag:blogger.com,1999:blog-6671019398434141469</id><updated>2012-01-27T22:04:30.443+01:00</updated><category term="Mockito" /><category term="Gr8Conf" /><category term="GroovyGoodness:CommandLine" /><category term="Alfresco 3.4.d" /><category term="Fitnesse" /><category term="Flex:Reference" /><category term="Groovy programming" /><category term="GrailsGoodness:Prompt" /><category term="GSP" /><category term="Mercurial" /><category term="Testing" /><category term="GroovyGoodness:AST" /><category term="Grails:Goodness" /><category term="SpringSource Tool Suite" /><category term="GriffonGoodness:CommandLine" /><category term="Git" /><category term="GrailsGoodness:Request" /><category term="DSL" /><category term="Grails 1.3.7" /><category term="GroovyGoodness:JMX" /><category term="GroovyGoodness:GKD" /><category term="GriffonGoodness:Beginner" /><category term="Google App Egine" /><category term="Mac" /><category term="Hudson" /><category term="GrailsGoodness:CommandLine" /><category term="Spock" /><category term="Flex:Samples" /><category term="Weekly Sightings" /><category term="GroovyGoodness:Closure" /><category term="Groovy Server Pages" /><category term="CSS:Reference" /><category term="Alfresco Web Editor" /><category term="Groovy 1.8.4" /><category term="GroovyGoodness:API" /><category term="GroovyGoodness:" /><category term="Grails 1.1" /><category term="Spock:Spotlight" /><category term="Alfresco Web Quick Start" /><category term="jQuery" /><category term="GroovyGoodness:CodeNarc" /><category term="GroovyGoodness:SQL" /><category term="XSLT" /><category term="Groovy 1.7" /><category term="MySQL" /><category term="GroovyGoodness:Date" /><category term="Javascript" /><category term="Yahoo Pipes" /><category term="Tomcat6" /><category term="Grails CLI" /><category term="XML" /><category term="Groovy Server Page" /><category term="Groovy 1.7.9" /><category term="NetBeans:Samples" /><category term="GroovyGoodness:Intermediate" /><category term="NetBeans" /><category term="OSX" /><category term="NetBeans 6.5" /><category term="Groovy" /><category term="GrailsGoodness:Plugins" /><category term="Gradle 0.8" /><category term="GroovyGoodness:MOP" /><category term="Tomcat" /><category term="SOAP web services" /><category term="Groovy 1.7.2" /><category term="Firefox" /><category term="Groovy 1.8" /><category term="Groovy:Grassroots" /><category term="Cocoon" /><category term="Eclipse" /><category term="GroovyGoodness:GDK" /><category term="Groovy:Goodness GroovyGoodness:GDK" /><category term="GMetrics 0.3" /><category term="GroovyGoodness:Beginner" /><category term="Tomcat7" /><category term="Gradle 0.9" /><category term="CodeNarc 0.11" /><category term="GroovyGoodness:JSON" /><category term="GroovyGoodness:Files" /><category term="JDriven" /><category term="Groovy 1.7.4" /><category term="Spring 3" /><category term="Maven:Reference" /><category term="GroovyGoodness:String" /><category term="Groovy 1.8.1" /><category term="GrailsGoodness:Testing" /><category term="Alfresco" /><category term="GroovyGoodness:Scripts" /><category term="IntelliJ IDEA" /><category term="Apache Camel" /><category term="GroovyGoodness:Advanced" /><category term="Log4j" /><category term="Gr8Conf2011" /><category term="GroovyGoodness:IO" /><category term="griffon" /><category term="Scala" /><category term="Grails 1.2" /><category term="Groovy:Goodness GroovyGoodness:XML" /><category term="STS" /><category term="Groovy 1.6.8" /><category term="GrailsGoodness:GSP" /><category term="Wicket" /><category term="GroovyGoodness:Operators" /><category term="Grails 1.1.2" /><category term="Grails" /><category term="Software:Toolbox" /><category term="GrailsGoodness:Tomcat" /><category term="GroovyGoodness:XML" /><category term="Terminal" /><category term="Spring" /><category term="JSON" /><category term="GroovyGoodness:Collections" /><category term="Android" /><category term="UI:Reference" /><category term="GroovyGoodness:DSL" /><category term="Groovy 1.7.3" /><category term="Gradle:Goodness" /><category term="Grails 2.0" /><category term="CodeNarc" /><category term="Gaelyk" /><category term="Grails 1.0.x" /><category term="Gradle 0.9.1" /><category term="GMetrics" /><category term="Book Review" /><category term="GroovyGoodness:Grape" /><category term="GrailsGoodness:Controllers" /><category term="Logback" /><category term="Groovy 1.8.3" /><category term="GroovyGoodness:Annotations" /><category term="Maven2" /><category term="Grails 1.1.1" /><category term="GroovyGoodness:Testing" /><category term="Spocklight" /><category term="NetBeans 6.1" /><category term="YUI" /><category term="Java" /><category term="RESTful webservices" /><category term="GroovyGoodness:Builders" /><category term="NetBeans 6.7.1" /><category term="GroovyGoodness:Syntax" /><category term="Cocoon 2.2" /><category term="Jenkins" /><category term="Gradle" /><category term="Javascript:Reference" /><category term="Griffon:Goodness" /><category term="NetBeans 6.7" /><category term="Maven" /><category term="Linux" /><category term="GPars" /><category term="Groovy:Goodness" /><category term="Ubuntu" /><category term="GroovyGoodness:Java" /><title>Messages from mrhaki</title><subtitle type="html">assert &amp;#39;mrhaki&amp;#39; == [&amp;#39;Hubert&amp;#39;,&amp;#39;Alexander&amp;#39;,&amp;#39;Klein&amp;#39;,&amp;#39;Ikkink&amp;#39;].inject(&amp;#39;mr&amp;#39;) { c,n -&amp;gt; c += n[0].toLowerCase() }</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://mrhaki.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://mrhaki.blogspot.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/6671019398434141469/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>Hubert Klein Ikkink</name><uri>https://profiles.google.com/116304108087638220732</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-VhI52jWYsR8/AAAAAAAAAAI/AAAAAAAAE_E/g4F9a-hMya8/s512-c/photo.jpg" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>675</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/mrhaki" /><feedburner:info uri="mrhaki" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;DUEHR3o-eCp7ImA9WhRUEkQ.&quot;"><id>tag:blogger.com,1999:blog-6671019398434141469.post-8227473520671709428</id><published>2012-01-23T06:47:00.000+01:00</published><updated>2012-01-23T06:47:16.450+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-23T06:47:16.450+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="GroovyGoodness:JSON" /><category scheme="http://www.blogger.com/atom/ns#" term="JDriven" /><category scheme="http://www.blogger.com/atom/ns#" term="Groovy" /><category scheme="http://www.blogger.com/atom/ns#" term="Groovy:Goodness" /><category scheme="http://www.blogger.com/atom/ns#" term="GroovyGoodness:XML" /><category scheme="http://www.blogger.com/atom/ns#" term="Grails" /><title>Groovy Goodness: Solve Naming Conflicts with Builders</title><content type="html">&lt;p&gt;With Groovy we can use for example the MarkupBuilder or JSONBuilder to create XML or JSON content. The builders are a very elegant way to create the content. Most builders in Groovy use the &lt;code&gt;invokeMethod&lt;/code&gt; and &lt;code&gt;getProperty&lt;/code&gt; and &lt;code&gt;setProperty&lt;/code&gt; methods to dynamically build the contents. But this also means that if we have builder node names that are the same as method or property names in the local context of our code running the builder, that we have a naming conflict. Let's see this with a simple sample:&lt;/p&gt;&lt;pre class="brush:groovy"&gt;import groovy.xml.*

def body = []

def writer = new StringWriter()
def builder = new MarkupBuilder(writer)
builder.message {
    body(contentType: 'plain') {
        text 'Simple message'
    }
}

def contents = writer.toString()
println contents
&lt;/pre&gt;&lt;p&gt;When we run this code we get an error message:&lt;/p&gt;&lt;pre class="brush:plain;light:true"&gt;groovy.lang.MissingMethodException: No signature of method: java.util.ArrayList.call() is applicable for argument types: (java.util.LinkedHashMap, xmlmessage$_run_closure1_closure2) values: [[contentType:plain], xmlmessage$_run_closure1_closure2@50502819]
Possible solutions: tail(), wait(), last(), any(), max(), clear()
 at xmlmessage$_run_closure1.doCall(xmlmessage.groovy:7)
 at xmlmessage$_run_closure1.doCall(xmlmessage.groovy)
 at xmlmessage.run(xmlmessage.groovy:6)
&lt;/pre&gt;&lt;p&gt;Groovy tries to use the &lt;code&gt;ArrayList&lt;/code&gt; class of our books variable to execute a &lt;code&gt;call&lt;/code&gt; method with two parameters of type &lt;code&gt;LinkedHashMap&lt;/code&gt; and closure. So our local variable is found by the builder and the builder tries to use this variable, which results in the shown error.&lt;/p&gt;&lt;p&gt;The following sample shows what happens if we have a local method with the same name as a node in the builder:&lt;/p&gt;&lt;pre class="brush:groovy"&gt;import groovy.xml.*

def body(value) {
    println "body contents is $value"
}

def writer = new StringWriter()
def builder = new MarkupBuilder(writer)
builder.message {
    body {
        text 'Simple message'
    }
}

def contents = writer.toString()
println contents
&lt;/pre&gt;&lt;p&gt;We get the following output if we run this script:&lt;/p&gt;&lt;pre class="brush:plain;light:true"&gt;body contents is 
&amp;lt;message&amp;gt;
  &amp;lt;text&amp;gt;Simple message&amp;lt;/text&amp;gt;
&amp;lt;/message&amp;gt;
&lt;/pre&gt;&lt;p&gt;Our method with the name body has the same signature and name as the body node in the builder. Our local method is invoked and we see the output of the &lt;code&gt;println&lt;/code&gt; statement.&lt;/p&gt;&lt;p&gt;To solve this naming conflict we can change the name of our local variable or method. But this is not always possible or desired. Imagine the method or variable is dynamically added to our class than we cannot change the name. But we can also change our builder syntax slightly to get what we want.&lt;/p&gt;&lt;p&gt;To force our builder to use the builder's code to create the contents we can prepend the node name with &lt;code&gt;delegate&lt;/code&gt;. Delegate is the closure context of our builder. This way our builder will not use any already defined variable or method names to create the content.&lt;/p&gt;&lt;pre class="brush:groovy"&gt;import groovy.xml.*

def body = []

def writer = new StringWriter()
def builder = new MarkupBuilder(writer)
builder.message {
    delegate.body(contentType: 'plain') {
        text 'Simple message'
    }
}

def contents = writer.toString()
println contents
&lt;/pre&gt;&lt;p&gt;When we run the script we get the following output:&lt;/p&gt;&lt;pre class="brush:plain;light:true"&gt;&amp;lt;message&amp;gt;
  &amp;lt;body contentType='plain'&amp;gt;
    &amp;lt;text&amp;gt;Simple message&amp;lt;/text&amp;gt;
  &amp;lt;/body&amp;gt;
&amp;lt;/message&amp;gt;
&lt;/pre&gt;&lt;p&gt;And that is the output we want.&lt;/p&gt;&lt;p&gt;If we are using Grails and use the &lt;code&gt;render&lt;/code&gt; method to create XML or JSON we must be aware that methods are also dynamically available in a controller. For example the &lt;code&gt;message&lt;/code&gt; method from the Grails tag libraries is a method in a controller:&lt;/p&gt;&lt;pre class="brush:groovy"&gt;package builder.naming

class SampleController {

    def index() {
        render(contenType: 'text/xml') {
            message {
                content 'Contents'
            }
        }
    }
}
&lt;/pre&gt;&lt;p&gt;If we invoke this controller we get the following XML output:&lt;/p&gt;&lt;pre class="brush:plain;light:true"&gt;&amp;lt;content&amp;gt;Contents&amp;lt;/content&amp;gt;
&lt;/pre&gt;&lt;p&gt;But if we change the code to:&lt;/p&gt;&lt;pre class="brush:groovy"&gt;package builder.naming

class SampleController {

    def index() {
        render(contenType: 'text/xml') {
            delegate.message {
                content 'Contents'
            }
        }
    }
}
&lt;/pre&gt;&lt;p&gt;We get the following output:&lt;/p&gt;&lt;pre class="brush:plain;light:true"&gt;&amp;lt;message&amp;gt;&amp;lt;content&amp;gt;Contents&amp;lt;/content&amp;gt;&amp;lt;/message&amp;gt;
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6671019398434141469-8227473520671709428?l=mrhaki.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/mrhaki/~4/xpgTLV5hGMo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://mrhaki.blogspot.com/feeds/8227473520671709428/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://mrhaki.blogspot.com/2012/01/groovy-goodness-solve-naming-conflicts.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6671019398434141469/posts/default/8227473520671709428?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6671019398434141469/posts/default/8227473520671709428?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/mrhaki/~3/xpgTLV5hGMo/groovy-goodness-solve-naming-conflicts.html" title="Groovy Goodness: Solve Naming Conflicts with Builders" /><author><name>Hubert Klein Ikkink</name><uri>https://profiles.google.com/116304108087638220732</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-VhI52jWYsR8/AAAAAAAAAAI/AAAAAAAAE_E/g4F9a-hMya8/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://mrhaki.blogspot.com/2012/01/groovy-goodness-solve-naming-conflicts.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUEEQHY9cCp7ImA9WhRVE0k.&quot;"><id>tag:blogger.com,1999:blog-6671019398434141469.post-2764782265402019005</id><published>2012-01-12T06:53:00.000+01:00</published><updated>2012-01-12T06:53:21.868+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-12T06:53:21.868+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Grails:Goodness" /><category scheme="http://www.blogger.com/atom/ns#" term="Grails 2.0" /><category scheme="http://www.blogger.com/atom/ns#" term="Groovy" /><category scheme="http://www.blogger.com/atom/ns#" term="Grails" /><title>Grails Goodness: Generate Links Outside Controllers or Tag Libraries</title><content type="html">&lt;p&gt;In Grails we can create a link to a controller with the &lt;code&gt;link()&lt;/code&gt; method. This works in the context of a request, like in a controller, tag library or Groovy Server Page (GSP). But since Grails 2.0 we can also generate links in services or any other Spring bean in our project. To create a link we need to inject the &lt;em&gt;grailsLinkGenerator&lt;/em&gt; bean into our class. The grailsLinkGenerator bean has a &lt;code&gt;link()&lt;/code&gt; method with the same argument list as we are already used to. We can define for example the controller, action and other parameters and the method will return a correct link.&lt;/p&gt;&lt;p&gt;We can also create the link for a resource with the &lt;code&gt;resource()&lt;/code&gt; method. And to get the context path and server base URL we use the methods &lt;code&gt;getContextPath()&lt;/code&gt; and &lt;code&gt;getServerBaseURL()&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;The following service uses the link generator to create links in a Grails service.&lt;/p&gt;&lt;pre class="brush:groovy"&gt;// File: grails-app/service/link/generator/LinkService.groovy
package link.generator

import org.codehaus.groovy.grails.web.mapping.LinkGenerator

class LinkService {

    // Inject link generator
    LinkGenerator grailsLinkGenerator

    String generate() {
        // Generate: http://localhost:8080/link-generator/sample/show/100
        grailsLinkGenerator.link(controller: 'sample', action: 'show', id: 100, absolute: true)
    }

    String resource() {
        // Generate: /link-generator/css/main.css
        grailsLinkGenerator.resource(dir: 'css', file: 'main.css')
    }

    String contextPath() {
        // Generate: /link-generator
        grailsLinkGenerator.contextPath
    }

    String serverUrl() {
        // Generate: http://localhost:8080/link-generator
        grailsLinkGenerator.serverBaseURL
    }
}
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6671019398434141469-2764782265402019005?l=mrhaki.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/mrhaki/~4/jOL9XW4fc9c" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://mrhaki.blogspot.com/feeds/2764782265402019005/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://mrhaki.blogspot.com/2012/01/grails-goodness-generate-links-outside.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6671019398434141469/posts/default/2764782265402019005?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6671019398434141469/posts/default/2764782265402019005?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/mrhaki/~3/jOL9XW4fc9c/grails-goodness-generate-links-outside.html" title="Grails Goodness: Generate Links Outside Controllers or Tag Libraries" /><author><name>Hubert Klein Ikkink</name><uri>https://profiles.google.com/116304108087638220732</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-VhI52jWYsR8/AAAAAAAAAAI/AAAAAAAAE_E/g4F9a-hMya8/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://mrhaki.blogspot.com/2012/01/grails-goodness-generate-links-outside.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkAERns8fip7ImA9WhRVEkg.&quot;"><id>tag:blogger.com,1999:blog-6671019398434141469.post-6815100081296441916</id><published>2012-01-11T06:11:00.000+01:00</published><updated>2012-01-11T06:11:47.576+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-11T06:11:47.576+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Grails:Goodness" /><category scheme="http://www.blogger.com/atom/ns#" term="Grails 2.0" /><category scheme="http://www.blogger.com/atom/ns#" term="Groovy" /><category scheme="http://www.blogger.com/atom/ns#" term="GrailsGoodness:Controllers" /><category scheme="http://www.blogger.com/atom/ns#" term="Grails" /><title>Grails Goodness: Date Request Parameter Value Conversions</title><content type="html">&lt;p&gt;Grails has great support for &lt;a href="http://mrhaki.blogspot.com/2010/02/grails-goodness-type-conversion-on.html"&gt;type conversion on request parameters&lt;/a&gt;. And since Grails 2.0 the support has been extended to include dates. In our controller we can use the &lt;code&gt;date()&lt;/code&gt; method on the &lt;code&gt;params&lt;/code&gt; object to get a date value. The value of a request parameter is a String, so the String value is parsed to a Date object.&lt;/p&gt;&lt;p&gt;The default expected date format is &lt;em&gt;yyyy-MM-dd HH:mm:ss.S&lt;/em&gt;. If we don't specify a specific date format in the &lt;code&gt;date()&lt;/code&gt; method then this format is used. Or we can add a format to our &lt;code&gt;messages.properties&lt;/code&gt; with the key &lt;em&gt;date.&amp;lt;param-name&amp;gt;.format&lt;/em&gt;. Grails will first try the default format, but if the request parameter cannot be parsed to a valid Date object then Grails will do a lookup of the date format in &lt;code&gt;messages.properties&lt;/code&gt;. Technically Grails uses the MessageSource bean to get the format, so we even can define the format per language or country.&lt;/p&gt;&lt;p&gt;Alternatively we can pass a date format or multiple date formats to the &lt;code&gt;date()&lt;/code&gt; method. Grails will use these date formats to parse the request parameter into a valid Date object.&lt;/p&gt;&lt;p&gt;Let's show the different options we have in a simple sample controller:&lt;/p&gt;&lt;pre class="brush:groovy"&gt;// File: grails-app/controllers/param/date/SampleController.groovy
package param.date

class SampleController {

    final def dateFormats = ['yyyy-MM-dd', 'yyyyMMdd']

    def index() {
        [
                defaultFormatDate: defaultFormatDate,
                defaultFormatNameDate: defaultFormatNameDate,
                singleFormatDate: singleFormatDate,
                multipleFormatsDate1: multipleFormatsDate1,
                multipleFormatsDate2: multipleFormatsDate2
        ]
    }

    private Date getDefaultFormatDate() {
        // Use default format yyyy-MM-dd HH:mm:ss.S
        params.date 'defaultFormatDate'
    }

    private Date getDefaultFormatNameDate() {
        // Lookup format with key date.defaultFormatNameDate.format
        // in messages.properties: yyyy-MM-dd
        params.date 'defaultFormatNameDate'
    }

    private Date getSingleFormatDate() {
        params.date 'singleFormatDate', 'yyyyMMdd'
    }

    private Date getMultipleFormatsDate1() {
        params.date 'multipleFormatsDate1', dateFormats
    }

    private Date getMultipleFormatsDate2() {
        params.date 'multipleFormatsDate2', dateFormats
    }

}
&lt;/pre&gt;&lt;p&gt;In &lt;code&gt;messages.properties&lt;/code&gt; we define the format for the request parameter &lt;em&gt;defaultFormatNameDate&lt;/em&gt;:&lt;/p&gt;&lt;pre class="brush:plain"&gt;# File: grails-app/i18n/messages.properties
...
date.defaultFormatNameDate.format=yyyy-MM-dd
...
&lt;/pre&gt;&lt;p&gt;To show that the date parsing works we write a little integration test. We need this to be an integration test, because then the lookup of the key via the MessageSource bean works.&lt;/p&gt;&lt;pre class="brush:groovy"&gt;package param.date

import org.junit.Test

class SampleControllerTests extends GroovyTestCase {

    @Test
    void testDateParameters() {
        def controller = new SampleController()

        // Set request parameters.
        def params = [
                defaultFormatDate: inputDateTime.format('yyyy-MM-dd HH:mm:ss.S'),
                defaultFormatNameDate: inputDateTime.format('yyyy-MM-dd'),
                singleFormatDate: inputDateTime.format('yyyyMMdd'),
                multipleFormatsDate1: inputDateTime.format('yyyy-MM-dd'),
                multipleFormatsDate2: inputDateTime.format('yyyyMMdd')
        ]
        controller.request.parameters = params

        def model = controller.index()

        assertDates inputDateTime, model.defaultFormatDate
        assertDates inputDate, model.defaultFormatNameDate
        assertDates inputDate, model.singleFormatDate
        assertDates inputDate, model.multipleFormatsDate1
        assertDates inputDate, model.multipleFormatsDate2
    }

    private void assertDates(final Date expected, final Date controllerDate) {
        assertEquals expected.toGMTString(), controllerDate.toGMTString()
    }

    /**
     * Create Date object for January 10, 2012 14:12:01.120
     */
    private Date getInputDateTime() {
        final Calendar cal = Calendar.instance
        cal.updated(year: 2012, month: Calendar.JANUARY, date: 10, 
                    hours: 14, minutes: 12, seconds: 1, milliSeconds: 120)
        cal.time
    }

    private Date getInputDate() {
        final Date inputDateTime = inputDateTime
        inputDateTime.clearTime()
        inputDateTime
    }
}
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6671019398434141469-6815100081296441916?l=mrhaki.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/mrhaki/~4/0AlakpCmwCs" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://mrhaki.blogspot.com/feeds/6815100081296441916/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://mrhaki.blogspot.com/2012/01/grails-goodness-date-request-parameter.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6671019398434141469/posts/default/6815100081296441916?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6671019398434141469/posts/default/6815100081296441916?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/mrhaki/~3/0AlakpCmwCs/grails-goodness-date-request-parameter.html" title="Grails Goodness: Date Request Parameter Value Conversions" /><author><name>Hubert Klein Ikkink</name><uri>https://profiles.google.com/116304108087638220732</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-VhI52jWYsR8/AAAAAAAAAAI/AAAAAAAAE_E/g4F9a-hMya8/s512-c/photo.jpg" /></author><thr:total>1</thr:total><feedburner:origLink>http://mrhaki.blogspot.com/2012/01/grails-goodness-date-request-parameter.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEcFSX4yfyp7ImA9WhRWFEQ.&quot;"><id>tag:blogger.com,1999:blog-6671019398434141469.post-5399955723912177572</id><published>2012-01-02T05:53:00.000+01:00</published><updated>2012-01-02T10:20:18.097+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-02T10:20:18.097+01:00</app:edited><title>Happy New Year and a Groovy 2012</title><content type="html">&lt;p&gt;I wish everyone a happy, healthy and Groovy 2012!&lt;/p&gt;&lt;p&gt;Today is my first working day at my new employer &lt;a href="http://www.jdriven.com"&gt;JDriven&lt;/a&gt;. Here I will work on Grails and Spring related projects together with 10 very enthusiastic, eager-to-learn, skilled and friendly colleagues. At JDriven we focus on SpringSource technologies and for me Groovy and Grails are (of course) very important. I am eager to start and really looking forward to a great year filled with fun at work by doing great projects with great technologies.&lt;/p&gt;&lt;p&gt;Oh, the perceptive reader might have seen the color change in the &lt;em&gt;haki&lt;/em&gt; logo. Instead of black and white colors of the &lt;a href="http://www.jdriven.com"&gt;JDriven&lt;/a&gt; colors are used to celebrate my new job.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6671019398434141469-5399955723912177572?l=mrhaki.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/mrhaki/~4/wTqVxlRXZgU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://mrhaki.blogspot.com/feeds/5399955723912177572/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://mrhaki.blogspot.com/2012/01/happy-new-year-and-groovy-2012.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6671019398434141469/posts/default/5399955723912177572?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6671019398434141469/posts/default/5399955723912177572?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/mrhaki/~3/wTqVxlRXZgU/happy-new-year-and-groovy-2012.html" title="Happy New Year and a Groovy 2012" /><author><name>Hubert Klein Ikkink</name><uri>https://profiles.google.com/116304108087638220732</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-VhI52jWYsR8/AAAAAAAAAAI/AAAAAAAAE_E/g4F9a-hMya8/s512-c/photo.jpg" /></author><thr:total>2</thr:total><feedburner:origLink>http://mrhaki.blogspot.com/2012/01/happy-new-year-and-groovy-2012.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUcFQHoyfip7ImA9WhRXGUs.&quot;"><id>tag:blogger.com,1999:blog-6671019398434141469.post-2815445444363741416</id><published>2011-12-27T06:16:00.000+01:00</published><updated>2011-12-27T06:16:51.496+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-27T06:16:51.496+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Grails:Goodness" /><category scheme="http://www.blogger.com/atom/ns#" term="Grails 2.0" /><category scheme="http://www.blogger.com/atom/ns#" term="Groovy" /><category scheme="http://www.blogger.com/atom/ns#" term="Grails" /><title>Grails Goodness: Customize the URL Format</title><content type="html">&lt;p&gt;Starting from Grails 2.0 we can change the URL format in our application. Default a camel case convention is used for the URLs. For example a controller &lt;em&gt;SampleAppController&lt;/em&gt; with an action &lt;em&gt;showSamplePage&lt;/em&gt; results in the following URL &lt;em&gt;/sampleApp/showSamplePage&lt;/em&gt;.&lt;/p&gt;&lt;p&gt;We can change this convention by creating a new class that implements the &lt;code&gt;grails.web.UrlConverter&lt;/code&gt; interface. Grails already provides the custom UrlConverter &lt;code&gt;grails.web.HyphenatedUrlConverter&lt;/code&gt;. This converter will add hyphens to the URL where there are uppercase characters and the uppercase character is converted to lowercase. Our sample controller and action result in the following URL with the &lt;code&gt;HyphenatedUrlConverter&lt;/code&gt;: &lt;em&gt;/sample-app/show-sample-page&lt;/em&gt;.&lt;/p&gt;&lt;p&gt;Because Grails already provides this UrlConverter it is very easy to configure. We only need to change our configuration in &lt;em&gt;grails-app/conf/Config.groovy&lt;/em&gt;. We add the key &lt;em&gt;grails.web.url.converter&lt;/em&gt; with the value &lt;em&gt;hyphenated&lt;/em&gt;:&lt;/p&gt;&lt;pre class="brush:groovy"&gt;// File: grails-app/conf/Config.groovy
...
grails.web.url.converter = 'hyphenated'
...
&lt;/pre&gt;&lt;p&gt;But we can implement our own class with the &lt;code&gt;grails.web.UrlConverter&lt;/code&gt; interface to define our own URL format to be used in the Grails application. The interface only has one method &lt;em&gt;String toUrlElement(String)&lt;/em&gt; we need to implement. The input argument is the name of the controller or action that needs to be converted. We cannot see if the value is a controller or action value, the conversion rules will be applied to both controller and action values. The following class is a sample implementation. The controller or action name is first converted to lowercase. Next we add the extension &lt;em&gt;-grails&lt;/em&gt; to the controller or action. We make sure the conversion is not already done by checking if the extension is not already in place. This check is necessary because Grails will invoke our UrlConverter several times to map it to the correct controller and action names. And without the check the extension would be added again and again and again, resulting in a 404 page not found error.&lt;/p&gt;&lt;pre class="brush:groovy"&gt;// File: src/groovy/customize/url/format/CustomUrlConverter.groovy
package customize.url.format

import grails.web.UrlConverter
import org.apache.commons.lang.StringUtils

class CustomUrlConverter implements UrlConverter {
    private static final String GRAILS_EXTENSION = '-grails'

    String toUrlElement(String propertyOrClassName) {
        if (StringUtils.isBlank(propertyOrClassName)) {
            propertyOrClassName
        } else {
            String lowerPropertyOrClassName = propertyOrClassName.toLowerCase()
            String extendedPropertyOrClassName = addGrailsExtension(lowerPropertyOrClassName)
            extendedPropertyOrClassName
        }
    }

    private String addGrailsExtension(String propertyOrClassName) {
        if (propertyOrClassName.endsWith(GRAILS_EXTENSION)) {
            propertyOrClassName
        } else {
            propertyOrClassName + GRAILS_EXTENSION
        }
    }
}
&lt;/pre&gt;&lt;p&gt;We have our custom UrlConverter. Now we need to configure our Grails application to use it. This time we don't change the configuration &lt;em&gt;grails-app/conf/Config.groovy&lt;/em&gt;, but we add our custom implementation to the Spring configuration in &lt;em&gt;grails-app/conf/spring/resources.groovy&lt;/em&gt;. If we use the name with the value of the constant &lt;code&gt;grails.web.UrlConverter.BEAN_NAME&lt;/code&gt; for our implementation then Grails will use our custom UrlConverter. We can remove any &lt;em&gt;grails.web.url.converter&lt;/em&gt; from &lt;em&gt;Config.groovy&lt;/em&gt;, because it will not be used.&lt;/p&gt;&lt;pre class="brush:groovy"&gt;// File: grails-app/conf/spring/resources.groovy
import static grails.web.UrlConverter.BEAN_NAME as UrlConverterBean

beans = {
...
    "${UrlConverterBean}"(customize.url.format.CustomUrlConverter)
...
}
&lt;/pre&gt;&lt;p&gt;We are done. If we start our application then we use the URL &lt;em&gt;/sampleapp-grails/showsamplepage-grails&lt;/em&gt; to access the controller &lt;em&gt;SampleAppController&lt;/em&gt; and the method &lt;em&gt;showSamplePage()&lt;/em&gt; in the controller.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6671019398434141469-2815445444363741416?l=mrhaki.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/mrhaki/~4/Ch5RC0mOBuo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://mrhaki.blogspot.com/feeds/2815445444363741416/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://mrhaki.blogspot.com/2011/12/grails-goodness-customize-url-format.html#comment-form" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6671019398434141469/posts/default/2815445444363741416?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6671019398434141469/posts/default/2815445444363741416?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/mrhaki/~3/Ch5RC0mOBuo/grails-goodness-customize-url-format.html" title="Grails Goodness: Customize the URL Format" /><author><name>Hubert Klein Ikkink</name><uri>https://profiles.google.com/116304108087638220732</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-VhI52jWYsR8/AAAAAAAAAAI/AAAAAAAAE_E/g4F9a-hMya8/s512-c/photo.jpg" /></author><thr:total>3</thr:total><feedburner:origLink>http://mrhaki.blogspot.com/2011/12/grails-goodness-customize-url-format.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUcBRHk8cSp7ImA9WhRXGUs.&quot;"><id>tag:blogger.com,1999:blog-6671019398434141469.post-2750281590632617034</id><published>2011-12-16T06:43:00.000+01:00</published><updated>2011-12-27T06:17:35.779+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-27T06:17:35.779+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Alfresco Web Quick Start" /><category scheme="http://www.blogger.com/atom/ns#" term="Alfresco" /><title>Alfresco 4 and Web Quick Start Page Not Found Errors</title><content type="html">&lt;p&gt;After installing Alfresco 4.0.b with the Web Quick Start module and setting up the demo site following the instructions I got "Page not found" errors. With the Alfresco 3.x release I never experienced these problems. It turns out to be a problem with the new Solr search engine that is used. The workaround for now is to revert back to the Lucene search mechanism. The Alfresco forum has &lt;a href="https://forums.alfresco.com/en/viewtopic.php?f=52&amp;t=41597"&gt;a topic with a description of the workaround&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;We need to change the file &lt;code&gt;$ALFRESCO_HOME/tomcat/shared/classes/alfresco-global.properties&lt;/code&gt;. The key &lt;em&gt;index.subsystem.name&lt;/em&gt; needs to be changed to &lt;em&gt;lucene&lt;/em&gt; instead of &lt;em&gt;solr&lt;/em&gt;. Also we must add an extra key &lt;em&gt;index.recovery.mode&lt;/em&gt; with the value &lt;em&gt;FULL&lt;/em&gt;. After the changes we must restart Alfresco and then the Web Quick Start demo site works as expected.&lt;/p&gt;&lt;pre class="brush:plain"&gt;# File: $ALFRESCO_HOME/tomcat/shared/classes/alfresco-global.properties
...
### Solr indexing ###
#index.subsystem.name=solr
index.subsystem.name=lucene
index.recovery.mode=FULL
...
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6671019398434141469-2750281590632617034?l=mrhaki.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/mrhaki/~4/gZOJPXuGqhU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://mrhaki.blogspot.com/feeds/2750281590632617034/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://mrhaki.blogspot.com/2011/12/alfresco-4-and-web-quick-start-page-not.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6671019398434141469/posts/default/2750281590632617034?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6671019398434141469/posts/default/2750281590632617034?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/mrhaki/~3/gZOJPXuGqhU/alfresco-4-and-web-quick-start-page-not.html" title="Alfresco 4 and Web Quick Start Page Not Found Errors" /><author><name>Hubert Klein Ikkink</name><uri>https://profiles.google.com/116304108087638220732</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-VhI52jWYsR8/AAAAAAAAAAI/AAAAAAAAE_E/g4F9a-hMya8/s512-c/photo.jpg" /></author><thr:total>1</thr:total><feedburner:origLink>http://mrhaki.blogspot.com/2011/12/alfresco-4-and-web-quick-start-page-not.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0AMQHs7fyp7ImA9WhRQFk4.&quot;"><id>tag:blogger.com,1999:blog-6671019398434141469.post-6238451690440646567</id><published>2011-12-11T22:41:00.001+01:00</published><updated>2011-12-11T22:43:01.507+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-11T22:43:01.507+01:00</app:edited><title>Some Groovy Love :-)</title><content type="html">&lt;p&gt;Our 2 year old son plays with his Lego Duplo Cars set and already experiences some &lt;em&gt;Groovy&lt;/em&gt; love. ;-)&lt;/p&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-K0eAbNjR-zU/TuUjz8VamtI/AAAAAAAAFHo/YeQD444Zy-4/s1600/IMAG0149.jpg" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="192" width="320" src="http://1.bp.blogspot.com/-K0eAbNjR-zU/TuUjz8VamtI/AAAAAAAAFHo/YeQD444Zy-4/s320/IMAG0149.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6671019398434141469-6238451690440646567?l=mrhaki.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/mrhaki/~4/lhANQHsvqpw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://mrhaki.blogspot.com/feeds/6238451690440646567/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://mrhaki.blogspot.com/2011/12/some-groovy-love.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6671019398434141469/posts/default/6238451690440646567?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6671019398434141469/posts/default/6238451690440646567?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/mrhaki/~3/lhANQHsvqpw/some-groovy-love.html" title="Some Groovy Love :-)" /><author><name>Hubert Klein Ikkink</name><uri>https://profiles.google.com/116304108087638220732</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-VhI52jWYsR8/AAAAAAAAAAI/AAAAAAAAE_E/g4F9a-hMya8/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-K0eAbNjR-zU/TuUjz8VamtI/AAAAAAAAFHo/YeQD444Zy-4/s72-c/IMAG0149.jpg" height="72" width="72" /><thr:total>1</thr:total><feedburner:origLink>http://mrhaki.blogspot.com/2011/12/some-groovy-love.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUMCQXw_fip7ImA9WhRRFEg.&quot;"><id>tag:blogger.com,1999:blog-6671019398434141469.post-282030123676338291</id><published>2011-11-28T05:11:00.000+01:00</published><updated>2011-11-28T05:11:00.246+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-28T05:11:00.246+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Grails:Goodness" /><category scheme="http://www.blogger.com/atom/ns#" term="GrailsGoodness:GSP" /><category scheme="http://www.blogger.com/atom/ns#" term="Groovy" /><category scheme="http://www.blogger.com/atom/ns#" term="Grails" /><title>Grails Goodness: Get GrailsApplication and ApplicationContext in GSP</title><content type="html">&lt;p&gt;Several variables are injected to Groovy Server Pages (GSP) in a Grails application. Two of them are the &lt;code&gt;ApplicationContext&lt;/code&gt; and &lt;code&gt;GrailsApplication&lt;/code&gt; objects. They are bound to the variables &lt;em&gt;applicationContext&lt;/em&gt; and &lt;em&gt;grailsApplication&lt;/em&gt;.&lt;/p&gt;&lt;p&gt;When we have access to the &lt;code&gt;ApplicationContext&lt;/code&gt; we could for example load resources or get references to beans in the context. Via the &lt;em&gt;grailsApplication&lt;/em&gt; variable we have access to for example the configuration values and metadata of the application.&lt;/p&gt;&lt;pre class="brush:html"&gt;&amp;lt;%-- File: grails-app/views/view/index.gsp --%&amp;gt;
&amp;lt;html&amp;gt;
    &amp;lt;head&amp;gt;
        &amp;lt;title&amp;gt;GSP Sample&amp;lt;/title&amp;gt;
    &amp;lt;/head&amp;gt;
    &amp;lt;body&amp;gt;
        &amp;lt;h1&amp;gt;ApplicationContext&amp;lt;/h1&amp;gt;

        &amp;lt;dl&amp;gt;
            &amp;lt;dt&amp;gt;applicationContext&amp;lt;/dt&amp;gt;
            &amp;lt;dd&amp;gt;${applicationContext}&amp;lt;/dd&amp;gt;
            &amp;lt;dt&amp;gt;# beans&amp;lt;/dt&amp;gt;
            &amp;lt;dd&amp;gt;${applicationContext.beanDefinitionCount}&amp;lt;/dd&amp;gt;
            &amp;lt;dt&amp;gt;beans&amp;lt;/dt&amp;gt;
            &amp;lt;dd&amp;gt;${applicationContext.beanDefinitionNames.join(', ')}&amp;lt;/dd&amp;gt;
        &amp;lt;/dl&amp;gt;

        &amp;lt;h1&amp;gt;GrailsApplication&amp;lt;/h1&amp;gt;

        &amp;lt;dl&amp;gt;
            &amp;lt;dt&amp;gt;grailsApplication&amp;lt;/dt&amp;gt;
            &amp;lt;dd&amp;gt;${grailsApplication}&amp;lt;/dd&amp;gt;
            &amp;lt;dt&amp;gt;configuration&amp;lt;/dt&amp;gt;
            &amp;lt;dd&amp;gt;${grailsApplication.config}&amp;lt;/dd&amp;gt;
            &amp;lt;dt&amp;gt;metadata&amp;lt;/dt&amp;gt;
            &amp;lt;dd&amp;gt;${grailsApplication.metadata}&amp;lt;/dd&amp;gt;
        &amp;lt;/dl&amp;gt;
    &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/pre&gt;&lt;p&gt;When we open this GSP in our browser we get the following output:&lt;/p&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-z_dQfpy7f9M/Ts9PrDBV6wI/AAAAAAAAFDE/_atThVFgKv8/s1600/http___localhost_8080_gspvars_view_index.jpg" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="249" width="320" src="http://3.bp.blogspot.com/-z_dQfpy7f9M/Ts9PrDBV6wI/AAAAAAAAFDE/_atThVFgKv8/s320/http___localhost_8080_gspvars_view_index.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6671019398434141469-282030123676338291?l=mrhaki.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/mrhaki/~4/YNPJSLOjwSo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://mrhaki.blogspot.com/feeds/282030123676338291/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://mrhaki.blogspot.com/2011/11/grails-goodness-get-grailsapplication.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6671019398434141469/posts/default/282030123676338291?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6671019398434141469/posts/default/282030123676338291?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/mrhaki/~3/YNPJSLOjwSo/grails-goodness-get-grailsapplication.html" title="Grails Goodness: Get GrailsApplication and ApplicationContext in GSP" /><author><name>Hubert Klein Ikkink</name><uri>https://profiles.google.com/116304108087638220732</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-VhI52jWYsR8/AAAAAAAAAAI/AAAAAAAAE_E/g4F9a-hMya8/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-z_dQfpy7f9M/Ts9PrDBV6wI/AAAAAAAAFDE/_atThVFgKv8/s72-c/http___localhost_8080_gspvars_view_index.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://mrhaki.blogspot.com/2011/11/grails-goodness-get-grailsapplication.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUENQXc4fip7ImA9WhRREk0.&quot;"><id>tag:blogger.com,1999:blog-6671019398434141469.post-3066308644111502230</id><published>2011-11-25T08:46:00.001+01:00</published><updated>2011-11-25T08:54:50.936+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-25T08:54:50.936+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Grails:Goodness" /><category scheme="http://www.blogger.com/atom/ns#" term="GrailsGoodness:GSP" /><category scheme="http://www.blogger.com/atom/ns#" term="Groovy" /><category scheme="http://www.blogger.com/atom/ns#" term="Grails" /><title>Grails Goodness: Access Action and Controller Name in GSP</title><content type="html">&lt;p&gt;In our GSP views we can see the name of the action and controller that resulted in the view. We can use this for example to show or hide certain information based on the values for the action and controller name. Grails injects the variables &lt;em&gt;actionName&lt;/em&gt; and &lt;em&gt;controllerName&lt;/em&gt; automatically and sets the values based on the action and controller.&lt;/p&gt;&lt;pre class="brush:groovy"&gt;// File: grails-app/controller/com/mrhaki/sample/ViewController.groovy
package com.mrhaki.sample

class ViewController {

    def index = {}
}
&lt;/pre&gt;&lt;pre class="brush:groovy"&gt;&amp;lt;%-- File: grails-app/views/view/index.gsp --%&amp;gt;
&amp;lt;html&amp;gt;
    &amp;lt;head&amp;gt;
        &amp;lt;title&amp;gt;GSP Sample&amp;lt;/title&amp;gt;
    &amp;lt;/head&amp;gt;
    &amp;lt;body&amp;gt;
        &amp;lt;h1&amp;gt;Action and Controller Name&amp;lt;/h1&amp;gt;

        &amp;lt;ul&amp;gt;
            &amp;lt;li&amp;gt;controllerName: &amp;lt;strong&amp;gt;${controllerName}&amp;lt;/strong&amp;gt;&amp;lt;/li&amp;gt;
            &amp;lt;li&amp;gt;actionName: &amp;lt;strong&amp;gt;${actionName}&amp;lt;/strong&amp;gt;&amp;lt;/li&amp;gt;
        &amp;lt;/ul&amp;gt;
    &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/pre&gt;&lt;p&gt;When we open the GSP we get the following output:&lt;/p&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-7TJejO4-0v4/Ts9Jdk-H6oI/AAAAAAAAFC4/jcP03Xi7dyg/s1600/Screen%2Bshot%2B2011-11-25%2Bat%2B8.52.54%2B.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="90" width="320" src="http://3.bp.blogspot.com/-7TJejO4-0v4/Ts9Jdk-H6oI/AAAAAAAAFC4/jcP03Xi7dyg/s320/Screen%2Bshot%2B2011-11-25%2Bat%2B8.52.54%2B.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6671019398434141469-3066308644111502230?l=mrhaki.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/mrhaki/~4/f8uTuqsw-C0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://mrhaki.blogspot.com/feeds/3066308644111502230/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://mrhaki.blogspot.com/2011/11/grails-goodness-access-action-and.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6671019398434141469/posts/default/3066308644111502230?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6671019398434141469/posts/default/3066308644111502230?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/mrhaki/~3/f8uTuqsw-C0/grails-goodness-access-action-and.html" title="Grails Goodness: Access Action and Controller Name in GSP" /><author><name>Hubert Klein Ikkink</name><uri>https://profiles.google.com/116304108087638220732</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-VhI52jWYsR8/AAAAAAAAAAI/AAAAAAAAE_E/g4F9a-hMya8/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-7TJejO4-0v4/Ts9Jdk-H6oI/AAAAAAAAFC4/jcP03Xi7dyg/s72-c/Screen%2Bshot%2B2011-11-25%2Bat%2B8.52.54%2B.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://mrhaki.blogspot.com/2011/11/grails-goodness-access-action-and.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0IGQ306cCp7ImA9WhRREEs.&quot;"><id>tag:blogger.com,1999:blog-6671019398434141469.post-3015896962304226827</id><published>2011-11-23T15:57:00.001+01:00</published><updated>2011-11-23T16:18:42.318+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-23T16:18:42.318+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Groovy" /><category scheme="http://www.blogger.com/atom/ns#" term="GroovyGoodness:DSL" /><category scheme="http://www.blogger.com/atom/ns#" term="Groovy:Goodness" /><category scheme="http://www.blogger.com/atom/ns#" term="GroovyGoodness:Advanced" /><title>Groovy Goodness: Magic Package to Add Custom MetaClass</title><content type="html">&lt;p&gt;Groovy is very dynamic. We can add methods to classes at runtime that don't exist at compile time. We can add our own custom &lt;code&gt;MetaClass&lt;/code&gt; at startup time of our application if we follow the &lt;em&gt;magic&lt;/em&gt; package naming convention. The naming convention is &lt;code&gt;groovy.runtime.metaclass.[package].[class]MetaClass&lt;/code&gt;. For example if we want to change the behavior of the &lt;code&gt;java.lang.String&lt;/code&gt; class, then we must write a custom &lt;code&gt;MetaClass&lt;/code&gt; with the package name &lt;code&gt;groovy.runtime.metaclass.java.lang&lt;/code&gt; and class name &lt;code&gt;StringMetaClass&lt;/code&gt;. We can do the same for classes we create ourselves. For example if we have a class &lt;code&gt;myapp.RunApp&lt;/code&gt; than the custom metaclass implementation &lt;code&gt;RunAppMetaClass&lt;/code&gt; would be in package &lt;code&gt;groovy.runtime.metaclass.myapp&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;Our custom &lt;code&gt;MetaClass&lt;/code&gt; is extended from &lt;code&gt;DelegatingMetaClass&lt;/code&gt; and besides the name of the class and the package we can write our code the way we want.&lt;/p&gt;&lt;p&gt;We must first compile the custom &lt;code&gt;MetaClass&lt;/code&gt; and then we must put it in the classpath of the application code that is going to use the &lt;code&gt;MetaClass&lt;/code&gt;.&lt;/p&gt;&lt;pre class="brush:groovy"&gt;// File: StringMetaClass.groovy
package groovy.runtime.metaclass.java.lang

class StringMetaClass extends DelegatingMetaClass {

    StringMetaClass(MetaClass meta) {
        super(meta)
    }

    Object invokeMethod(Object object, String method, Object[] arguments) {
        if (method == 'hasGroovy') {
            object ==~ /.*[Gg]roovy.*/
        } else {
            super.invokeMethod object, method, arguments
        }
    }
}
&lt;/pre&gt;&lt;p&gt;The code that will use the delegating metaclass implementation:&lt;/p&gt;&lt;pre class="brush:groovy"&gt;// File: StringDelegateSample.groovy

// Original methods are still invoked.
assert 'mrhaki'.toUpperCase() == 'MRHAKI'

// Invoke 'hasGroovy' method we added via the DelegatingMetaClass.
assert !'Java'.hasGroovy()
assert 'mrhaki loves Groovy'.hasGroovy()
assert 'Groovy'.toLowerCase().hasGroovy()
&lt;/pre&gt;&lt;p&gt;First we compile our &lt;code&gt;StringMetaClass&lt;/code&gt;:&lt;br /&gt;&lt;code&gt;$ groovyc StringMetaClass.groovy&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;Next we can run the &lt;code&gt;StringDelegateSample.groovy&lt;/code&gt; file if we put the generated class file in our classpath:&lt;br /&gt;&lt;code&gt;$ groovy -cp . StringDelegateSample&lt;/code&gt;&lt;/p&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6671019398434141469-3015896962304226827?l=mrhaki.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/mrhaki/~4/ZsvZLWPOirU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://mrhaki.blogspot.com/feeds/3015896962304226827/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://mrhaki.blogspot.com/2011/11/groovy-goodness-magic-package-to-add.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6671019398434141469/posts/default/3015896962304226827?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6671019398434141469/posts/default/3015896962304226827?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/mrhaki/~3/ZsvZLWPOirU/groovy-goodness-magic-package-to-add.html" title="Groovy Goodness: Magic Package to Add Custom MetaClass" /><author><name>Hubert Klein Ikkink</name><uri>https://profiles.google.com/116304108087638220732</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-VhI52jWYsR8/AAAAAAAAAAI/AAAAAAAAE_E/g4F9a-hMya8/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://mrhaki.blogspot.com/2011/11/groovy-goodness-magic-package-to-add.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Ck4DSXs6cCp7ImA9WhRSFUs.&quot;"><id>tag:blogger.com,1999:blog-6671019398434141469.post-1675936502562524531</id><published>2011-11-17T21:12:00.000+01:00</published><updated>2011-11-17T21:16:18.518+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-17T21:16:18.518+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Groovy" /><category scheme="http://www.blogger.com/atom/ns#" term="GroovyGoodness:DSL" /><category scheme="http://www.blogger.com/atom/ns#" term="Groovy:Goodness" /><title>Groovy Goodness: Create Simple Builders with Closures</title><content type="html">&lt;p&gt;In Groovy we can use pre-defined builders like the &lt;code&gt;JsonBuilder&lt;/code&gt; or &lt;code&gt;MarkupBuilder&lt;/code&gt; to create data or text structures. It is very easy to create our own builder simply with closures. A node in the builder is simply a method and we can use a closure as the argument of the method to create a new level in the builder hierarchy.&lt;/p&gt;&lt;p&gt;We can use pre-defined method names in our builder syntax, but can also use dynamic or unkown method names by implementing the &lt;code&gt;methodMissing&lt;/code&gt; method. The same goes for properties we can implement with real property methods or by implementing the &lt;code&gt;propertyMissing&lt;/code&gt; method.&lt;/p&gt;&lt;p&gt;In our example we create a new builder to create a &lt;code&gt;Reservation&lt;/code&gt; object for a travel flight. In the builder we can define a list of passengers, the destination airport, the departing airport and if the flight is a two-way flight.&lt;/p&gt;&lt;pre class="brush:groovy"&gt;// Builder syntax to create a reservation with passengers,
// departing and destination airport and make it a 2-way flight.
def reservation = new ReservationBuilder().make {
    passengers {
        name 'mrhaki'
        name 'Hubert A. Klein Ikkink'
    }
    from 'Schiphol, Amsterdam'
    to 'Kastrup, Copenhagen'
    retourFlight
}

assert reservation.flight.from == new Airport(name: 'Schiphol', city: 'Amsterdam')
assert reservation.flight.to == new Airport(name: 'Kastrup', city: 'Copenhagen')
assert reservation.passengers.size() == 2
assert reservation.passengers == [new Person(name: 'mrhaki'), new Person(name: 'Hubert A. Klein Ikkink')]
assert reservation.retourFlight


// ----------------------------------------------
// Builder implementation and supporting classes.
// ----------------------------------------------
import groovy.transform.*

@Canonical
class Reservation {
    Flight flight = new Flight()
    List&amp;lt;Person&amp;gt; passengers = []
    Boolean retourFlight = false
}

@Canonical
class Person { String name }

@Canonical
class Airport { String name, city }

@Canonical
class Flight { Airport from, to }

// The actual builder for reservations.
class ReservationBuilder {
    // Reservation to make and fill with property values.
    Reservation reservation

    private Boolean passengersMode = false

    Reservation make(Closure definition) {
        reservation = new Reservation()

        runClosure definition

        reservation
    }

    void passengers(Closure names) {
        passengersMode = true

        runClosure names

        passengersMode = false
    }

    void name(String personName) {
        if (passengersMode) {
            reservation.passengers &amp;lt;&amp;lt; new Person(name: personName)
        } else {
            throw new IllegalStateException("name() only allowed in passengers context.")
        }
    }

    def methodMissing(String name, arguments) {
        // to and from method calls will set flight properties
        // with Airport objects.
        if (name in ['to', 'from']) {
            def airport = arguments[0].split(',')
            def airPortname = airport[0].trim()
            def city = airport[1].trim()
            reservation.flight."$name" = new Airport(name: airPortname, city: city)
        }
    }

    def propertyMissing(String name) {
        // Property access of retourFlight sets reservation
        // property retourFlight to true.
        if (name == 'retourFlight') {
            reservation.retourFlight = true
        }
    }

    private runClosure(Closure runClosure) {
        // Create clone of closure for threading access.
        Closure runClone = runClosure.clone()

        // Set delegate of closure to this builder.
        runClone.delegate = this

        // And only use this builder as the closure delegate.
        runClone.resolveStrategy = Closure.DELEGATE_ONLY

        // Run closure code.
        runClone()
    }

}
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6671019398434141469-1675936502562524531?l=mrhaki.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/mrhaki/~4/XC7rNHGNsn0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://mrhaki.blogspot.com/feeds/1675936502562524531/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://mrhaki.blogspot.com/2011/11/groovy-goodness-create-simple-builders.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6671019398434141469/posts/default/1675936502562524531?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6671019398434141469/posts/default/1675936502562524531?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/mrhaki/~3/XC7rNHGNsn0/groovy-goodness-create-simple-builders.html" title="Groovy Goodness: Create Simple Builders with Closures" /><author><name>Hubert Klein Ikkink</name><uri>https://profiles.google.com/116304108087638220732</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-VhI52jWYsR8/AAAAAAAAAAI/AAAAAAAAE_E/g4F9a-hMya8/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://mrhaki.blogspot.com/2011/11/groovy-goodness-create-simple-builders.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0cERng-cSp7ImA9WhRSFUw.&quot;"><id>tag:blogger.com,1999:blog-6671019398434141469.post-3431719069145255074</id><published>2011-11-17T07:19:00.001+01:00</published><updated>2011-11-17T07:23:27.659+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-17T07:23:27.659+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Groovy" /><category scheme="http://www.blogger.com/atom/ns#" term="GroovyGoodness:DSL" /><category scheme="http://www.blogger.com/atom/ns#" term="Groovy:Goodness" /><title>Groovy Goodness: Create Our Own Script Class</title><content type="html">&lt;p&gt;Groovy is a great language to write DSL implementations. The Groovy syntax allows for example to leave out parenthesis or semi colons, which results in better readable DSL (which is actually Groovy code).&lt;/p&gt;&lt;p&gt;To run a DSL script we can use the GroovyShell class and evaluate the script. By default the script is evaluated with an instance of &lt;code&gt;groovy.lang.Script&lt;/code&gt; class. But we can extends this &lt;code&gt;Script&lt;/code&gt; class and write our DSL allowed methods, which can then be used by the DSL script. We pass our own &lt;code&gt;Script&lt;/code&gt; class to the &lt;code&gt;GroovyShell&lt;/code&gt; with an &lt;code&gt;CompilerConfiguration&lt;/code&gt; object. The &lt;code&gt;CompilerConfiguration&lt;/code&gt; allows us to set a new base script class to be used.&lt;/p&gt;&lt;p&gt;The following sample is a simple DSL to change the state of a &lt;code&gt;Car&lt;/code&gt; object. Notice we implicitly access the &lt;code&gt;Car&lt;/code&gt; object that is passed to the &lt;code&gt;GroovyShell&lt;/code&gt; via a binding. The custom &lt;code&gt;CarScript&lt;/code&gt; class can access the car object via the binding and change it's state.&lt;/p&gt;&lt;pre class="brush:groovy"&gt;import org.codehaus.groovy.control.CompilerConfiguration

// Simple Car class to save state and distance.
class Car {
    String state
    Long distance = 0
}

// Custom Script with methods that change the Car's state.
// The Car object is passed via the binding.
abstract class CarScript extends Script {
    def start() {
        this.binding.car.state = 'started'
    }

    def stop() {
        this.binding.car.state = 'stopped'
    }

    def drive(distance) {
        this.binding.car.distance += distance
    }
}


// Use custom CarScript.
def compilerConfiguration = new CompilerConfiguration()
compilerConfiguration.scriptBaseClass = CarScript.class.name

// Define Car object here, so we can use it in assertions later on.
def car = new Car()
// Add to script binding (CarScript references this.binding.car).
def binding = new Binding(car: car)

// Configure the GroovyShell.
def shell = new GroovyShell(this.class.classLoader, binding, compilerConfiguration)

// Simple DSL to start, drive and stop the car.
// The methods are defined in the CarScript class.
def carDsl = '''
start()
drive 20
stop()
'''

// Run DSL script.
shell.evaluate carDsl

// Checks to see that Car object has changed.
assert car.distance == 20
assert car.state == 'stopped'
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6671019398434141469-3431719069145255074?l=mrhaki.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/mrhaki/~4/C18qxcGQ02M" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://mrhaki.blogspot.com/feeds/3431719069145255074/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://mrhaki.blogspot.com/2011/11/groovy-goodness-create-our-own-script.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6671019398434141469/posts/default/3431719069145255074?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6671019398434141469/posts/default/3431719069145255074?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/mrhaki/~3/C18qxcGQ02M/groovy-goodness-create-our-own-script.html" title="Groovy Goodness: Create Our Own Script Class" /><author><name>Hubert Klein Ikkink</name><uri>https://profiles.google.com/116304108087638220732</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-VhI52jWYsR8/AAAAAAAAAAI/AAAAAAAAE_E/g4F9a-hMya8/s512-c/photo.jpg" /></author><thr:total>2</thr:total><feedburner:origLink>http://mrhaki.blogspot.com/2011/11/groovy-goodness-create-our-own-script.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0YNRHwyfip7ImA9WhRSEkg.&quot;"><id>tag:blogger.com,1999:blog-6671019398434141469.post-1862410291443489251</id><published>2011-11-14T08:13:00.001+01:00</published><updated>2011-11-14T08:19:55.296+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-14T08:19:55.296+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Grails:Goodness" /><category scheme="http://www.blogger.com/atom/ns#" term="Groovy" /><category scheme="http://www.blogger.com/atom/ns#" term="GrailsGoodness:Plugins" /><category scheme="http://www.blogger.com/atom/ns#" term="Grails" /><title>Grails Goodness: Internationalize Javascript Messages with JAWR Plugin</title><content type="html">&lt;p&gt;Grails has great builtin support for &lt;a href="http://grails.org/doc/latest/guide/10.%20Internationalization.html"&gt;internationalization (i18n)&lt;/a&gt;. The underlying Spring support for i18n is used. We can easily change for example text on views based on the user's locale. But this only applies for the server side of our code. So we can generate the correct messages and labels based on the user's locale on the server, but not in our Javascript code. What if we want to display a localized message in a bit of Javascript code, that is not created on the server? Why do I add this extra information 'not created on the server'? Because we can still generate Javascript code in a view or use the gsp-resources plugin to create Javascript on the server. This code can contain the output of a localized message and can be used in Javascript. But that is not what we want for this blog post. Here we are going to reference our i18n messages from plain, non-generated Javascript code.&lt;/p&gt;&lt;p&gt;We can achieve this with the &lt;a href="http://grails.org/plugin/jawr"&gt;JAWR plugin&lt;/a&gt;. The plugin provides roughly the same functionality as the &lt;a href="http://grails.org/plugin/resources"&gt;resources plugin&lt;/a&gt; for bundling resources efficiently in a Grails application. We are not interested in that part, but the JAWR library used by the plugin also has a i18n messages generator. And we are going to use that in our Grails application to get localized Javascript messages.&lt;/p&gt;&lt;p&gt;First we must install the JAWR plugin: &lt;code&gt;$ grails install-plugin jawr&lt;/code&gt;. Next we can configure the plugin. We open our &lt;code&gt;grails-app/conf/Config.groovy&lt;/code&gt; file and add:&lt;/p&gt;&lt;pre class="brush:groovy"&gt;// File: grails-app/conf/Config.groovy
...

jawr {
    js {
        // Specific mapping to disable resource handling by plugin.
        mapping = '/jawr/'

        bundle {
            lib {
                // Bundle id is used in views.
                id = '/i18n/messages.js'

                // Tell which messages need to localized in Javascript.
                mappings = 'messages:grails-app.i18n.messages'
            }
        }
    }
    locale {
        // Define resolver so ?lang= Grails functionality works with controllers.
        resolver = 'net.jawr.web.resource.bundle.locale.SpringLocaleResolver'
    }
}

...
&lt;/pre&gt;&lt;p&gt;At line 6 we define a mapping. If we don't define a mapping the JAWR plugin will also act as a resource and bundling plugin, but for this example we only want to use the i18n messages generator.&lt;/p&gt;&lt;p&gt;Line 14 defines which resource in the classpath contains the messages that need to be accessible in Javascript. For our Grails application we want the messages from  &lt;code&gt;messages.properties&lt;/code&gt; (and the locale specific versions) so we define &lt;code&gt;grails-app.i18n.messages&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;With Grails it is easy to switch to a specific user locale by adding the request parameter &lt;em&gt;lang&lt;/em&gt; to a request. At line 20 we add a resolver that will use the Grails locale resolver to determine a user's locale.&lt;/p&gt;&lt;p&gt;It it time to see our Javascript in action. First we create two new message labels in &lt;code&gt;messages.properties&lt;/code&gt;. One without variables and one with a variable placeholder to show how the JAWR plugin supports this:&lt;/p&gt;&lt;pre class="brush:groovy"&gt;// File: grails-app/i18n/messages.properties
js.sample.hello.message=Hello
js.sample.hello.user.message=Hello {0}
&lt;/pre&gt;&lt;p&gt;Let's add a Dutch version of these messages in &lt;code&gt;grails-app/i18n/messages_nl.properties&lt;/code&gt;:&lt;/p&gt;&lt;pre class="brush:groovy"&gt;// File: grails-app/i18n/messages_nl.properties
js.sample.hello.message=Hallo
js.sample.hello.user.message=Hallo {0}
&lt;/pre&gt;&lt;p&gt;Now it is time to create a GSP view with a simple controller (only request through a controller will be able to use the locale resolver we defined in our configuration).&lt;/p&gt;&lt;pre class="brush:groovy"&gt;// File: grails-app/controller/grails/js/i18n/SampleController.groovy
package grails.js.i18n

class SampleController {
    def index = {
        // render 'sample/index.gsp'
    }
}
&lt;/pre&gt;&lt;pre class="brush:html"&gt;%{-- File: grails-app/views/sample/index.gsp --}%
&amp;lt;html&amp;gt;
    &amp;lt;head&amp;gt;
        &amp;lt;meta name="layout" content="main"/&amp;gt;
        &amp;lt;jawr:script src="/i18n/messages.js"/&amp;gt;
        &amp;lt;g:javascript library="application"/&amp;gt;
    &amp;lt;/head&amp;gt;
    &amp;lt;body&amp;gt;
        &amp;lt;h1&amp;gt;Simple message&amp;lt;/h1&amp;gt;

        &amp;lt;input type="button" onclick="showAlertHello();" value="Hello"/&amp;gt;

        &amp;lt;hr/&amp;gt;

        &amp;lt;h1&amp;gt;Message with variable placeholder&amp;lt;/h1&amp;gt;

        Username: &amp;lt;input type="text" id="username" size="30"/&amp;gt;

        &amp;lt;input type="button" onclick="showAlertUsername();" value="Hello"/&amp;gt;

    &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/pre&gt;&lt;p&gt;At line 4 we inlude the Javascript i18n messages generated by the JAWR plugin. And at line 5 we include an external Javascript file that will use the generated messages:&lt;/p&gt;&lt;pre class="brush:javascript"&gt;// File: web-app/js/application.js

function showAlertHello() {
    var alertMessage = messages.js.sample.hello.message();
    alert(alertMessage);
}

function showAlertUsername() {
    var usernameValue = document.getElementById("username").value;
    var alertMessage = messages.js.sample.hello.username.message(usernameValue);
    alert(alertMessage);
}
&lt;/pre&gt;&lt;p&gt;Notice how we can access the i18n messages in Javascript. The plugin will convert the messages to Javascript functions to return the message. And even variable substitution is supported (see line 9).&lt;/p&gt;&lt;p&gt;The following screenshots show the alert messages for the default locale and for a request with the Dutch locale:&lt;/p&gt;&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-elOkExcL0Kc/TsC_wTomUoI/AAAAAAAAE_w/DWNXGW-fcts/s1600/simple-js.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="199" width="320" src="http://2.bp.blogspot.com/-elOkExcL0Kc/TsC_wTomUoI/AAAAAAAAE_w/DWNXGW-fcts/s320/simple-js.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-f093wR0S1BI/TsC_wXT6cGI/AAAAAAAAE_4/fOKwnkxigy8/s1600/simple-js-nl.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="198" width="320" src="http://2.bp.blogspot.com/-f093wR0S1BI/TsC_wXT6cGI/AAAAAAAAE_4/fOKwnkxigy8/s320/simple-js-nl.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-Mp8t4sHh8cU/TsC_wnU7MxI/AAAAAAAAFAE/9_4xKeJPRJU/s1600/placeholder-js.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="198" width="320" src="http://4.bp.blogspot.com/-Mp8t4sHh8cU/TsC_wnU7MxI/AAAAAAAAFAE/9_4xKeJPRJU/s320/placeholder-js.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-n9DiPT4mVi4/TsC_wzpDplI/AAAAAAAAFAU/1cmLbF2iJgU/s1600/placeholder-js-nl.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="198" width="320" src="http://1.bp.blogspot.com/-n9DiPT4mVi4/TsC_wzpDplI/AAAAAAAAFAU/1cmLbF2iJgU/s320/placeholder-js-nl.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;p&gt;With the current configuration of the JAWR plugin all messages in the &lt;code&gt;messages.properties&lt;/code&gt; (and locale versions) will be exported to Javascript messages. But maybe this is too much and we only want to include a subset of the messages in the generated Javascript. In the configuration we can define a prefix for the messages to be exported or we can even define a separate properties file with only messages necessary for Javascript:&lt;/p&gt;&lt;pre class="brush:groovy"&gt;// File: grails-app/conf/Config.groovy
...
// Only filter messages starting with js.
jawr.js.bundle.lib.mappings=messages:grails-app.i18n.messages[js]
...
&lt;/pre&gt;&lt;pre class="brush:groovy"&gt;// File: grails-app/conf/Config.groovy
...
// Use a different properties file: jsmessages.properties (jsmessages_nl.properties, ...).
jawr.js.bundle.lib.mappings=messages:grails-app.i18n.jsmessages
...
&lt;/pre&gt;&lt;p&gt;In our Javascript we reference the messages by prefixing &lt;code&gt;messages.&lt;/code&gt; to the message properties. We can change this as well in our JAWR plugin configuration. If for example we want to use &lt;em&gt;i18n&lt;/em&gt; we must define our plugin as follows:&lt;/p&gt;&lt;pre class="brush:groovy"&gt;// File: grails-app/conf/Config.groovy
...
// Define custom namespace for reference in Javascript.
jawr.js.bundle.lib.mappings=messages:grails-app.i18n.messages(i18n)
...
&lt;/pre&gt;&lt;p&gt;With the use of the JAWR plugin and the i18n messages generator we can easily use localized messages in our Javascript code.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6671019398434141469-1862410291443489251?l=mrhaki.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/mrhaki/~4/9hD097JT_OI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://mrhaki.blogspot.com/feeds/1862410291443489251/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://mrhaki.blogspot.com/2011/11/grails-goodness-internationalize.html#comment-form" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6671019398434141469/posts/default/1862410291443489251?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6671019398434141469/posts/default/1862410291443489251?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/mrhaki/~3/9hD097JT_OI/grails-goodness-internationalize.html" title="Grails Goodness: Internationalize Javascript Messages with JAWR Plugin" /><author><name>Hubert Klein Ikkink</name><uri>https://profiles.google.com/116304108087638220732</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-VhI52jWYsR8/AAAAAAAAAAI/AAAAAAAAE_E/g4F9a-hMya8/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-elOkExcL0Kc/TsC_wTomUoI/AAAAAAAAE_w/DWNXGW-fcts/s72-c/simple-js.png" height="72" width="72" /><thr:total>3</thr:total><feedburner:origLink>http://mrhaki.blogspot.com/2011/11/grails-goodness-internationalize.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkIGQno9eCp7ImA9WhRTGU0.&quot;"><id>tag:blogger.com,1999:blog-6671019398434141469.post-1433362657153623706</id><published>2011-11-10T06:33:00.001+01:00</published><updated>2011-11-10T06:55:23.460+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-10T06:55:23.460+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Groovy 1.8.4" /><category scheme="http://www.blogger.com/atom/ns#" term="Groovy" /><category scheme="http://www.blogger.com/atom/ns#" term="GroovyGoodness:Date" /><category scheme="http://www.blogger.com/atom/ns#" term="GroovyGoodness:GDK" /><category scheme="http://www.blogger.com/atom/ns#" term="Groovy:Goodness" /><category scheme="http://www.blogger.com/atom/ns#" term="Groovy 1.8" /><title>Groovy Goodness: Parse Date.toString() Value</title><content type="html">&lt;p&gt;With Groovy 1.8.4 we can parse the output of the &lt;code&gt;Date.toString()&lt;/code&gt; method back to a Date. For example we get the string value of a Date from an external source and want to parse it to a Date object. The format of the string must have the pattern "EEE MMM dd HH:mm:ss zzz yyyy" with the US Locale. This is used by the &lt;code&gt;toString()&lt;/code&gt; method of the Date class.&lt;/p&gt;&lt;pre class="brush:groovy"&gt;import static java.util.Calendar.*

// Create date 10 November 2011.
def cal = Calendar.getInstance(TimeZone.getTimeZone('Europe/Amsterdam'))
def date = cal.time
date.clearTime()
date[YEAR] = 2011
date[MONTH] = NOVEMBER
date[DATE] = 10

// Get toString() value.
def dateToString = date.toString()
assert dateToString == 'Thu Nov 10 00:00:00 CET 2011'

// Replace Nov for Dec in string and 10 for 24.
dateString = dateToString.replace('Nov', 'Dec').replace('10', '24')

// Use parseToStringDate to get new Date.
def newDate = Date.parseToStringDate(dateString)
assert newDate[MONTH] == DECEMBER
assert newDate[DATE] == 24
assert newDate[YEAR] == 2011
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6671019398434141469-1433362657153623706?l=mrhaki.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/mrhaki/~4/zm9Ee4_XbRM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://mrhaki.blogspot.com/feeds/1433362657153623706/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://mrhaki.blogspot.com/2011/11/groovy-goodness-parse-datetostring.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6671019398434141469/posts/default/1433362657153623706?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6671019398434141469/posts/default/1433362657153623706?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/mrhaki/~3/zm9Ee4_XbRM/groovy-goodness-parse-datetostring.html" title="Groovy Goodness: Parse Date.toString() Value" /><author><name>Hubert Klein Ikkink</name><uri>https://profiles.google.com/116304108087638220732</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-VhI52jWYsR8/AAAAAAAAAAI/AAAAAAAAE_E/g4F9a-hMya8/s512-c/photo.jpg" /></author><thr:total>1</thr:total><feedburner:origLink>http://mrhaki.blogspot.com/2011/11/groovy-goodness-parse-datetostring.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0UERXk5cCp7ImA9WhRTFkk.&quot;"><id>tag:blogger.com,1999:blog-6671019398434141469.post-3218481991909078322</id><published>2011-11-07T06:53:00.000+01:00</published><updated>2011-11-07T06:53:24.728+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-07T06:53:24.728+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Groovy" /><category scheme="http://www.blogger.com/atom/ns#" term="GroovyGoodness:GDK" /><category scheme="http://www.blogger.com/atom/ns#" term="Groovy:Goodness" /><category scheme="http://www.blogger.com/atom/ns#" term="GroovyGoodness:Collections" /><title>Groovy Goodness: Find Non-Null Results After Transformation in a Collection</title><content type="html">&lt;p&gt;Since Groovy 1.8.1 we can use the &lt;code&gt;findResults&lt;/code&gt; method and pass a closure to transform elements in a collection and get all non-null elements after transformation. We also have the &lt;a href="http://mrhaki.blogspot.com/2010/12/groovy-goodness-find-first-non-null.html"&gt;&lt;code&gt;findResult&lt;/code&gt;&lt;/a&gt; method to return the first non-null transformed element, but with &lt;code&gt;findResults&lt;/code&gt; we get all non-null elements.&lt;/p&gt;&lt;pre class="brush:groovy"&gt;def stuff = ['Groovy', 'Griffon', 'Gradle', 'Spock', 'Grails', 'GContracts']
def stuffResult = stuff.findResults { it.size() == 6 ? "$it has 6 characters" : null }

assert stuffResult == ['Groovy has 6 characters', 
                       'Gradle has 6 characters',
                       'Grails has 6 characters']
                        
def map = [what: 'Finish blog post', priority: 1, when: new Date()]
def mapResult = map.findResults { it.value instanceof String ? "Key $it.key is of type String" : null }

assert mapResult == ['Key what is of type String']
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6671019398434141469-3218481991909078322?l=mrhaki.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/mrhaki/~4/gV41JJ-w9KU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://mrhaki.blogspot.com/feeds/3218481991909078322/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://mrhaki.blogspot.com/2011/11/groovy-goodness-find-non-null-results.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6671019398434141469/posts/default/3218481991909078322?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6671019398434141469/posts/default/3218481991909078322?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/mrhaki/~3/gV41JJ-w9KU/groovy-goodness-find-non-null-results.html" title="Groovy Goodness: Find Non-Null Results After Transformation in a Collection" /><author><name>Hubert Klein Ikkink</name><uri>https://profiles.google.com/116304108087638220732</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-VhI52jWYsR8/AAAAAAAAAAI/AAAAAAAAE_E/g4F9a-hMya8/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://mrhaki.blogspot.com/2011/11/groovy-goodness-find-non-null-results.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUcBSH0zeip7ImA9WhRTFEw.&quot;"><id>tag:blogger.com,1999:blog-6671019398434141469.post-5638770101901853129</id><published>2011-11-04T14:23:00.001+01:00</published><updated>2011-11-04T14:24:19.382+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-04T14:24:19.382+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Groovy" /><title>Source Code, PDF and Presentation about Groovy 1.8 from JFall 2011</title><content type="html">&lt;p&gt;For those that attended the Dutch Java User Group conference &lt;a href="http://www.nljug.org/pages/events/content/jfall_2011/"&gt;JFall 2011&lt;/a&gt; I have posted the slides (not that many, because of live coding ;-) ), the code from the session and an extensive PDF with content on &lt;a href="http://github.com/mrhaki/jfall2011"&gt;Github&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6671019398434141469-5638770101901853129?l=mrhaki.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/mrhaki/~4/YTZHRkSxpps" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://mrhaki.blogspot.com/feeds/5638770101901853129/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://mrhaki.blogspot.com/2011/11/source-code-pdf-and-presentation-about.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6671019398434141469/posts/default/5638770101901853129?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6671019398434141469/posts/default/5638770101901853129?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/mrhaki/~3/YTZHRkSxpps/source-code-pdf-and-presentation-about.html" title="Source Code, PDF and Presentation about Groovy 1.8 from JFall 2011" /><author><name>Hubert Klein Ikkink</name><uri>https://profiles.google.com/116304108087638220732</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-VhI52jWYsR8/AAAAAAAAAAI/AAAAAAAAE_E/g4F9a-hMya8/s512-c/photo.jpg" /></author><thr:total>1</thr:total><feedburner:origLink>http://mrhaki.blogspot.com/2011/11/source-code-pdf-and-presentation-about.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0cGQHk9eyp7ImA9WhRTEU4.&quot;"><id>tag:blogger.com,1999:blog-6671019398434141469.post-2724327376450465912</id><published>2011-11-01T10:04:00.000+01:00</published><updated>2011-11-01T10:17:01.763+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-01T10:17:01.763+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="JSON" /><category scheme="http://www.blogger.com/atom/ns#" term="Java" /><category scheme="http://www.blogger.com/atom/ns#" term="Groovy:Grassroots" /><category scheme="http://www.blogger.com/atom/ns#" term="Groovy" /><title>Grassroots Groovy: Reading JSON with JsonSlurper</title><content type="html">&lt;p&gt;We can introduce Groovy into our Java projects at grassroots level. In this post we see how we can use the &lt;code&gt;JsonSlurper&lt;/code&gt; class in our Java code to read JSON data. Once we have included the Groovy libraries in our project, for example by adding a dependency in a Maven POM file, we can use Groovy classes in our Java applications. And once we have Groovy in our project we might extend the use of Groovy further...&lt;/p&gt;&lt;p&gt;The &lt;code&gt;JsonSlurper&lt;/code&gt; class has a &lt;code&gt;parseText()&lt;/code&gt; and &lt;code&gt;parse()&lt;/code&gt; method to read in JSON data. We get back a &lt;code&gt;Map&lt;/code&gt; with values from the JSON structure. Let's see how we can use it in a simple Java application:&lt;/p&gt;&lt;pre class="brush:java"&gt;package com.mrhaki.sample;

import groovy.json.JsonSlurper;

import java.util.List;
import java.util.Map;

public class JsonParser {

    public static void main(String[] args) {
        String jsonText = "{\"user\":{\"name\":\"mrhaki\",\"age\":38,\"interests\":[\"Groovy\",\"Grails\"]}}";
        JsonSlurper jsonSlurper = new JsonSlurper();
        Object result = jsonSlurper.parseText(jsonText);

        Map jsonResult = (Map) result;
        Map user = (Map) jsonResult.get("user");
        String name = (String) user.get("name");
        Integer age = (Integer) user.get("age");
        List interests = (List) user.get("interests");

        assert name.equals("mrhaki");
        assert age == 38;
        assert interests.size() == 2;
        assert interests.get(0).equals("Groovy");
        assert interests.get(1).equals("Grails");
    }

}
&lt;/pre&gt;&lt;p&gt;Or use a URL with JSON content:&lt;/p&gt;&lt;pre class="brush:java"&gt;package com.mrhaki.sample;

import groovy.json.JsonSlurper;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import java.util.Map;

public class JsonUrlParser {

    private static final String JSON_URL = "http://www.mrhaki.com/samples/sample.json";

    public static void main(String[] args) throws IOException, MalformedURLException {
        URL url = new URL(JSON_URL);
        InputStream urlStream = null;
        try {
            urlStream = url.openStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(urlStream));
            JsonSlurper jsonSlurper = new JsonSlurper();
            Object result = jsonSlurper.parse(reader);

            Map jsonResult = (Map) result;
            Map user = (Map) jsonResult.get("user");
            String name = (String) user.get("name");
            Integer age = (Integer) user.get("age");
            List interests = (List) user.get("interests");

            assert name.equals("mrhaki");
            assert age == 38;
            assert interests.size() == 2;
            assert interests.get(0).equals("Groovy");
            assert interests.get(1).equals("Grails");

        } finally {
            if (urlStream != null) {
                urlStream.close();
            }
        }

    }
}
&lt;/pre&gt;&lt;p&gt;Once we have the Groovy libraries in our classpath we can run the Java application with &lt;code&gt;$ java -ea com.mrhaki.sample.JsonParser&lt;/code&gt; and the assertions should be okay.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6671019398434141469-2724327376450465912?l=mrhaki.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/mrhaki/~4/8XGd_5QUq-o" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://mrhaki.blogspot.com/feeds/2724327376450465912/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://mrhaki.blogspot.com/2011/11/grassroots-groovy-reading-json-with.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6671019398434141469/posts/default/2724327376450465912?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6671019398434141469/posts/default/2724327376450465912?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/mrhaki/~3/8XGd_5QUq-o/grassroots-groovy-reading-json-with.html" title="Grassroots Groovy: Reading JSON with JsonSlurper" /><author><name>Hubert Klein Ikkink</name><uri>https://profiles.google.com/116304108087638220732</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-VhI52jWYsR8/AAAAAAAAAAI/AAAAAAAAE_E/g4F9a-hMya8/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://mrhaki.blogspot.com/2011/11/grassroots-groovy-reading-json-with.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C04DSHw9cSp7ImA9WhdaFU8.&quot;"><id>tag:blogger.com,1999:blog-6671019398434141469.post-1724726527805196416</id><published>2011-10-25T07:52:00.000+02:00</published><updated>2011-10-25T07:52:59.269+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-25T07:52:59.269+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Grails:Goodness" /><category scheme="http://www.blogger.com/atom/ns#" term="Groovy" /><category scheme="http://www.blogger.com/atom/ns#" term="GrailsGoodness:Plugins" /><category scheme="http://www.blogger.com/atom/ns#" term="Grails" /><title>Grails Goodness: Use a Different jQuery UI Theme with Resources Plugin</title><content type="html">&lt;p&gt;The &lt;a href="http://grails-plugins.github.com/grails-resources/"&gt;resources plugin&lt;/a&gt; is a great way to manage resources in our Grails application. We define our resources like Javascript and CSS files with a simple DSL. The plugin will package the resources in the most efficient way for us in the final application.&lt;/p&gt;&lt;p&gt;The &lt;a href="http://www.jqueryui.com"&gt;jQuery UI&lt;/a&gt; library has support for theming. We can use the default theme(s), but we can also create our own custom theme with for example the &lt;a href="http://jqueryui.com/themeroller/"&gt;jQuery UI ThemeRoller&lt;/a&gt; site. &lt;/p&gt;&lt;p&gt;If we use the &lt;a href="http://www.grails.org/plugin/jquery-ui"&gt;jQuery UI plugin&lt;/a&gt; and want to use a different than the default theme we must change our configuration for the resources plugin. We override the theme that is set by default and point it to our new custom theme. We can change &lt;code&gt;grails-app/conf/Config.groovy&lt;/code&gt; or a separate resources artifact file. We add an &lt;em&gt;overrides&lt;/em&gt; section and use the same &lt;em&gt;id&lt;/em&gt; attribute value as set by the jQuery UI plugin. The &lt;em&gt;url&lt;/em&gt; attribute points to the location of the custom jQuery UI ThemeRoller CSS file.&lt;/p&gt;&lt;pre class="brush:groovy;highlight:[5,6,7,8,9,10]"&gt;// File: grails-app/conf/Config.groovy
grails.resources.modules = {
    core {
        dependsOn 'jquery-ui'
    }
    // Define reference to custom jQuery UI theme
    overrides {
        'jquery-theme' {
            resource id: 'theme', url: '/css/custom-theme/jquery-ui.custom.css'
        }
    }
}
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6671019398434141469-1724726527805196416?l=mrhaki.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/mrhaki/~4/Pw_DOEhi6xs" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://mrhaki.blogspot.com/feeds/1724726527805196416/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://mrhaki.blogspot.com/2011/10/grails-goodness-use-different-jquery-ui.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6671019398434141469/posts/default/1724726527805196416?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6671019398434141469/posts/default/1724726527805196416?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/mrhaki/~3/Pw_DOEhi6xs/grails-goodness-use-different-jquery-ui.html" title="Grails Goodness: Use a Different jQuery UI Theme with Resources Plugin" /><author><name>Hubert Klein Ikkink</name><uri>https://profiles.google.com/116304108087638220732</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-VhI52jWYsR8/AAAAAAAAAAI/AAAAAAAAE_E/g4F9a-hMya8/s512-c/photo.jpg" /></author><thr:total>1</thr:total><feedburner:origLink>http://mrhaki.blogspot.com/2011/10/grails-goodness-use-different-jquery-ui.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0UEQX8-eip7ImA9WhdaFEs.&quot;"><id>tag:blogger.com,1999:blog-6671019398434141469.post-7558831143304392904</id><published>2011-10-24T16:05:00.001+02:00</published><updated>2011-10-24T16:06:40.152+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-24T16:06:40.152+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Groovy" /><category scheme="http://www.blogger.com/atom/ns#" term="Groovy:Goodness" /><title>Groovy Goodness: Customize Groovy Console Visual Output</title><content type="html">&lt;p&gt;The Groovy Console (&lt;code&gt;$ groovyConsole&lt;/code&gt;)  is a great tool to run Groovy scripts and experiment with Groovy. Normally when we run a script the return result (if not null) is shown as a string value. We can customize the way the value is shown by creating a new file with the name &lt;code&gt;OutputTransforms.groovy&lt;/code&gt; in our &lt;code&gt;GROOVY_HOME&lt;/code&gt; directory. Normally this directory is located in your user directory with the name &lt;code&gt;.groovy&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;In &lt;code&gt;OutputTransforms.groovy&lt;/code&gt; we must fill the internal script variable &lt;code&gt;transforms&lt;/code&gt; of type &lt;code&gt;ArrayList&lt;/code&gt; with a closure where we do the actual customization of the return result. The closure has one parameter which is the return result of the script. We can check for example the type and then transform the result to a different output result.&lt;/p&gt;&lt;p&gt;The Groovy Console already contains some transformations for script results of type &lt;code&gt;java.awt.Image&lt;/code&gt;, &lt;code&gt;javax.swing.Icon&lt;/code&gt; and &lt;code&gt;java.awt.Component&lt;/code&gt; with no parent. To see the customized visual output we must make sure we enable this in the &lt;em&gt;View&lt;/em&gt; menu and select &lt;em&gt;Visualize Script Results&lt;/em&gt;.&lt;/p&gt;&lt;p&gt;The following sample code show that we return a String result that starts with &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt; and ends with &lt;code&gt;&amp;lt;/html&amp;gt;&lt;/code&gt; as a formatted &lt;code&gt;JLabel&lt;/code&gt;. Other String values are prepended with the default text &lt;em&gt;Groovy Console says:&lt;/em&gt;.&lt;/p&gt;&lt;pre class="brush:groovy"&gt;// File: ~/.groovy/OutputTransforms.groovy
import javax.swing.JLabel
import javax.swing.ImageIcion

transforms &lt;&lt; { result -&amp;gt;
    if (result instanceof String) {
        if (result ==~ /&amp;lt;html&amp;gt;.*&amp;lt;\/html&amp;gt;/) {
            return new JLabel(result)
        } else if (result == 'mrhaki') {
            return new ImageIcon('/Users/mrhaki/Pictures/blog/haki-logo-black-64.png')
        } else {
            return "Groovy Console says: $result"
        }
    }
}
&lt;/pre&gt;

&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-mVj7v55BBfQ/TqVvlbapHuI/AAAAAAAAE98/Mfc_nv_LGQQ/s1600/groovyconsole-output-1.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="173" width="400" src="http://2.bp.blogspot.com/-mVj7v55BBfQ/TqVvlbapHuI/AAAAAAAAE98/Mfc_nv_LGQQ/s400/groovyconsole-output-1.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-OpA9qopU4xU/TqVvld-1nrI/AAAAAAAAE-E/WMAfFmvZDEk/s1600/groovyconsole-output-2.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="132" width="400" src="http://2.bp.blogspot.com/-OpA9qopU4xU/TqVvld-1nrI/AAAAAAAAE-E/WMAfFmvZDEk/s400/groovyconsole-output-2.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-BXB5S_NAHPE/TqVwj51mkPI/AAAAAAAAE-U/fRfJYtta_FY/s1600/groovyconsole-output-3.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="215" width="400" src="http://1.bp.blogspot.com/-BXB5S_NAHPE/TqVwj51mkPI/AAAAAAAAE-U/fRfJYtta_FY/s400/groovyconsole-output-3.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6671019398434141469-7558831143304392904?l=mrhaki.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/mrhaki/~4/oXY17SdSfzg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://mrhaki.blogspot.com/feeds/7558831143304392904/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://mrhaki.blogspot.com/2011/10/groovy-goodness-customize-groovy.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6671019398434141469/posts/default/7558831143304392904?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6671019398434141469/posts/default/7558831143304392904?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/mrhaki/~3/oXY17SdSfzg/groovy-goodness-customize-groovy.html" title="Groovy Goodness: Customize Groovy Console Visual Output" /><author><name>Hubert Klein Ikkink</name><uri>https://profiles.google.com/116304108087638220732</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-VhI52jWYsR8/AAAAAAAAAAI/AAAAAAAAE_E/g4F9a-hMya8/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-mVj7v55BBfQ/TqVvlbapHuI/AAAAAAAAE98/Mfc_nv_LGQQ/s72-c/groovyconsole-output-1.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://mrhaki.blogspot.com/2011/10/groovy-goodness-customize-groovy.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0MCR38-eip7ImA9WhdaEEU.&quot;"><id>tag:blogger.com,1999:blog-6671019398434141469.post-4004279573404177397</id><published>2011-10-20T06:37:00.000+02:00</published><updated>2011-10-20T06:37:46.152+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-20T06:37:46.152+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Groovy" /><category scheme="http://www.blogger.com/atom/ns#" term="GroovyGoodness:Date" /><category scheme="http://www.blogger.com/atom/ns#" term="GroovyGoodness:GDK" /><category scheme="http://www.blogger.com/atom/ns#" term="Groovy:Goodness" /><category scheme="http://www.blogger.com/atom/ns#" term="Groovy 1.8.3" /><title>Groovy Goodness: Format Dates with TimeZone</title><content type="html">&lt;p&gt;Since Groovy 1.8.3 we can use an extra &lt;code&gt;TimeZone&lt;/code&gt; parameter with the &lt;code&gt;format()&lt;/code&gt; method of the &lt;code&gt;Date&lt;/code&gt; class. This can be used to print a date/time for a particular timezone.&lt;/p&gt;&lt;pre class="brush:groovy"&gt;import static java.util.Calendar.*

def timeZone = TimeZone.getTimeZone('Europe/Amsterdam')
def otherTimeZone = TimeZone.getTimeZone('Australia/Canberra')

def cal = Calendar.instance
cal.set(year: 2011, month: OCTOBER, date: 20, hourOfDay: 12, minute: 30)

def date = cal.time
def dateFormat = 'yyyy/MM/dd HH:mm'

assert date.format(dateFormat, timeZone) == '2011/10/20 12:30'
assert date.format(dateFormat, otherTimeZone) == '2011/10/20 21:30'
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6671019398434141469-4004279573404177397?l=mrhaki.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/mrhaki/~4/Q1joTcg2DCY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://mrhaki.blogspot.com/feeds/4004279573404177397/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://mrhaki.blogspot.com/2011/10/groovy-goodness-format-dates-with.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6671019398434141469/posts/default/4004279573404177397?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6671019398434141469/posts/default/4004279573404177397?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/mrhaki/~3/Q1joTcg2DCY/groovy-goodness-format-dates-with.html" title="Groovy Goodness: Format Dates with TimeZone" /><author><name>Hubert Klein Ikkink</name><uri>https://profiles.google.com/116304108087638220732</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-VhI52jWYsR8/AAAAAAAAAAI/AAAAAAAAE_E/g4F9a-hMya8/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://mrhaki.blogspot.com/2011/10/groovy-goodness-format-dates-with.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkADR304cSp7ImA9WhdaFU8.&quot;"><id>tag:blogger.com,1999:blog-6671019398434141469.post-4505551128909387260</id><published>2011-10-19T04:32:00.000+02:00</published><updated>2011-10-25T08:39:36.339+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-25T08:39:36.339+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Groovy" /><category scheme="http://www.blogger.com/atom/ns#" term="Groovy:Goodness" /><category scheme="http://www.blogger.com/atom/ns#" term="GroovyGoodness:CommandLine" /><title>Groovy Goodness: Default Groovy Script File Extensions</title><content type="html">&lt;p&gt;When we run a Groovy script file from the command line with the &lt;code&gt;groovy&lt;/code&gt; command we can use the complete filename to refer to the script file. But we can also leave out the filename extension. By default the following extensions are used to search for the Groovy script file:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;code&gt;.groovy&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.gvy&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.gy&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.gsh&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;So suppose we have a Groovy script file named &lt;code&gt;sample.gsh&lt;/code&gt; we can use the following commands to run the file:&lt;/p&gt;&lt;pre class="brush:shell"&gt;$ groovy sample.gsh
$ groovy sample
&lt;/pre&gt;&lt;p&gt;&lt;em&gt;(With this post we hit Groovy Goodness post 250. ;-) )&lt;/em&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6671019398434141469-4505551128909387260?l=mrhaki.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/mrhaki/~4/t2j_CyvFDP0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://mrhaki.blogspot.com/feeds/4505551128909387260/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://mrhaki.blogspot.com/2011/10/groovy-goodness-default-groovy-script.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6671019398434141469/posts/default/4505551128909387260?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6671019398434141469/posts/default/4505551128909387260?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/mrhaki/~3/t2j_CyvFDP0/groovy-goodness-default-groovy-script.html" title="Groovy Goodness: Default Groovy Script File Extensions" /><author><name>Hubert Klein Ikkink</name><uri>https://profiles.google.com/116304108087638220732</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-VhI52jWYsR8/AAAAAAAAAAI/AAAAAAAAE_E/g4F9a-hMya8/s512-c/photo.jpg" /></author><thr:total>1</thr:total><feedburner:origLink>http://mrhaki.blogspot.com/2011/10/groovy-goodness-default-groovy-script.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D08FQH4yfSp7ImA9WhdbGU4.&quot;"><id>tag:blogger.com,1999:blog-6671019398434141469.post-9017868385003771869</id><published>2011-10-18T13:03:00.002+02:00</published><updated>2011-10-18T13:03:31.095+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-18T13:03:31.095+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Groovy" /><category scheme="http://www.blogger.com/atom/ns#" term="Groovy:Goodness" /><category scheme="http://www.blogger.com/atom/ns#" term="GroovyGoodness:CommandLine" /><category scheme="http://www.blogger.com/atom/ns#" term="Groovy 1.8.3" /><title>Groovy Goodness: Run Remote Scripts via URL</title><content type="html">&lt;p&gt;Since Groovy 1.8.3 we can run remote Groovy scripts. We can use an URL to refer to the Groovy script that we want to execute. This can be very useful to build a library of Groovy scripts and publish them on a web server or a code repository like Github. Then we can run those scripts by referring the scripts by URL.&lt;/p&gt;&lt;pre class="brush:groovy"&gt;// File:
// http://www.mrhaki.com/samples/remotesample.groovy

printMessage 'Remote Groovy script @ http://www.mrhaki.com/samples/remotesample.groovy'

['Groovy', 'rocks'].each {
    print "${it.toUpperCase()} "
}
println '!'

def printMessage(message) {
    def LINE_LENGTH = message.size() + 4
    println '*' * LINE_LENGTH
    println "* $message *"
    println '*' * LINE_LENGTH
}
&lt;/pre&gt;&lt;p&gt;On a command line we run &lt;code&gt;$ groovy http://www.mrhaki.com/samples/remotesample.groovy&lt;/code&gt; and we get the following output:&lt;/p&gt;&lt;pre class="brush:plain"&gt;$ groovy http://www.mrhaki.com/samples/remotesample.groovy
****************************************************************************
* Remote Groovy script @ http://www.mrhaki.com/samples/remotesample.groovy *
****************************************************************************
GROOVY ROCKS !
$
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6671019398434141469-9017868385003771869?l=mrhaki.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/mrhaki/~4/lGYRM2vOxYw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://mrhaki.blogspot.com/feeds/9017868385003771869/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://mrhaki.blogspot.com/2011/10/groovy-goodness-run-remote-scripts-via.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6671019398434141469/posts/default/9017868385003771869?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6671019398434141469/posts/default/9017868385003771869?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/mrhaki/~3/lGYRM2vOxYw/groovy-goodness-run-remote-scripts-via.html" title="Groovy Goodness: Run Remote Scripts via URL" /><author><name>Hubert Klein Ikkink</name><uri>https://profiles.google.com/116304108087638220732</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-VhI52jWYsR8/AAAAAAAAAAI/AAAAAAAAE_E/g4F9a-hMya8/s512-c/photo.jpg" /></author><thr:total>2</thr:total><feedburner:origLink>http://mrhaki.blogspot.com/2011/10/groovy-goodness-run-remote-scripts-via.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEMERXk5fCp7ImA9WhdUEEQ.&quot;"><id>tag:blogger.com,1999:blog-6671019398434141469.post-1913479618074811634</id><published>2011-09-27T05:00:00.000+02:00</published><updated>2011-09-27T05:00:04.724+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-27T05:00:04.724+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Groovy 1.8.1" /><category scheme="http://www.blogger.com/atom/ns#" term="Groovy" /><category scheme="http://www.blogger.com/atom/ns#" term="GroovyGoodness:GDK" /><category scheme="http://www.blogger.com/atom/ns#" term="Groovy:Goodness" /><category scheme="http://www.blogger.com/atom/ns#" term="GroovyGoodness:Advanced" /><category scheme="http://www.blogger.com/atom/ns#" term="GroovyGoodness:Collections" /><title>Groovy Goodness: Use inject Method on a Map</title><content type="html">&lt;p&gt;The &lt;a href="http://mrhaki.blogspot.com/2009/09/groovy-goodness-using-inject-method.html"&gt;&lt;code&gt;inject()&lt;/code&gt; method&lt;/a&gt; is since Groovy 1.8.1 also available for Map objects. The closure arguments accepts two or three arguments. With the three-argument variant we get the key and value separately as arguments. Otherwise we get a map entry as closure argument.&lt;/p&gt;&lt;pre class="brush:groovy"&gt;// 3-argument closure with key, value.
def m = [user: 'mrhaki', likes: 'Groovy']
def sentence = m.inject('Message: ') { s, k, v -&gt;
    s += "${k == 'likes' ? 'loves' : k} $v "
}

assert sentence.trim() == 'Message: user mrhaki loves Groovy'

// 2-argument closure with entry. 
def map = [sort: 'name', order: 'desc']
def equalSizeKeyValue = map.inject([]) { list, entry -&gt;
    list &lt;&lt; (entry.key.size() == entry.value.size())
}

assert equalSizeKeyValue == [true, false]
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6671019398434141469-1913479618074811634?l=mrhaki.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/mrhaki/~4/7y7_J5slU_A" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://mrhaki.blogspot.com/feeds/1913479618074811634/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://mrhaki.blogspot.com/2011/09/groovy-goodness-use-inject-method-on.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6671019398434141469/posts/default/1913479618074811634?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6671019398434141469/posts/default/1913479618074811634?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/mrhaki/~3/7y7_J5slU_A/groovy-goodness-use-inject-method-on.html" title="Groovy Goodness: Use inject Method on a Map" /><author><name>Hubert Klein Ikkink</name><uri>https://profiles.google.com/116304108087638220732</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-VhI52jWYsR8/AAAAAAAAAAI/AAAAAAAAE_E/g4F9a-hMya8/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://mrhaki.blogspot.com/2011/09/groovy-goodness-use-inject-method-on.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0EEQHc6eSp7ImA9WhdUEE0.&quot;"><id>tag:blogger.com,1999:blog-6671019398434141469.post-2793300033834297783</id><published>2011-09-26T06:00:00.000+02:00</published><updated>2011-09-26T06:00:01.911+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-26T06:00:01.911+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="GroovyGoodness:SQL" /><category scheme="http://www.blogger.com/atom/ns#" term="Groovy" /><category scheme="http://www.blogger.com/atom/ns#" term="Groovy:Goodness" /><title>Groovy Goodness: Access ResultSetMetaData with Groovy SQL</title><content type="html">&lt;p&gt;Groovy's SQL support allows us to access &lt;code&gt;ResultSetMetaData&lt;/code&gt; with a  closure when we use the query methods &lt;code&gt;rows()&lt;/code&gt; and &lt;code&gt;eachRow()&lt;/code&gt;. We can pass a closure as the last argument of these methods. The closure parameter is the &lt;code&gt;ResultSetMetaData&lt;/code&gt; object. The closure is only invoked once after the query is executed.&lt;br /&gt;
&lt;/p&gt;&lt;pre class="brush:groovy"&gt;@Grapes([
    @Grab(group='com.h2database', module='h2', version='1.3.160'),
    @GrabConfig(systemClassLoader = true)
])
import com.h2database.*
import groovy.sql.*

def db = Sql.newInstance('jdbc:h2:mem:', 'sa', '', 'org.h2.Driver')

// Setup database.
db.execute '''
    create table if not exists languages(
        id int primary key,
        name varchar(20) not null
    )
'''

db.execute "insert into languages values(1, 'Groovy')"
db.execute "insert into languages values(2, 'Java')"

// Sample of meta closure:
String query = 'select id as identifier, name as langName from languages'
def rows = db.rows(query, { meta -&gt;
    assert meta.tableName == 'languages'
    assert meta.columnCount == 2

    assert meta.getColumnLabel(1) == 'IDENTIFIER'
    assert meta.getColumnName(1) == 'ID'
    assert meta.getColumnTypeName(1) == 'INTEGER'

    assert meta.getColumnLabel(2) == 'LANGNAME'
    assert meta.getColumnName(2) == 'NAME'
    assert meta.getColumnTypeName(2) == 'VARCHAR'
})
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6671019398434141469-2793300033834297783?l=mrhaki.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/mrhaki/~4/c5-0Trw7fD8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://mrhaki.blogspot.com/feeds/2793300033834297783/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://mrhaki.blogspot.com/2011/09/groovy-goodness-access.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6671019398434141469/posts/default/2793300033834297783?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6671019398434141469/posts/default/2793300033834297783?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/mrhaki/~3/c5-0Trw7fD8/groovy-goodness-access.html" title="Groovy Goodness: Access ResultSetMetaData with Groovy SQL" /><author><name>Hubert Klein Ikkink</name><uri>https://profiles.google.com/116304108087638220732</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-VhI52jWYsR8/AAAAAAAAAAI/AAAAAAAAE_E/g4F9a-hMya8/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://mrhaki.blogspot.com/2011/09/groovy-goodness-access.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CU8AQXw7fip7ImA9WhdVF0g.&quot;"><id>tag:blogger.com,1999:blog-6671019398434141469.post-3135641285848261514</id><published>2011-09-23T06:54:00.000+02:00</published><updated>2011-09-23T06:57:20.206+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-23T06:57:20.206+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="GroovyGoodness:SQL" /><category scheme="http://www.blogger.com/atom/ns#" term="Groovy" /><category scheme="http://www.blogger.com/atom/ns#" term="Groovy:Goodness" /><title>Groovy Goodness: Using Named (Ordinal) Parameters with Groovy SQL</title><content type="html">&lt;p&gt;Groovy has great SQL support built-in. With just a few lines of code we can access a database and write SQL statements and execute them. To query data we can for example use the &lt;code&gt;rows()&lt;/code&gt; method. We pass a SQL query and we get a List of &lt;code&gt;GroovyResultSet&lt;/code&gt; objects back. But we can also use other methods like &lt;code&gt;query()&lt;/code&gt; or &lt;code&gt;eachRow()&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;The query may contain named placeholders. For example &lt;code&gt;:name&lt;/code&gt; or &lt;code&gt;?.id&lt;/code&gt;. Both the &lt;code&gt;:&lt;/code&gt; and &lt;code&gt;?.&lt;/code&gt; syntax are supported. To give the named parameters a value we pass an extra object to the query method. This object can be a Map, Expando object or any object with properties matching the names of the named parameter.&lt;/p&gt;&lt;p&gt;Besides we can even used named ordinal parameters. Then we must use the &lt;code&gt;?.&lt;/code&gt; syntax. We set the ordinal (1-based) after the question mark. Now we pass multiple objects with values for the named parameters to the query method. For each ordinal we must pass an object with values for that named ordinal parameter.&lt;/p&gt;&lt;p&gt;The following sample shows the possibilities:&lt;/p&gt;&lt;pre class="brush:groovy"&gt;@Grapes([
    @Grab(group='com.h2database', module='h2', version='1.3.160'),
    @GrabConfig(systemClassLoader = true)
])
import com.h2database.*
import groovy.sql.*

def db = Sql.newInstance('jdbc:h2:mem:', 'sa', '', 'org.h2.Driver')

// Setup database.
db.execute '''
    create table if not exists languages(
        id int primary key,
        name varchar(20) not null
    )
'''

db.execute "insert into languages values(1, 'Groovy')"
db.execute "insert into languages values(2, 'Java')"

// ------------------
// Ready for queries:
// ------------------

// Use :name syntax for named parameters.
def result = db.rows('select * from languages where name = :name',
                     [name: 'Groovy'])
assert result[0] == [ID: 1, NAME: 'Groovy']

// Different syntax with ?.name.
result = db.rows('select * from languages where name = ?.name',
                 [name: 'Groovy'])
assert result[0] == [ID: 1, NAME: 'Groovy']

// We can use our own classes with properties matching
// query parameters.
class QueryParams {
    String name = 'Java'
    Integer id = 2
}

result = db.rows('select * from languages where name = ?.name and id = :id',
                 new QueryParams())
assert result[0] == [ID: 2, NAME: 'Java']


// We can use ordinal named parameters.
// For each ordinal placeholder we must pass an object
// with values.
result = db.rows('select * from languages where name = ?1.name and id = ?2.id',
                 [name: 'Groovy'] /* ?1.name */, [id: 1] /* ?2.id */)
assert result[0] == [ID: 1, NAME: 'Groovy']

result = db.rows('select * from languages where name = ?1.name and id = ?2.id',
                 [name: 'Groovy'], new Expando([id: 1]))
assert result[0] == [ID: 1, NAME: 'Groovy']

result = db.rows('select * from languages where name = ?1.name or name = ?2.name',
                 new QueryParams(), [name: 'Groovy'])
assert result[0] == [ID: 1, NAME: 'Groovy']
assert result[1] == [ID: 2, NAME: 'Java']
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6671019398434141469-3135641285848261514?l=mrhaki.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/mrhaki/~4/Qxd1RYIPXKM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://mrhaki.blogspot.com/feeds/3135641285848261514/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://mrhaki.blogspot.com/2011/09/groovy-goodness-using-named-ordinal.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6671019398434141469/posts/default/3135641285848261514?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6671019398434141469/posts/default/3135641285848261514?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/mrhaki/~3/Qxd1RYIPXKM/groovy-goodness-using-named-ordinal.html" title="Groovy Goodness: Using Named (Ordinal) Parameters with Groovy SQL" /><author><name>Hubert Klein Ikkink</name><uri>https://profiles.google.com/116304108087638220732</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-VhI52jWYsR8/AAAAAAAAAAI/AAAAAAAAE_E/g4F9a-hMya8/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://mrhaki.blogspot.com/2011/09/groovy-goodness-using-named-ordinal.html</feedburner:origLink></entry></feed>

