<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"><channel><atom:link rel="hub" href="http://tumblr.superfeedr.com/" xmlns:atom="http://www.w3.org/2005/Atom"/><description>Music, software, life… and stuff.</description><title>LD.</title><generator>Tumblr (3.0; @ldaley)</generator><link>http://ldaley.com/</link><item><title>Grails, WebTest and JQuery.</title><description>&lt;p&gt;The recently released &lt;a href="http://grails.org/plugin/webtest" title="Grails Plugin - Webtest Plugin"&gt;grails-webtest 2.0.2&lt;/a&gt; now installs &lt;a href="http://webtest.canoo.com" title="Canoo WebTest"&gt;WebTest&lt;/a&gt;  via &lt;a href="http://grails.org/doc/latest/guide/3.%20Configuration.html#3.7%20Dependency%20Resolution" title="3. Configuration"&gt;dependency resolution&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This allows you to work around the &lt;a href="http://old.nabble.com/Problem-with-jQuery-and-HtmlUnit-2.4-td21931584.html" title="Old Nabble - HtmlUnit - General - Problem with jQuery and HtmlUnit 2.4"&gt;HTMLUnit 2.4 incompatibility with JQuery&lt;/a&gt;. WebTest 3.0 depends on HTMLUnit 2.4, but we can force the use of HTMLUnit 2.5 which works with JQuery.&lt;/p&gt;

&lt;p&gt;Simply add it as a dependency in your app.&lt;/p&gt;

&lt;pre class="brush: groovy"&gt;
grails.project.dependency.resolution = {
    inherits "global"
    log "warn"

    repositories {
        grailsHome()
        mavenCentral()
    }
  
    dependencies {
        test('net.sourceforge.htmlunit:htmlunit:2.5') {
            excludes 'xalan' // IVY-1006 - use xalan 2.7.0 to avoid (see below)
            excludes 'xml-apis' // GROOVY-3356
        }
        test('xalan:xalan:2.7.0') {
            excludes 'xml-apis' // GROOVY-3356
        }
    }
}    
&lt;/pre&gt;</description><link>http://ldaley.com/post/440451067</link><guid>http://ldaley.com/post/440451067</guid><pubDate>Thu, 11 Mar 2010 15:16:30 +1100</pubDate><category>software</category><category>grails</category></item><item><title>Scoped Services &amp; Proxies in Grails</title><description>&lt;p&gt;Grails has supported &lt;a href="http://www.grails.org/doc/latest/guide/8.%20The%20Service%20Layer.html#8.2%20Scoped%20Services" title="8. The Service Layer"&gt;“scoping” services&lt;/a&gt; for as long as I have been working with it. Surprisingly, you very rarely here of people using this feature. For my money, it’s one of the lowest cost techniques available to avoid the inherent spaghetti in referencing the &lt;code&gt;session&lt;/code&gt; and &lt;code&gt;request&lt;/code&gt; (for all intents and purposes) global objects.&lt;/p&gt;

&lt;p&gt;This feature is built on top of &lt;a href="http://static.springsource.org/spring/docs/2.5.x/reference/beans.html#beans-factory-scopes" title="Chapter 3. The IoC container"&gt;Spring’s bean scoping&lt;/a&gt;. However, you don’t need to know much Spring to get value out of this in Grails.&lt;/p&gt;

&lt;p&gt;Scoping a service is as simple as declaring a static &lt;code&gt;scope&lt;/code&gt; property with the name of the desired scope…&lt;/p&gt;

&lt;pre class="brush: groovy"&gt;
class MyScopedService {
    static scope = 'session'
}
&lt;/pre&gt;

&lt;p&gt;So now, for each distinct session there will be a distinct instance of &lt;code&gt;MyScopedService&lt;/code&gt; in our application.&lt;/p&gt;

&lt;h2&gt;A shopping cart as a service&lt;/h2&gt;

&lt;p&gt;An easy to understand use case for this might be a shopping cart…&lt;/p&gt;

&lt;pre class="brush: groovy"&gt;
class CartService {
    static scope = 'session'
    
    
    void addCartItem(cartItem) {
        // …
    }
    
    def getPrice() {
        // …
    }
}
&lt;/pre&gt;

&lt;p&gt;We would use this in our controller like so…&lt;/p&gt;

&lt;pre class="brush: groovy"&gt;
class CartController {
    
    def cartService
    
    def addItem = {
        cartService.addItem(/* cart item */)
    }
    
    def price = {
        println "Cart price is: " + cartService.price
    }
}
&lt;/pre&gt;

&lt;p&gt;You might be wondering just which session that &lt;code&gt;cartService&lt;/code&gt; belongs to. Grails controllers are &lt;em&gt;prototype&lt;/em&gt; scoped beans (which means a new one is created whenever it is retrieved from the application context) and only ever created inside of a request environment. Therefore, a Grails controller always lives within the context of a session. So when the controller instance is created by Grails at the start of the request, it can be injected with the instance of &lt;code&gt;cartService&lt;/code&gt; that correlates to the session that the request is for.&lt;/p&gt;

&lt;p&gt;But what about objects that don’t live inside a request (like taglibs)? For that we need a scoped proxy.&lt;/p&gt;

&lt;h2&gt;Using proxies to deal with scope differences&lt;/h2&gt;

&lt;p&gt;So we want to have a taglib that renders the current price of the shopping cart. We could pass the &lt;code&gt;cartService&lt;/code&gt; instance to the view layer via our controller action and then pass it to the taglib, but that gets tiresome &lt;em&gt;real&lt;/em&gt; quick when you start doing it for lots of actions. Since our cart is now a Spring managed bean we could try adding it as a dependency of our taglib…&lt;/p&gt;

&lt;pre class="brush: groovy"&gt;
class CartTagLib {
    
    def cartService
    
    def price = {
        out &lt;&lt; cartService.price
    }
}
&lt;/pre&gt;

&lt;p&gt;If you try and do this you are going to get…&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'cartService': Scope 'session' is not active for the current thread;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Grails taglibs are &lt;code&gt;singleton&lt;/code&gt; scoped so are created at application startup when the notion of &lt;code&gt;session&lt;/code&gt; doesn’t make any sense. What we can do though is create a singleton &lt;em&gt;proxy&lt;/em&gt; that &lt;em&gt;delegates&lt;/em&gt; to the relevant &lt;code&gt;cartService&lt;/code&gt; object at execution time (taglibs are always executed during a request so there will be session when the tag is executed).&lt;/p&gt;

&lt;p&gt;With Grails 1.2 and earlier, we have to create this proxy manually by adding this to &lt;code&gt;grails-app/conf/resources.groovy&lt;/code&gt;…&lt;/p&gt;

&lt;pre class="brush: groovy"&gt;
import org.springframework.aop.scope.ScopedProxyFactoryBean

beans = {
    cartServiceProxy(ScopedProxyFactoryBean) {
        targetBeanName = 'cartService'
        proxyTargetClass = true
    }
}
&lt;/pre&gt;

&lt;p&gt;This, in effect, creates a singleton bean, which is a dynamically generated subclass of &lt;code&gt;CartService&lt;/code&gt;, that delegates method/property calls to the &lt;code&gt;cartService&lt;/code&gt; instance stored in the session. Check out &lt;a href="http://static.springsource.org/spring/docs/2.5.x/reference/beans.html#beans-factory-scopes-other-injection" title="Chapter 3. The IoC container"&gt;Spring’s docs on scope proxies&lt;/a&gt; if you want more information on this.&lt;/p&gt;

&lt;p&gt;Now we just rewrite our taglib to use our proxy…&lt;/p&gt;

&lt;pre class="brush: groovy"&gt;
class CartTagLib {
    
    def cartServiceProxy
    
    def price = {
        out &lt;&lt; cartServiceProxy.price
    }
}
&lt;/pre&gt;

&lt;p&gt;You can now use your &lt;code&gt;cartServiceProxy&lt;/code&gt; anywhere like other services or filters. As long as the code that calls &lt;code&gt;cartServiceProxy&lt;/code&gt; is executed in a request environment everything will work as expected in a completely thread safe manner.&lt;/p&gt;

&lt;h3&gt;Some notes on Grails 1.3 improvements&lt;/h3&gt;

&lt;p&gt;Grails 1.3 will make scoped beans even more attractive by removing the need to define your own proxies. All you will have to do is…&lt;/p&gt;

&lt;pre class="brush: groovy"&gt;
class CartService {
    static scope = 'session'
    static proxy = true
}
&lt;/pre&gt;

&lt;p&gt;To have a proxy named &lt;code&gt;cartServiceProxy&lt;/code&gt; created for you. You can &lt;a href="http://jira.codehaus.org/browse/GRAILS-5701"&gt;track this new feature&lt;/a&gt; via the Grails issue tracker.&lt;/p&gt;

&lt;p&gt;Grails 1.3 will also &lt;a href="http://jira.codehaus.org/browse/GRAILS-5911"&gt;support scoped tag libs&lt;/a&gt; in the same manner as services.&lt;/p&gt;

&lt;h2&gt;Testing and scoped services&lt;/h2&gt;

&lt;p&gt;When integration testing scoped services, you need to be aware of the request/session lifecycle semantics.&lt;/p&gt;

&lt;p&gt;Each test method is run in it’s own unique environment. This means two things; you must use a proxy to access a request or session scoped in a test, and each test method will have it’s own distinct underlying service instance.&lt;/p&gt;

&lt;p&gt;class SomeTests extends GroovyTestCase {&lt;/p&gt;

&lt;pre class="brush: groovy"&gt;
import grails.plugin.spock.*

class ScopedServiceSpec extends IntegrationSpec {
 
    def sessionScopedServiceProxy
    def requestScopedServiceProxy
    
    void test1() {
        expect:
        sessionScopedServiceProxy.property == null
        requestScopedServiceProxy.property == null
        when:
        sessionScopedServiceProxy.property = 1
        requestScopedServiceProxy.property = 1
        then:
        sessionScopedServiceProxy.property == 1
        requestScopedServiceProxy.property == 1
    }

    void test2() {
        expect:
        sessionScopedServiceProxy.property == null
        requestScopedServiceProxy.property == null
        when:
        sessionScopedServiceProxy.property = 2
        requestScopedServiceProxy.property = 2
        then:
        sessionScopedServiceProxy.property == 2
        requestScopedServiceProxy.property == 2
    }
}
&lt;/pre&gt;

&lt;h2&gt;Why use scoped services and proxies?&lt;/h2&gt;

&lt;p&gt;For me it’s really about expressing intent. Some aspects of your application, like a shopping cart, are so pervasive that they end up everywhere in your code. It’s very hard to track down who is getting something from or setting something in the &lt;code&gt;session&lt;/code&gt; or &lt;code&gt;request&lt;/code&gt; objects in controllers, taglibs or filters. If you use scoped services, it’s &lt;em&gt;very&lt;/em&gt; easy to see who is doing what. I can tell a controller does something with the cart because I see &lt;code&gt;def cartService&lt;/code&gt; at the start of the class. That’s easier to spot than &lt;code&gt;session.cart&lt;/code&gt; buried in an action. I also find it allows me to stay more focussed in the language of my problem domain.&lt;/p&gt;

&lt;p&gt;Scoped services are a great tool to have in your arsenal. In an upcoming post, I’ll be discussing using custom scopes or lifecycles for your scoped services.&lt;/p&gt;</description><link>http://ldaley.com/post/436635056</link><guid>http://ldaley.com/post/436635056</guid><pubDate>Tue, 09 Mar 2010 21:46:00 +1100</pubDate><category>software</category><category>grails</category></item><item><title>Configuration based Spring bean definition with Grails. </title><description>&lt;p&gt;I released a new version of the Grails JMS plugin (0.5) over the weekend. This release features completely rewritten internals to expose every configuration aspect of the underlying Spring JMS classes. JMS is a complicated topic with lots of setup and configuration options so this level of access is necessary.&lt;/p&gt;

&lt;p&gt;What’s novel about the approach is that it allows users to configure the underlying beans via the Grails application config, rather than via direct Spring bean configuration. This has the advantage of being more generally accessible as a lot of Grails developers still shy away from directly configuring beans. It also has the advantage of allowing the plugin to assert a certain level of control over the bean definitions.&lt;/p&gt;

&lt;h2&gt;A little bit about Grails JMS&lt;/h2&gt;

&lt;p&gt;The plugin makes it convenient to specify service methods as JMS listeners.&lt;/p&gt;

&lt;pre class="brush: groovy"&gt;
import grails.plugin.jms.Subscriber

class ListeningService {
    
    @Subscriber
    void interestingStuff(payload) {
        
    }
    
}
&lt;/pre&gt;

&lt;p&gt;Whenever a message is sent to the topic “interestingStuff”, the message will be delivered to this service method.&lt;/p&gt;

&lt;p&gt;There are two aspects to receiving JMS messages with Spring’s JMS support; &lt;a href="http://static.springsource.org/spring/docs/3.0.x/api/org/springframework/jms/listener/DefaultMessageListenerContainer.html" title="DefaultMessageListenerContainer"&gt;containers&lt;/a&gt; and &lt;a href="http://static.springsource.org/spring/docs/3.0.x/api/org/springframework/jms/listener/adapter/MessageListenerAdapter.html" title="MessageListenerAdapter"&gt;adapters&lt;/a&gt;. For each listener there is a distinct container and adapter pair. In a plain Spring app, you would configure a pair of these beans to receive your messages. If you have a look at those classes, there are a lot of config options. The goal of this plugin  release was to give you access to those options &lt;em&gt;should you need it&lt;/em&gt;, but not force you to define everything yourself.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;@Subscriber&lt;/code&gt; annotation has &lt;code&gt;container&lt;/code&gt; and &lt;code&gt;adapter&lt;/code&gt; parameters that default to &lt;code&gt;"standard"&lt;/code&gt;. These parameters are the names of the &lt;em&gt;abstract&lt;/em&gt; beans that the concrete listener and adapter instances shall inherit from. There are implicit suffixes though; a &lt;code&gt;container&lt;/code&gt; value of &lt;code&gt;"standard"&lt;/code&gt; actually means the bean &lt;code&gt;standardJmsListenerContainer&lt;/code&gt; and so forth. The plugin does force some properties on the concrete instances, but very few. The majority of configuration is controlled by the abstract base.&lt;/p&gt;

&lt;h2&gt;Config based bean definitions&lt;/h2&gt;

&lt;p&gt;The other half of the story is how the beans are defined based on the config. This is driven by the &lt;a href="http://github.com/alkemist/grails-jms/blob/master/src/groovy/grails/plugin/jms/bean/MapBasedBeanDefinitionBuilder.groovy" title="src/groovy/grails/plugin/jms/bean/MapBasedBeanDefinitionBuilder.groovy at master from alkemist's grails-jms - GitHub"&gt;MapBasedBeanDefinitionBuilder&lt;/a&gt; that takes a name and &lt;code&gt;Map&lt;/code&gt; of properties a certain format and registers a bean based on the map data. There are also certain MapBasedBeanDefinitionBuilder subclasses in the plugin like &lt;a href="http://github.com/alkemist/grails-jms/blob/master/src/groovy/grails/plugin/jms/bean/JmsListenerContainerAbstractBeanDefinitionBuilder.groovy" title="src/groovy/grails/plugin/jms/bean/JmsListenerContainerAbstractBeanDefinitionBuilder.groovy at master from alkemist's grails-jms - GitHub"&gt;JmsListenerContainerAbstractBeanDefinitionBuilder&lt;/a&gt; that specialise in creating certain types of beans.&lt;/p&gt;

&lt;p&gt;The default set of beans configurations look like this…&lt;/p&gt;

&lt;pre class="brush: groovy"&gt;
import org.springframework.jms.support.converter.SimpleMessageConverter
import org.springframework.jms.listener.DefaultMessageListenerContainer

templates {
    standard {
        connectionFactoryBean = "jmsConnectionFactory"
        messageConverter = new SimpleMessageConverter()
    }
}
containers {
    standard {
        concurrentConsumers = 1
        subscriptionDurable = false
        autoStartup = false
        connectionFactoryBean = "jmsConnectionFactory"
        messageSelector = null
        cacheLevel = DefaultMessageListenerContainer.CACHE_SESSION
    }
}
adapters {
    standard {
        messageConverter = new SimpleMessageConverter()
        persistenceInterceptorBean = 'persistenceInterceptor'
    }
}
&lt;/pre&gt;

&lt;p&gt;The details aren’t important. The point is to illustrate the syntax.&lt;/p&gt;

&lt;h2&gt;Overriding defaults&lt;/h2&gt;

&lt;p&gt;This default config gets merged with the application config under the &lt;code&gt;jms&lt;/code&gt; key (e.g. &lt;code&gt;grailsApplication.config.jms&lt;/code&gt;). So to override the standard container to use a different connection factory we would have the following in our &lt;code&gt;Config.groovy&lt;/code&gt;&lt;/p&gt;

&lt;pre class="brush: groovy"&gt;
jms {
    containers {
        standard {
            connectionFactoryBean = "someOtherJmsConnectionFactory"
        }
    }
}
&lt;/pre&gt;

&lt;p&gt;Because &lt;code&gt;Config.groovy&lt;/code&gt; is environment aware, we can also do things like&lt;/p&gt;

&lt;pre class="brush: groovy"&gt;
environments {
    development {
        jms.containers.standard.connectionFactoryBean = "someOtherJmsConnectionFactory"
    }
    test {
        jms.containers.standard.connectionFactoryBean = "testJmsConnectionFactory"
    }
}
&lt;/pre&gt;

&lt;p&gt;You could even change the class of the default container definition.&lt;/p&gt;

&lt;pre class="brush: groovy"&gt;
jms {
    containers {
        standard {
            meta {
                clazz = SomeOtherListenerContainer
            }
        }
    }
}
&lt;/pre&gt;

&lt;h2&gt;Additional Beans&lt;/h2&gt;

&lt;p&gt;This mechanism also supports having more than one container &lt;em&gt;type&lt;/em&gt;&lt;/p&gt;

&lt;pre class="brush: groovy"&gt;
jms {
    containers {
        other {
            meta {
                parentBean = "standardJmsListenerContainer"
            }
            connectionFactoryBean = "otherJmsConnectionFactory"
        }
    }
}
&lt;/pre&gt;

&lt;p&gt;This creates a new container type called &lt;code&gt;other&lt;/code&gt; that inherits all of the configuration from the &lt;code&gt;standard&lt;/code&gt; container, but overrides the connection factory.&lt;/p&gt;

&lt;p&gt;You would then use this container by specifying the container on the listener.&lt;/p&gt;

&lt;pre class="brush: groovy"&gt;
import grails.plugin.jms.Subscriber

class ListeningService {
    
    @Subscriber(container = "other")
    void interestingStuff(payload) {
        
    }
    
}
&lt;/pre&gt;

&lt;h2&gt;The Point&lt;/h2&gt;

&lt;p&gt;The point of this article is not specifically to talk about the JMS plugin. This approach to bean configuration seems to work quite well when users need access to the underlying beans in an optional manner. This may be an approach that other plugin authors might want to adopt.&lt;/p&gt;</description><link>http://ldaley.com/post/435520332</link><guid>http://ldaley.com/post/435520332</guid><pubDate>Tue, 09 Mar 2010 10:42:53 +1100</pubDate><category>software</category><category>grails</category></item><item><title>Using Grails's JSON support with HTTPBuilder</title><description>&lt;p&gt;I am currently working on a set of JSON over HTTP web services APIs between Grails applications. &lt;a href="http://grails.org/doc/latest/guide/6.%20The%20Web%20Layer.html#6.1.7%20XML%20and%20JSON%20Responses" title="6. The Web Layer"&gt;Producing JSON content in Grails applications&lt;/a&gt; is ridiculously trivial, but the story on consuming content is not so clear.&lt;/p&gt;

&lt;p&gt;I am using &lt;a href="http://blog.thomnichols.org/" title="Thom Nichols"&gt;Tom Nichol&lt;/a&gt;’s &lt;a href="http://groovy.codehaus.org/modules/http-builder/" title="HTTP Builder - News"&gt;HTTPBuilder&lt;/a&gt; for consumption. It’s a great library, but does take a little getting used to. Fortunately, the documentation is excellent.&lt;/p&gt;

&lt;p&gt;HTTPBuilder ships with JSON support based on &lt;a href="http://www.jroller.com/aalmiray/" title="Andres Almiray's Weblog : Weblog"&gt;Andres Almiray&lt;/a&gt;’s &lt;a href="http://json-lib.sourceforge.net/" title="Maven - Json-lib::Welcome"&gt;json-lib&lt;/a&gt;. That works fine, but I was worried about a potential impedance mismatch between json-lib’s encoding/decoding and Grails’.&lt;/p&gt;

&lt;p&gt;Here’s how I configured HTTPBuilder to use Grails’ JSON bits for encoding/decoding JSON data…&lt;/p&gt;

&lt;pre class="brush: groovy"&gt;
import groovyx.net.http.HTTPBuilder
import groovyx.net.http.ParserRegistry
import groovyx.net.http.ContentType.JSON

import org.apache.http.entity.EntityTemplate
import org.apache.http.entity.ContentProducer
import org.apache.http.message.BasicHeader

// create a builder instance
def builder = new HTTPBuilder()

// the closure that takes a HttpServletResponse and returns an object
def jsonParser = { response -&gt;
    grails.converters.JSON.parse(new InputStreamReader(response.entity.content, ParserRegistry.getCharset(response)))
}

// the closure that takes an object and returns an org.apache.http.HttpEntity
def jsonEncoder = { value -&gt;
    def json = value instanceof Closure ? new grails.web.JSONBuilder().build(value) : new grails.converters.JSON(value)
    def producer = [writeTo: { OutputStream out -&gt; out.withWriter { json.render(it) } }] as ContentProducer
    def entity = new EntityTemplate(producer)
    entity.contentType = new BasicHeader("Content-Type", JSON.toString())
    entity
}

// for each JSON content type, install the handler
JSON.contentTypeStrings.each {
    builder.parser."$it" = jsonParser
    builder.encoder."$it" = jsonEncoder
}
&lt;/pre&gt;

&lt;p&gt;Note that you have to configure each created HTTPBuilder instance.&lt;/p&gt;

&lt;p&gt;Here is some contrived example usage. We are calling a JSON “mirror” service that simply just returns the JSON it was sent.&lt;/p&gt;

&lt;pre class="brush: groovy"&gt;

import grails.plugin.spock.*

import groovyx.net.http.Method.POST
import groovyx.net.http.ContentType.JSON

class HttpBuilderWithGrailsJsonSpec extends UnitSpec {

    void "test it all works like it should"() {
        given: "a configured HTTP builder"
        def builder = new HTTPBuilder("http://jsonmirror.org")
        // configure the builder as per above
        
        when: "I post '{a: 1}' to the JSON mirror service"
        def requestMethod = POST
        def responseContentType = JSON
        def result = builder.request(requestMethod, responseContentType) {
            def requestContentType = JSON
            send(requestContentType) {
                a = 1
            }
        }
        
        then: "I get the JSON '{a: 1}' returned"
        result.a == 1
    }
}
&lt;/pre&gt;</description><link>http://ldaley.com/post/410169928</link><guid>http://ldaley.com/post/410169928</guid><pubDate>Thu, 25 Feb 2010 13:01:00 +1100</pubDate><category>software</category><category>grails</category></item><item><title>Automatically packaging inline plugins in Grails 1.2</title><description>&lt;p&gt;Working with module Grails applications via in-place plugins is currently not as convenient as it could be. One of the major sticking points is the need to &lt;code&gt;package-plugin&lt;/code&gt; all of your inline plugins manually before using them in your application’s build.&lt;/p&gt;

&lt;p&gt;If you try to build your app without packaging your in-place plugins first you will see something like…&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;The inplace plugin at [«plugin path»] does not have a plugin.xml. Please run the package-plugin command inside the plugin directory.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This gets tiresome real quick when you have a lot of in-place plugins. Fortunately the workaround isn’t too bad.&lt;/p&gt;

&lt;h2&gt;Add a build event listener&lt;/h2&gt;

&lt;p&gt;Add the following to &lt;code&gt;scripts/_Events.groovy&lt;/code&gt;…&lt;/p&gt;

&lt;pre class="brush: groovy"&gt;
eventInitInplacePluginsStart = {
    pluginSettings.inlinePluginDirectories.each { resource -&gt;
        if (!new File(resource.file, 'plugin.xml').exists()) {
            def descriptor = pluginSettings.getDescriptorForPlugin(resource)
            generatePluginXml(descriptor.file)
        }
    }
}
&lt;/pre&gt;

&lt;p&gt;That’s going to generate any missing &lt;code&gt;plugin.xml&lt;/code&gt;’s for you… but there is a catch&lt;/p&gt;

&lt;h2&gt;Lazily load classes in the plugin descriptor&lt;/h2&gt;

&lt;p&gt;The event code above has to compile the &lt;code&gt;*GrailsPlugin.groovy&lt;/code&gt; plugin descriptor in order to read the metadata to generate the &lt;code&gt;plugin.xml&lt;/code&gt;. This is done &lt;em&gt;before&lt;/em&gt; the classes in the plugin are compiled and therefore any classes that you &lt;em&gt;import&lt;/em&gt; in your plugin descriptor are not going to be available.&lt;/p&gt;

&lt;p&gt;The solution is to load the classes lazily via the application classloader…&lt;/p&gt;

&lt;pre class="brush: groovy"&gt;
class MyGrailsPlugin {

    def version = "0.1"
    def grailsVersion = "1.2.* &gt; *"

    def doWithSpring = {
        def awesomeClass = application.classLoader("grails.plugin.my.Awesome")
        // …
    }
}
&lt;/pre&gt;

&lt;p&gt;While this is slightly inconvenient, it beats manually running &lt;code&gt;package-plugin&lt;/code&gt; in a bunch of directories.&lt;/p&gt;

&lt;h2&gt;The good news&lt;/h2&gt;

&lt;p&gt;This issue is well known about, but the fix is non trivial. It will be fixed for Grails 1.3 though.&lt;/p&gt;</description><link>http://ldaley.com/post/406653338</link><guid>http://ldaley.com/post/406653338</guid><pubDate>Tue, 23 Feb 2010 19:09:18 +1100</pubDate><category>software</category><category>grails</category></item><item><title>Instantiating the right class in Groovy dynamic constructors</title><description>&lt;p&gt;I just came across some Groovy code that essentially looks like this…&lt;/p&gt;

&lt;pre class="brush: groovy"&gt;
def installConstructor(Class clazz) {
    clazz.metaClass.constructor = { Map params -&gt;
        def instance = clazz.newInstance()
        // do some stuff with params
        instance
    }
}
&lt;/pre&gt;

&lt;p&gt;Looks innocent at first right?&lt;/p&gt;

&lt;p&gt;Consider this…&lt;/p&gt;

&lt;pre class="brush: groovy"&gt;
class Parent {}
class Child extends Parent { String name }

ExpandoMetaClass.enableGlobally() // enable metaclass inheritance

installConstructor(Parent)
def c = new Child(name: "LD")
&lt;/pre&gt;

&lt;p&gt;The issue here is that &lt;code&gt;c&lt;/code&gt; is not going to be what you expect. You are going to get back an instance of &lt;code&gt;Parent&lt;/code&gt; from this constructor call because our newly added constructor added to &lt;code&gt;Parent&lt;/code&gt; is hardcoded to return &lt;code&gt;Parent&lt;/code&gt; instances.&lt;/p&gt;

&lt;p&gt;The fix is easy…&lt;/p&gt;

&lt;pre class="brush: groovy"&gt;
def installConstructor(Class clazz) {
    clazz.metaClass.constructor = { Map params -&gt;
        def instance = delegate.newInstance() 
        // do some stuff with params
        instance
    }
}
&lt;/pre&gt;

&lt;p&gt;For a dynamic constructor implementation, &lt;code&gt;delegate&lt;/code&gt; refers to the actual target class of the construction. So unless you are doing some really wild stuff and deliberately returning objects of a different class, you always want to use &lt;code&gt;delegate&lt;/code&gt; as the target class.&lt;/p&gt;</description><link>http://ldaley.com/post/401574184</link><guid>http://ldaley.com/post/401574184</guid><pubDate>Sun, 21 Feb 2010 12:46:00 +1100</pubDate><category>software</category><category>grails</category></item><item><title>Brute force fixture cleanup in Grails</title><description>&lt;p&gt;I am currently working on establishing a suite of functional tests. I am using the functional test features of the &lt;a href="http://www.grails.org/plugin/spock" title="Grails Plugin - Spock"&gt;spock plugin&lt;/a&gt; to do this, which I’ll be writing more on in the near future.&lt;/p&gt;

&lt;p&gt;Naturally, I am using the &lt;a href="http://grails.org/plugin/fixtures" title="Grails - Fixtures Plugin"&gt;fixtures plugin&lt;/a&gt; to load my test data in the functional tests. However, the plugin provides no support for tearing down data. You generally don’t need to worry about this in integration tests because integration tests are by default wrapped in rollback-only transactions. This is not possible due to the nature of functional tests though.&lt;/p&gt;

&lt;p&gt;In order to get something up and running quickly, I implemented this…&lt;/p&gt;

&lt;pre class="brush: groovy"&gt;
import groovy.sql.Sql
import grails.plugin.spock.FunctionalSpec

abstract class FunctionalSpecSupport extends FunctionalSpec {

    def dataSource
    def sessionFactory
        
    def cleanup() {
        sessionFactory.currentSession.flush()
        def sql = new Sql(dataSource)
        sql.execute("SET FOREIGN_KEY_CHECKS = 0")
        grailsApplication.domainClasses.each { domainClass -&gt;
            sql.execute "DELETE FROM " + sessionFactory.getClassMetadata(domainClass.clazz).tableName
        }
        sql.execute("SET FOREIGN_KEY_CHECKS = 1")
        sessionFactory.currentSession.clear()
    }
    
}   
&lt;/pre&gt;

&lt;p&gt;All of my actual functional tests extend this &lt;code&gt;FunctionalSpecSupport&lt;/code&gt; class. The &lt;code&gt;cleanup()&lt;/code&gt; method is to Spock what &lt;code&gt;tearDown()&lt;/code&gt; is to standard JUnit tests. That is, it’s invoked after &lt;em&gt;every&lt;/em&gt; test. Also, due to historical reasons the project I am working on uses MySQL so the SQL above may be specific to that DB, I don’t know.&lt;/p&gt;

&lt;p&gt;That lacks finesse, but it get’s the job done.&lt;/p&gt;</description><link>http://ldaley.com/post/398082618</link><guid>http://ldaley.com/post/398082618</guid><pubDate>Fri, 19 Feb 2010 17:09:23 +1100</pubDate><category>software</category><category>grails</category></item><item><title>Integration Testing Grails Filters</title><description>&lt;p&gt;Grails currently doesn’t ship with any support for testing filters, other than via a functional test. It’s pretty easy to roll your own filter &lt;strong&gt;integration&lt;/strong&gt; tests though.&lt;/p&gt;

&lt;p&gt;Here is an example:&lt;/p&gt;

&lt;pre class="brush: groovy"&gt;
import grails.util.GrailsWebUtil

class MyFilterTests extends GroovyTestCase {
    
    def filterInterceptor
    def grailsApplication
    def grailsWebRequest
    
    def request(Map params, controllerName, actionName) {
        grailsWebRequest = GrailsWebUtil.bindMockWebRequest(grailsApplication.mainContext)
        grailsWebRequest.params.putAll(params)
        grailsWebRequest.controllerName = controllerName
        grailsWebRequest.actionName = actionName
        filterInterceptor.preHandle(grailsWebRequest.request, grailsWebRequest.response, null)
    }
    
    def getResponse() {
        grailsWebRequest.currentResponse
    }
    
    def testFilterRedirects() {
        def result = request("home", "index", someParameter: "2")
        assertFalse result
        assertTrue response.redirectedUrl.endsWith(/* something */)
    }
    
}
&lt;/pre&gt;

&lt;p&gt;Note that &lt;code&gt;filterInterceptor.preHandle()&lt;/code&gt; executes &lt;em&gt;all&lt;/em&gt; of your filters, which is what you really want in an integration test. It also returns the return value of the &lt;em&gt;last executed&lt;/em&gt; filter. When issuing a redirect, we return &lt;code&gt;false&lt;/code&gt; in our filter handler to prevent any further request processing so we are testing for that here.&lt;/p&gt;

&lt;p&gt;If you are interesting in &lt;strong&gt;unit&lt;/strong&gt; testing your filters, you might want to check out the &lt;a href="http://n4.nabble.com/Testing-Filters-td1382438.html" title="Nabble - Grails - user - Testing Filters?"&gt;mailing list thread on the topic&lt;/a&gt;.&lt;/p&gt;</description><link>http://ldaley.com/post/392153102</link><guid>http://ldaley.com/post/392153102</guid><pubDate>Tue, 16 Feb 2010 15:54:00 +1100</pubDate><category>grails</category><category>software</category></item><item><title>Dealing with common test support across test types</title><description>&lt;p&gt;Grails ships with several different test superclasses to make your testing life easier. This is great, but what if you have your own common testing bits that you want to provide in a superclass? Even worse, what if you are using the &lt;a href="http://spockframework.org/" title="spock - Project Hosting on Google Code"&gt;Spock&lt;/a&gt; &lt;a href="http://grails.org/plugin/spock" title="Grails Plugin - Spock"&gt;plugin&lt;/a&gt; and have a completely different class hierarchy to work with?&lt;/p&gt;

&lt;p&gt;The current project I am working on has a mix of Spock and JUnit tests of different types. Most of the tests also require some relatively common context establishment regardless of the test type. The solution I came up with was to use a &lt;em&gt;test support object&lt;/em&gt; instead of a super class. That might seem straightforward, but it gets interesting when you need dependency injection.&lt;/p&gt;

&lt;p&gt;Let’s take a look at the test support class…&lt;/p&gt;

&lt;pre class="brush: groovy"&gt;
import org.codehaus.groovy.grails.commons.ApplicationHolder

class TestSupport { 
    
    @Lazy fixtureLoader = getBean('fixtureLoader')
    @Lazy someOtherService = getBean('someOtherService')
    
    protected getBean(name) {
        ApplicationHolder.application.mainContext[name]
    }
    
    def loadFixture(fixtureParams) {
        // load fixture here
    }
    
    // Other common methods and stuff
}
&lt;/pre&gt;

&lt;p&gt;Why the use of &lt;code&gt;ApplicationHolder&lt;/code&gt; to get at the application context and the beans? Well, we are trying to avoid &lt;a href="http://www.exubero.com/junit/antipatterns.html#Mixing_Production_and_Test_Code" title="Exubero - JUnit Anti-patterns"&gt;mixing test and production code&lt;/a&gt; by having the &lt;code&gt;TestSupport&lt;/code&gt; class in &lt;code&gt;tests/integration&lt;/code&gt;, which means we can’t make it a service. We also can’t selectively create an autowired instance via &lt;code&gt;grails-app/conf/resources.groovy&lt;/code&gt; because classes in &lt;code&gt;tests/integration&lt;/code&gt; are not available to the classloader that deals with loading the application context. So while the use of the static holder bothers me, it’s the only tool we have to get the job done at the moment. Also, not the use of Groovy’s &lt;a href="http://groovy.codehaus.org/Lazy+transformation" title="Groovy - Lazy transformation"&gt;@Lazy transformation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here is how I use the test support class in a Spec…&lt;/p&gt;

&lt;pre class="brush: groovy"&gt;
import grails.plugin.spock.*

class SomeSpec extends IntegrationSpec {
    
    @Delegate TestSupport testSupport = new TestSupport()
    
    def "some stuff should happen"() {
        given:
        loadFixture(/* fixture options */)
        when:
        someOtherService.doStuff()
        then:
        someOtherService.stuffHappened
    }
    
    def "some other stuff should happen"() {
        given:
        loadFixture(/* fixture options */)
        when:
        someOtherService.doOtherStuff()
        then:
        someOtherService.otherStuffHappened
    }
}
&lt;/pre&gt;

&lt;p&gt;The use of Groovy’s &lt;a href="http://groovy.codehaus.org/Delegate+transformation" title="Groovy - Delegate transformation"&gt;@Delegate transformation&lt;/a&gt; makes the actual test code look like it’s using a support superclass, but it isn’t, which is the whole point of this exercise. You can now use your common test support methods in any kind of test case.&lt;/p&gt;</description><link>http://ldaley.com/post/391882325</link><guid>http://ldaley.com/post/391882325</guid><pubDate>Tue, 16 Feb 2010 13:08:10 +1100</pubDate><category>grails</category><category>software</category></item><item><title>Panic! At The Disco: Pretty Odd</title><description>&lt;p&gt;&lt;img src="http://media.tumblr.com/tumblr_kxrs3j4RPv1qzm4y3.jpg" alt=""/&gt;&lt;/p&gt;

&lt;p&gt;A very underrated album that kind of slipped past without much fanfare. I despised these guys from their first single. It dropped around the same time My Chemical Romance were getting airplay and there was way too much guyliner and mascara going on. Shitty Emo fashion aside the first album was ok. Not great, but ok. This one really shines though.&lt;/p&gt;

&lt;p&gt;It plays like a modern day Sgt. Peppers with solid arrangement and unexpected musicianship. If you enjoy melodically rich tunes and can get past the band’s image and persona then I recommend checking it out.&lt;/p&gt;</description><link>http://ldaley.com/post/386921587</link><guid>http://ldaley.com/post/386921587</guid><pubDate>Sat, 13 Feb 2010 19:03:16 +1100</pubDate><category>music</category></item><item><title>Providing non-domain validateables in Grails plugins.</title><description>&lt;p&gt;Grails now (1.2+) supports &lt;a href="http://grails.org/doc/latest/guide/7.%20Validation.html#7.5%20Validation%20Non%20Domain%20and%20Command%20Object%20Classes" title="7. Validation"&gt;making arbitrary classes validateable&lt;/a&gt;. This is easy enough, but what if you have a plugin with a non-domain class that needs to be validateable?&lt;/p&gt;

&lt;p&gt;What you might try is adding the necessary config into the &lt;code&gt;Config.groovy&lt;/code&gt; in your plugin. This &lt;em&gt;is not&lt;/em&gt; going to work though because that’s not going to be sourced when your plugin is deployed into an application.&lt;/p&gt;

&lt;p&gt;So here’s a solution:&lt;/p&gt;

&lt;pre class="brush: groovy"&gt;
package grails.plugin.radness

class RadnessGrailsPlugin {
    def loadBefore = ['validation'] // important

    def doWithDynamicMethods = {
        if (!application.config.grails.validateable.classes) {
            application.config.grails.validateable.classes = []
        }
        application.config.grails.validateable.classes &lt;&lt; RadnessValidateable
    }
}
&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;RadnessValidateable&lt;/code&gt; class gets configured with all the validation bits. You &lt;em&gt;don’t&lt;/em&gt; need to annotate the class with &lt;code&gt;org.codehaus.groovy.grails.validation.Validateable&lt;/code&gt;, the above is enough to make it work.&lt;/p&gt;</description><link>http://ldaley.com/post/381257676</link><guid>http://ldaley.com/post/381257676</guid><pubDate>Wed, 10 Feb 2010 15:50:00 +1100</pubDate><category>grails</category><category>software</category></item><item><title>TextMate Interactive Input and Snow Leopard</title><description>&lt;p&gt;I had some fun today upgrading tm_interactive_input.dylib to make it work with Snow Leopard. Previously, it was &lt;a href="http://blog.macromates.com/2009/interactive-input/"&gt;busted in a pretty decent way&lt;/a&gt;.&lt;/p&gt;



&lt;p&gt;I can’t be exactly sure, but it seems that &lt;code&gt;malloc() &lt;/code&gt;on Snow Leopard calls &lt;code&gt;read()&lt;/code&gt; for some strange reason. Since our overloaded &lt;code&gt;read()&lt;/code&gt; implementation does quite a few things, including a lot of &lt;code&gt;malloc()&lt;/code&gt;ing we have a problem. The end result was that anything loaded with our library injected explodes.&lt;/p&gt;



&lt;p&gt;The solution was to use a thread local flag via the &lt;a href="http://developer.apple.com/mac/library/documentation/Darwin/Reference/ManPages/man3/pthread.3.html" title="Mac OS X Manual Page For pthread(3)"&gt;pthreads&lt;/a&gt; &lt;a href="http://developer.apple.com/mac/library/documentation/Darwin/Reference/ManPages/man3/pthread_getspecific.3.html" title="Mac OS X Manual Page For pthread_getspecific(3)"&gt;thread local storage&lt;/a&gt; to mark when we entered any of our overloaded code paths. This is simple enough, but I couldn’t for the life of me getting working due to a nasty issue which I hadn’t anticipated.&lt;/p&gt;



&lt;p&gt;To use the pthread library’s thread local storage stuff, you need to create a token using &lt;a href="http://developer.apple.com/mac/library/documentation/Darwin/Reference/ManPages/man3/pthread_key_create.3.html" title="Mac OS X Manual Page For pthread_key_create(3)"&gt;pthread_key_create()&lt;/a&gt; which you can later use to retrieve a thread specific value for. So in C library, how do you handle initialisation code? It turns out that &lt;a href="http://www.faqs.org/docs/Linux-HOWTO/Program-Library-HOWTO.html#INIT-AND-CLEANUP"&gt;library constructors&lt;/a&gt; solve this exact problem.&lt;/p&gt;



&lt;p&gt;News to me.&lt;/p&gt;



&lt;p&gt;So I initialise the key in a library constructor and litter my code with the appropriate checks and so forth. No dice. I am still seeing the exact same behaviour. To make things more interesting I can’t use GDB because of the nature of the library and I can’t use printf statements because they use &lt;code&gt;malloc() &lt;/code&gt; internally which just exacerbates the problem. I can however use &lt;code&gt;write()&lt;/code&gt;, so that’s something.&lt;/p&gt;



&lt;p&gt;After littering the code with &lt;code&gt;write()&lt;/code&gt;s, I discovered that my &lt;code&gt;read()&lt;/code&gt; implementation is being called &lt;i&gt;before&lt;/i&gt; my library constructor. I don’t know why this is the case but I am guessing that somehow the dynamic linker has made the overloaded functions in our library available to the host binary &lt;i&gt;during the loading process&lt;/i&gt;. Either that, or the linker itself is calling our overloaded functions. Either way, kinda strange.&lt;/p&gt;



&lt;p&gt;Once I worked out that this was going on, it was trivial to fix. Simply set an ‘initialised’ flag in our library constructor and don’t use our overloaded functions until that is set.&lt;/p&gt;



&lt;p&gt;GitHub has the &lt;a href="http://github.com/alkemist/interactive-input/commit/1504bb2b4edc970f1f339d986b4ada5b7d4685f5" title="Commit 1504bb2b4edc970f1f339d986b4ada5b7d4685f5 to alkemist's interactive-input - GitHub"&gt;commit&lt;/a&gt; for more info, or grab the &lt;a href="http://cloud.github.com/downloads/alkemist/interactive-input/tm_interactive_input.dylib"&gt;binary&lt;/a&gt; directly (see &lt;a href="http://lists.macromates.com/textmate/2009-September/029486.html" title="[TxMt] [FIXED] Interactive Input on Snow Leopard."&gt;here&lt;/a&gt; for install instructions).&lt;/p&gt;



&lt;p&gt;This should be included in the next TextMate distribution.&lt;/p&gt;</description><link>http://ldaley.com/post/184441587</link><guid>http://ldaley.com/post/184441587</guid><pubDate>Thu, 10 Sep 2009 21:14:00 +1000</pubDate><category>textmate</category><category>software</category></item><item><title>Reclaim your home life with AppleScript</title><description>&lt;p&gt;Anyone using Mail.app to both work and home combined with MobileMe sync is probably like me and unable to avoid reading work email when at home because you just can’t resist taking a look when you see something new there. A co-worker came up with a good solution to this problem: stop Mail.app from checking for new email in your work account during non work hours.&lt;/p&gt;

&lt;p&gt;Here is a simple AppleScript you can use to take an account out of the auto fetch schedule:&lt;/p&gt;

&lt;pre class="applescript" id="geshi_code"&gt;&lt;span style="color: #b1b100;"&gt;tell&lt;/span&gt; application &lt;span style="color: #ff0000;"&gt;"Mail"&lt;/span&gt;
    &lt;span style="color: #b1b100;"&gt;set&lt;/span&gt; include when getting new mail &lt;span style="color: #b1b100;"&gt;of&lt;/span&gt; account &lt;span style="color: #ff0000;"&gt;"account name"&lt;/span&gt; &lt;span style="color: #b1b100;"&gt;to&lt;/span&gt; &lt;span style="color: #000066;"&gt;false&lt;/span&gt;
&lt;span style="color: #b1b100;"&gt;end&lt;/span&gt; &lt;span style="color: #b1b100;"&gt;tell&lt;/span&gt;&lt;/pre&gt;
&lt;br/&gt;</description><link>http://ldaley.com/post/184379864</link><guid>http://ldaley.com/post/184379864</guid><pubDate>Sun, 06 Sep 2009 23:25:00 +1000</pubDate><category>software</category></item><item><title>Why I do Open Source</title><description>&lt;p&gt;(This was inspired by &lt;a href="http://www.jroller.com/aalmiray/entry/why_i_do_open_source" title="Andres Almiray's Weblog : Weblog"&gt;Andres Almiray&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;I did not have a lot of exposure to Open Source software during my formative computing years. I come from a Classic Mac OS (I saw the last few releases of 7) background and was blissfully ignorant to Linux. The move to OS X exposed me to a plethora of previously unavailable software and during this time I was becoming interested in coding. As a student surrounded by other “Computer Scientists” who were interested in anything but coding, my only real available avenue for growth was to participate in virtual communities of developers.&lt;/p&gt;

&lt;p&gt;While it wasn’t an intentional move, the ideals and general culture of typical open source developer communities resonate very naturally with me (open information, need before greed etc). Also, I am attracted to the artistic side of writing software as opposed to just being in it for the utility. In my experience (which granted isn’t vast) you can find extremely talented people who are true artists, not just laborers, gathered around open source projects. If you are putting your work up in front of these people then you are forcing yourself to improve, and to me that is what it’s about.&lt;/p&gt;

&lt;p&gt;I am sure not all Open Source Software is of a high calibre, but I bet you that in almost every case that man hour for man hour an open source project will trump a closed commercial project in terms of quality almost every time. If you want to improve your skills, hang out with the best around.&lt;/p&gt;

&lt;p&gt;Apart from this self interested reason, I also enjoy creating software that other people use. There is not much better than getting an email from someone you don’t know and them thanking you for the hours you put into something because it has helped them achieve something.&lt;/p&gt;</description><link>http://ldaley.com/post/184379859</link><guid>http://ldaley.com/post/184379859</guid><pubDate>Mon, 26 Jan 2009 21:20:00 +1100</pubDate><category>software</category></item><item><title>Gldapo Validation</title><description>&lt;p&gt;I am about to commit the new GORM inspired validation mechanism to Gldapo. Here is what it is going to look like…&lt;/p&gt;

&lt;h3&gt;Declaring your constraints&lt;/h3&gt;

&lt;p&gt;Instead of a DSL like GORM, we are using annotations…&lt;/p&gt;

&lt;pre class="groovy" id="geshi_code"&gt;&lt;span style="color: #a1a100;"&gt;import gldapo.schema.annotations.&lt;em&gt;&lt;/em&gt;&lt;/span&gt;

&lt;a href="http://www.google.de/search?q=site%3Adocs.codehaus.org/%20class"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;class&lt;/span&gt;&lt;/a&gt; Person &lt;span style="color: #66cc66;"&gt;{&lt;/span&gt;

    @GldapoNamingAttribute 
    &lt;a href="http://www.google.de/search?as_q=String&amp;num=100&amp;hl=en&amp;as_occt=url&amp;as_sitesearch=java.sun.com%2Fj2se%2F1.5.0%2Fdocs%2Fapi%2F"&gt;&lt;span style="color: #aaaadd; font-weight: bold;"&gt;String&lt;/span&gt;&lt;/a&gt; uid

    @Required
    &lt;a href="http://www.google.de/search?as_q=String&amp;num=100&amp;hl=en&amp;as_occt=url&amp;as_sitesearch=java.sun.com%2Fj2se%2F1.5.0%2Fdocs%2Fapi%2F"&gt;&lt;span style="color: #aaaadd; font-weight: bold;"&gt;String&lt;/span&gt;&lt;/a&gt; sn

    @Required
    @Matches&lt;span style="color: #66cc66;"&gt;(&lt;/span&gt;/&lt;span style="color: #66cc66;"&gt;[&lt;/span&gt;A-Z&lt;span style="color: #66cc66;"&gt;]&lt;/span&gt;.&lt;span style="color: #006600;"&gt;&lt;/span&gt;/&lt;span style="color: #66cc66;"&gt;)&lt;/span&gt;
    &lt;a href="http://www.google.de/search?as_q=String&amp;num=100&amp;hl=en&amp;as_occt=url&amp;as_sitesearch=java.sun.com%2Fj2se%2F1.5.0%2Fdocs%2Fapi%2F"&gt;&lt;span style="color: #aaaadd; font-weight: bold;"&gt;String&lt;/span&gt;&lt;/a&gt; givenName
&lt;span style="color: #66cc66;"&gt;}&lt;/span&gt;&lt;/pre&gt;
&lt;br/&gt;&lt;h3&gt;Plugging in your own constraints&lt;/h3&gt;

&lt;p&gt;You can register your own constraints quite easily. There are two parts, the constraint annotation and the validator.&lt;/p&gt;

&lt;p&gt;The constraint annotation (has to be in Java since you can’t define annotations in Groovy 1.5.x)…&lt;/p&gt;

&lt;pre class="java" id="geshi_code"&gt;&lt;span style="color: #a1a100;"&gt;import java.lang.annotation.*;&lt;/span&gt;
&lt;span style="color: #a1a100;"&gt;import gldapo.schema.annotation.Validator;&lt;/span&gt;
&lt;span style="color: #a1a100;"&gt;import gldapo.schema.attribute.validator.EqualsValidator;&lt;/span&gt;

@Target&lt;span style="color: #66cc66;"&gt;(&lt;/span&gt;ElementType.&lt;span style="color: #006600;"&gt;FIELD&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;)&lt;/span&gt;
@Retention&lt;span style="color: #66cc66;"&gt;(&lt;/span&gt;RetentionPolicy.&lt;span style="color: #006600;"&gt;RUNTIME&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;)&lt;/span&gt;
@Validator&lt;span style="color: #66cc66;"&gt;(&lt;/span&gt;EqualsValidator&lt;span style="color: #66cc66;"&gt;)&lt;/span&gt; &lt;span style="color: #808080; font-style: italic;"&gt;// 
&lt;span style="color: #000000; font-weight: bold;"&gt;public&lt;/span&gt; @&lt;span style="color: #000000; font-weight: bold;"&gt;interface&lt;/span&gt; Equals
&lt;span style="color: #66cc66;"&gt;{&lt;/span&gt;
    &lt;a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AObject+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"&gt;&lt;span style="color: #aaaadd; font-weight: bold;"&gt;Object&lt;/span&gt;&lt;/a&gt; value&lt;span style="color: #66cc66;"&gt;(&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;)&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;;&lt;/span&gt;
&lt;span style="color: #66cc66;"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;br/&gt;&lt;p&gt;As you can see it’s a stock standard annotation, that is itself annotated with &lt;code&gt;@Validator&lt;/code&gt; to tell Gldapo how to validate this type of constraint.&lt;/p&gt;

&lt;p&gt;The validator looks like this…&lt;/p&gt;

&lt;pre class="groovy" id="geshi_code"&gt;&lt;a href="http://www.google.de/search?q=site%3Adocs.codehaus.org/%20package"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;package&lt;/span&gt;&lt;/a&gt; gldapo.&lt;span style="color: #006600;"&gt;schema&lt;/span&gt;.&lt;span style="color: #006600;"&gt;attribute&lt;/span&gt;.&lt;span style="color: #006600;"&gt;validator&lt;/span&gt;

&lt;a href="http://www.google.de/search?q=site%3Adocs.codehaus.org/%20class"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;class&lt;/span&gt;&lt;/a&gt; EqualsValidator &lt;a href="http://www.google.de/search?q=site%3Adocs.codehaus.org/%20extends"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;extends&lt;/span&gt;&lt;/a&gt; AbstractFieldValidator &lt;span style="color: #66cc66;"&gt;{&lt;/span&gt;

    &lt;a href="http://www.google.de/search?q=site%3Adocs.codehaus.org/%20def"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;def&lt;/span&gt;&lt;/a&gt; validate&lt;span style="color: #66cc66;"&gt;(&lt;/span&gt;obj&lt;span style="color: #66cc66;"&gt;)&lt;/span&gt; &lt;span style="color: #66cc66;"&gt;{&lt;/span&gt;
        &lt;a href="http://www.google.de/search?q=site%3Adocs.codehaus.org/%20if"&gt;&lt;span style="color: #b1b100;"&gt;if&lt;/span&gt;&lt;/a&gt; &lt;span style="color: #66cc66;"&gt;(&lt;/span&gt;obj &lt;span style="color: #66cc66;"&gt;!=&lt;/span&gt; &lt;a href="http://www.google.de/search?q=site%3Adocs.codehaus.org/%20this"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;this&lt;/span&gt;&lt;/a&gt;.&lt;span style="color: #006600;"&gt;constraint&lt;/span&gt;.&lt;span style="color: #006600;"&gt;value&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;(&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;)&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;)&lt;/span&gt; &lt;span style="color: #66cc66;"&gt;{&lt;/span&gt;
            &lt;a href="http://www.google.de/search?q=site%3Adocs.codehaus.org/%20return"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;return&lt;/span&gt;&lt;/a&gt; &lt;span style="color: #66cc66;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;'notequals'&lt;/span&gt;, &lt;span style="color: #ff0000;"&gt;"notequals.${this.constraint.value()}"&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;]&lt;/span&gt;
        &lt;span style="color: #66cc66;"&gt;}&lt;/span&gt;
    &lt;span style="color: #66cc66;"&gt;}&lt;/span&gt;

&lt;span style="color: #66cc66;"&gt;}&lt;/span&gt;&lt;/pre&gt;
&lt;br/&gt;&lt;p&gt;Validators have to extend &lt;code&gt;gldapo.schema.attribute.validator.AbstractFieldValidator&lt;/code&gt; and implement &lt;code&gt;validate(obj)&lt;/code&gt;. This method takes the value to validate and returns either a single error code, or a list of error codes. If the value is valid it should return &lt;code&gt;null&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Gldapo will register several error codes if validation fails. If a class called &lt;code&gt;Person&lt;/code&gt; has it’s &lt;code&gt;name&lt;/code&gt; field annotated with &lt;code&gt;@Equals('Luke')&lt;/code&gt; and it fails validation, the following error codes will be registered…&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;notequals
notequals.Luke
person.notequals
person.notequals.Luke
person.name.notequals
person.name.notequals.Luke
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If the usage of error codes seem a bit weird here, then you should check out &lt;a href="http://grails.org/doc/1.0.x/guide/7.%20Validation.html#7.4%20Validation%20and%20Internationalization" title="7. Validation"&gt;7.4 Validation and Internationalization&lt;/a&gt; in the Grails user guide as the concept is exactly the same.&lt;/p&gt;

&lt;p&gt;Finally, you need to register your constraint with Gldapo. You do this by listing your custom constraint types as a list under the &lt;code&gt;contraintTypes&lt;/code&gt; key in the config…&lt;/p&gt;

&lt;pre class="groovy" id="geshi_code"&gt;Gldapo.&lt;span style="color: #006600;"&gt;initialize&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;(&lt;/span&gt;
    contraintTypes: &lt;span style="color: #66cc66;"&gt;[&lt;/span&gt;Equals&lt;span style="color: #66cc66;"&gt;]&lt;/span&gt;
&lt;span style="color: #66cc66;"&gt;)&lt;/span&gt;&lt;/pre&gt;
&lt;br/&gt;&lt;h3&gt;Performing validation&lt;/h3&gt;

&lt;p&gt;This side of things works exactly like GORM…&lt;/p&gt;

&lt;pre class="groovy" id="geshi_code"&gt;&lt;a href="http://www.google.de/search?q=site%3Adocs.codehaus.org/%20def"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;def&lt;/span&gt;&lt;/a&gt; p &lt;span style="color: #66cc66;"&gt;=&lt;/span&gt; &lt;a href="http://www.google.de/search?q=site%3Adocs.codehaus.org/%20new"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;new&lt;/span&gt;&lt;/a&gt; Person&lt;span style="color: #66cc66;"&gt;(&lt;/span&gt;uid: &lt;span style="color: #ff0000;"&gt;"ld"&lt;/span&gt;, givenName: &lt;span style="color: #ff0000;"&gt;"Luke"&lt;/span&gt; sn: &lt;span style="color: #ff0000;"&gt;"Daley"&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;)&lt;/span&gt;
    &lt;a href="http://www.google.de/search?q=site%3Adocs.codehaus.org/%20if"&gt;&lt;span style="color: #b1b100;"&gt;if&lt;/span&gt;&lt;/a&gt; &lt;span style="color: #66cc66;"&gt;(&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;!&lt;/span&gt;p.&lt;span style="color: #006600;"&gt;save&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;(&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;)&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;)&lt;/span&gt; &lt;span style="color: #66cc66;"&gt;{&lt;/span&gt;
        p.&lt;span style="color: #006600;"&gt;errors&lt;/span&gt;.&lt;span style="color: #006600;"&gt;allErrors&lt;/span&gt;.&lt;a href="http://www.google.de/search?q=site%3Adocs.codehaus.org/%20each"&gt;&lt;span style="color: #663399;"&gt;each&lt;/span&gt;&lt;/a&gt; &lt;span style="color: #66cc66;"&gt;{&lt;/span&gt;
            &lt;a href="http://www.google.de/search?q=site%3Adocs.codehaus.org/%20println"&gt;&lt;span style="color: #993399;"&gt;println&lt;/span&gt;&lt;/a&gt; it
        &lt;span style="color: #66cc66;"&gt;}&lt;/span&gt;
    &lt;span style="color: #66cc66;"&gt;}&lt;/span&gt;&lt;/pre&gt;
&lt;br/&gt;&lt;p&gt;There is also the &lt;code&gt;validate()&lt;/code&gt; method if you just want to perform validation without trying to write the object back.&lt;/p&gt;

&lt;p&gt;If you haven’t used validation in GORM, check out &lt;a href="http://grails.org/doc/1.0.x/guide/7.%20Validation.html" title="7. Validation"&gt;this chapter&lt;/a&gt; in the user guide, because it will all hold true (except how constraints are defined) with Gldapo.&lt;/p&gt;</description><link>http://ldaley.com/post/184379843</link><guid>http://ldaley.com/post/184379843</guid><pubDate>Wed, 03 Dec 2008 20:52:00 +1100</pubDate><category>gldapo</category><category>software</category></item><item><title>Grails TextMate bundle is being improved</title><description>&lt;p&gt;I am working on a grails app (more info to come), as such I am making some long needed improvements to the &lt;a href="http://macromates.com/svn/Bundles/trunk/Bundles/Groovy%20Grails.tmbundle/" title="/trunk/Bundles/Groovy Grails.tmbundle"&gt;Grails TextMate bundle&lt;/a&gt;. If you are using this, you might want to subscribe to the bundle &lt;a href="http://fisheye2.atlassian.com/browse/textmate-bundles/trunk/Bundles/Groovy%20Grails.tmbundle" title="FishEye: browsing textmate-bundles/trunk/Bundles/Groovy Grails.tmbundle"&gt;changes feed&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I have made two changes already; a snippet for the &lt;code&gt;&lt;render&gt;&lt;/render&gt;&lt;/code&gt; tag in GSPs, and a command to run a single test case (the currently open file in TM).&lt;/p&gt;</description><link>http://ldaley.com/post/184379831</link><guid>http://ldaley.com/post/184379831</guid><pubDate>Sun, 21 Sep 2008 22:01:00 +1000</pubDate><category>grails</category></item><item><title>Gldapo 0.7.1 Released</title><description>&lt;p&gt;This release has only one change which fixes &lt;a href="http://jira.codehaus.org/browse/GLDP-92" title="[#GLDP-92] Non string type attributes are not properly handled - jira.codehaus.org"&gt;an issue with password attributes&lt;/a&gt;.&lt;/p&gt;</description><link>http://ldaley.com/post/184379821</link><guid>http://ldaley.com/post/184379821</guid><pubDate>Sun, 21 Sep 2008 21:52:51 +1000</pubDate></item><item><title>Gldapo 0.7 Released</title><description>&lt;p&gt;Gldapo 0.7 (and a corresponding grails plugin) is &lt;a href="http://gldapo.codehaus.org/gldapo/download.html" title="Gldapo - Download"&gt;now available&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This release primarily fixes some bugs with password attributes and brings the following major features/improvements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The addition of an LDAP filter DSL (thanks to Siegfried Puchbauer)&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://ldaley.com/2008/07/04/movingreplacing-entries-with-gldapo-07/" title="ldaley.com  Moving/Replacing entries with Gldapo 0.7"&gt;Drastic improvement&lt;/a&gt; to the API for creating and moving objects.&lt;/li&gt;
&lt;li&gt;JavaDoc for commonly used classes (thanks to new GMaven features)&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Release Notes&lt;/h4&gt;

&lt;h5&gt;Sub-task&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;[&lt;a href="http://jira.codehaus.org/browse/GLDP-66"&gt;GLDP-66&lt;/a&gt;] - Base the location of entries in the directory on a ‘parent’ directiory rather than the ‘rdn’ attribute&lt;/li&gt;
&lt;li&gt;[&lt;a href="http://jira.codehaus.org/browse/GLDP-69"&gt;GLDP-69&lt;/a&gt;] - Make defining a naming attribute mandatory (i.e. throw exception if none defined)&lt;/li&gt;
&lt;li&gt;[&lt;a href="http://jira.codehaus.org/browse/GLDP-70"&gt;GLDP-70&lt;/a&gt;] - Add documentation for @GldapoNamingAttribute&lt;/li&gt;
&lt;li&gt;[&lt;a href="http://jira.codehaus.org/browse/GLDP-79"&gt;GLDP-79&lt;/a&gt;] - Raise exception if rdn is set with a different naming attribute&lt;/li&gt;
&lt;li&gt;[&lt;a href="http://jira.codehaus.org/browse/GLDP-82"&gt;GLDP-82&lt;/a&gt;] - Raise exception if naming attribute is changed directly (i.e. not via move() or replace())&lt;/li&gt;
&lt;li&gt;[&lt;a href="http://jira.codehaus.org/browse/GLDP-86"&gt;GLDP-86&lt;/a&gt;] - Create ‘GldapoEntry’ abstract base class and document&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;Bug&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;[&lt;a href="http://jira.codehaus.org/browse/GLDP-76"&gt;GLDP-76&lt;/a&gt;] - Converting raw array values to native (groovy) values with schema-custom mapper raises GldapoTypeMappingException&lt;/li&gt;
&lt;li&gt;[&lt;a href="http://jira.codehaus.org/browse/GLDP-77"&gt;GLDP-77&lt;/a&gt;] - Reading an entry with a password attribute raises exceptions&lt;/li&gt;
&lt;li&gt;[&lt;a href="http://jira.codehaus.org/browse/GLDP-81"&gt;GLDP-81&lt;/a&gt;] - Static properties on schemas are not ignored&lt;/li&gt;
&lt;li&gt;[&lt;a href="http://jira.codehaus.org/browse/GLDP-91"&gt;GLDP-91&lt;/a&gt;] - GldapoSynonymFor breaks GldapoNamingAttribute&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;Improvement&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;[&lt;a href="http://jira.codehaus.org/browse/GLDP-47"&gt;GLDP-47&lt;/a&gt;] - When moving/replacing an object, the in memory value of the naming attribute should be updated to reflect the change&lt;/li&gt;
&lt;li&gt;[&lt;a href="http://jira.codehaus.org/browse/GLDP-58"&gt;GLDP-58&lt;/a&gt;] - Fix JavaDoc generation and use that as the definitive documentation source&lt;/li&gt;
&lt;li&gt;[&lt;a href="http://jira.codehaus.org/browse/GLDP-60"&gt;GLDP-60&lt;/a&gt;] - Sanitise API for replacing/moving objects&lt;/li&gt;
&lt;li&gt;[&lt;a href="http://jira.codehaus.org/browse/GLDP-72"&gt;GLDP-72&lt;/a&gt;] - Consolidate overloaded rdn setter on schema objects&lt;/li&gt;
&lt;li&gt;[&lt;a href="http://jira.codehaus.org/browse/GLDP-73"&gt;GLDP-73&lt;/a&gt;] - Fetch raw values from contexts as objects, not strings&lt;/li&gt;
&lt;li&gt;[&lt;a href="http://jira.codehaus.org/browse/GLDP-74"&gt;GLDP-74&lt;/a&gt;] - Implement tests for schema-custom TO FIELD type mappers&lt;/li&gt;
&lt;li&gt;[&lt;a href="http://jira.codehaus.org/browse/GLDP-75"&gt;GLDP-75&lt;/a&gt;] - Implement tests for schema-custom TO TYPE type mappers&lt;/li&gt;
&lt;li&gt;[&lt;a href="http://jira.codehaus.org/browse/GLDP-87"&gt;GLDP-87&lt;/a&gt;] - Rename ‘rdn’ property to ‘brdn’&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;New Feature&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;[&lt;a href="http://jira.codehaus.org/browse/GLDP-41"&gt;GLDP-41&lt;/a&gt;] - Provide way to name object based on particular attribute&lt;/li&gt;
&lt;li&gt;[&lt;a href="http://jira.codehaus.org/browse/GLDP-68"&gt;GLDP-68&lt;/a&gt;] - Add a Filter DSL to ease LDAP querying&lt;/li&gt;
&lt;li&gt;[&lt;a href="http://jira.codehaus.org/browse/GLDP-71"&gt;GLDP-71&lt;/a&gt;] - Support password type attributes&lt;/li&gt;
&lt;li&gt;[&lt;a href="http://jira.codehaus.org/browse/GLDP-78"&gt;GLDP-78&lt;/a&gt;] - Add ‘namingValue’ property to entries&lt;/li&gt;
&lt;li&gt;[&lt;a href="http://jira.codehaus.org/browse/GLDP-83"&gt;GLDP-83&lt;/a&gt;] - Add move(String,Object) method to move an object by naming value and parent&lt;/li&gt;
&lt;li&gt;[&lt;a href="http://jira.codehaus.org/browse/GLDP-84"&gt;GLDP-84&lt;/a&gt;] - Add replace(String,Object) method to replace an object by naming value and parent&lt;/li&gt;
&lt;li&gt;[&lt;a href="http://jira.codehaus.org/browse/GLDP-85"&gt;GLDP-85&lt;/a&gt;] - Add replace() method&lt;/li&gt;
&lt;li&gt;[&lt;a href="http://jira.codehaus.org/browse/GLDP-89"&gt;GLDP-89&lt;/a&gt;] - Provide find() and findAll() variants that take a filter builder closure&lt;/li&gt;
&lt;li&gt;[&lt;a href="http://jira.codehaus.org/browse/GLDP-90"&gt;GLDP-90&lt;/a&gt;] - Typemapping for Boolean type&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Enjoy.&lt;/p&gt;</description><link>http://ldaley.com/post/184379819</link><guid>http://ldaley.com/post/184379819</guid><pubDate>Sun, 24 Aug 2008 01:29:08 +1000</pubDate></item><item><title>New Java and JavaDoc TextMate bundles</title><description>&lt;p&gt;Finally, I got the new Java and JavaDoc TM bundles up to scratch and got them promoted from review.&lt;/p&gt;

&lt;p&gt;If you are using TM for Java, you’ll want to update your bundle.&lt;/p&gt;</description><link>http://ldaley.com/post/184379809</link><guid>http://ldaley.com/post/184379809</guid><pubDate>Sat, 05 Jul 2008 03:57:00 +1000</pubDate><category>software</category><category>textmate</category></item><item><title>Moving/Replacing entries with Gldapo 0.7</title><description>&lt;p&gt;Following on from the &lt;a href="http://ldaley.com/2008/07/02/gldaponamingattribute/" title="ldaley.com  @GldapoNamingAttribute"&gt;previous post&lt;/a&gt;, Gldapo 0.7 makes dealing with the location of LDAP objects much easier. This impacts the &lt;code&gt;move()&lt;/code&gt; and &lt;code&gt;replace()&lt;/code&gt; methods. I’ll focus on &lt;code&gt;replace()&lt;/code&gt; here, but pretty much everything applies to &lt;code&gt;move()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;0.7 introduces a new signature of &lt;code&gt;replace(String namingValue, Object parent)&lt;/code&gt;. Let’s look at some usage then I’ll explain.&lt;/p&gt;

&lt;p&gt;What we want to do here is replace an object with &lt;code&gt;cn=Luke&lt;/code&gt; and &lt;code&gt;sn=Daily&lt;/code&gt; with an object with &lt;code&gt;sn=Daley&lt;/code&gt; (note: we could do this with a search, mod, save admittedly, but this is just an example).&lt;/p&gt;

&lt;p&gt;I am using the person schema class from the &lt;a href="http://ldaley.com/2008/07/02/gldaponamingattribute/" title="ldaley.com  @GldapoNamingAttribute"&gt;previous post&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;First, 0.6 style…&lt;/p&gt;


&lt;pre class="groovy" id="geshi_code"&gt;&lt;a href="http://www.google.de/search?q=site%3Adocs.codehaus.org/%20def"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;def&lt;/span&gt;&lt;/a&gt; p &lt;span style="color: #66cc66;"&gt;=&lt;/span&gt; &lt;a href="http://www.google.de/search?q=site%3Adocs.codehaus.org/%20new"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;new&lt;/span&gt;&lt;/a&gt; Person&lt;span style="color: #66cc66;"&gt;(&lt;/span&gt;
    cn: &lt;span style="color: #ff0000;"&gt;"Luke"&lt;/span&gt;,
    sn: &lt;span style="color: #ff0000;"&gt;"Daley"&lt;/span&gt;
&lt;span style="color: #66cc66;"&gt;)&lt;/span&gt;

p.&lt;span style="color: #006600;"&gt;replace&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;(&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;"cn=Luke"&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;)&lt;/span&gt;&lt;/pre&gt;
&lt;br/&gt;&lt;p&gt;In 0.7…&lt;/p&gt;


&lt;pre class="groovy" id="geshi_code"&gt;&lt;a href="http://www.google.de/search?q=site%3Adocs.codehaus.org/%20def"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;def&lt;/span&gt;&lt;/a&gt; p &lt;span style="color: #66cc66;"&gt;=&lt;/span&gt; &lt;a href="http://www.google.de/search?q=site%3Adocs.codehaus.org/%20new"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;new&lt;/span&gt;&lt;/a&gt; Person&lt;span style="color: #66cc66;"&gt;(&lt;/span&gt;
    sn: &lt;span style="color: #ff0000;"&gt;"Daley"&lt;/span&gt;
&lt;span style="color: #66cc66;"&gt;)&lt;/span&gt;

p.&lt;span style="color: #006600;"&gt;replace&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;(&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;"Luke"&lt;/span&gt;, &lt;a href="http://www.google.de/search?q=site%3Adocs.codehaus.org/%20null"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;null&lt;/span&gt;&lt;/a&gt;&lt;span style="color: #66cc66;"&gt;)&lt;/span&gt;&lt;/pre&gt;
&lt;br/&gt;&lt;p&gt;Or…&lt;/p&gt;


&lt;pre class="groovy" id="geshi_code"&gt;&lt;a href="http://www.google.de/search?q=site%3Adocs.codehaus.org/%20def"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;def&lt;/span&gt;&lt;/a&gt; p &lt;span style="color: #66cc66;"&gt;=&lt;/span&gt; &lt;a href="http://www.google.de/search?q=site%3Adocs.codehaus.org/%20new"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;new&lt;/span&gt;&lt;/a&gt; Person&lt;span style="color: #66cc66;"&gt;(&lt;/span&gt;
    cn: &lt;span style="color: #ff0000;"&gt;"Luke"&lt;/span&gt;,
    sn: &lt;span style="color: #ff0000;"&gt;"Daley"&lt;/span&gt;
&lt;span style="color: #66cc66;"&gt;)&lt;/span&gt;

p.&lt;span style="color: #006600;"&gt;replace&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;(&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;)&lt;/span&gt;&lt;/pre&gt;
&lt;br/&gt;&lt;p&gt;Because we now know which attribute defines the name, we don’t need to duplicate that information in the replace() call.&lt;/p&gt;

&lt;p&gt;The second argument to &lt;code&gt;replace(String,Object)&lt;/code&gt; is the parent of the object to replace. Say we wanted to replace an object in a different ou…&lt;/p&gt;


&lt;pre class="groovy" id="geshi_code"&gt;p.&lt;span style="color: #006600;"&gt;replace&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;(&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;"Luke"&lt;/span&gt;, &lt;span style="color: #ff0000;"&gt;"ou=people"&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;)&lt;/span&gt;&lt;/pre&gt;
&lt;br/&gt;&lt;p&gt;The &lt;code&gt;move(String,Object)&lt;/code&gt; method follows similar semantics. Note though that there is no &lt;code&gt;move()&lt;/code&gt; method, cause that just wouldn’t make sense.&lt;/p&gt;</description><link>http://ldaley.com/post/184379806</link><guid>http://ldaley.com/post/184379806</guid><pubDate>Fri, 04 Jul 2008 05:30:29 +1000</pubDate></item></channel></rss>
