Grails Custom Data Binding in 3 Simple Steps

29 / Dec / 2011 by Vivek Krishna 1 comments

The other day, Farid came with an interesting problem of binding a Time String to java.sql.Time. We straight away found the answer in using a CustomTimeEditor and registering it using a CustomPropertyEditorRegistrar bean. We were able to come arrive at this solution, thanks to this StackOverflow thread.

This set me thinking into using a CustomProperty Editor for, say a Cost object, which could contain a unit and an amount


class Cost{

String unit //Could be constrained to belong to some range of values

BigDecimal amount

}

I was able to solve this issue in 3 simple steps which I would like to share with you. I felt that this would take a lesser amount of time compared to the Extended Data Binding Plugin(my gut feeling)

1. Add a CustomCostEditor to src/groovy


import java.beans.PropertyEditorSupportimport org.springframework.util.StringUtils
class CustomCostEditor extends PropertyEditorSupport {    private final boolean allowEmpty
        CustomCostEditor(boolean allowEmpty) {
               this.allowEmpty = allowEmpty
        }
        @Override
        void setAsText(String text) {
               if (this.allowEmpty && !StringUtils.hasText(text)) {
                     // Treat empty String as null value.
                     setValue(null);
               } else {
                      setValue(parse(text))
               }
        }
        @Override
        String getAsText() {
                Cost cost = (Cost) getValue()
                return "${cost.unit} ${cost.amount}"
        }
       Cost parse(String text){
                try{
                     new Cost(unit: text.substring(0, text.indexOf(" ")), amount: text.substring(text.indexOf(" ") + 1).toBigDecimal())
                } catch(Exception exception){
                     throw new IllegalArgumentException("Cost should be of the format 'Unit Amount'")
                }
       }
}

The methods which we need to override are setAsText() and getAsText()
2. Add a CustomPropertyEditorRegistrar class, which has a registerCustomEditorMethods

import org.springframework.beans.PropertyEditorRegistrar
import org.springframework.beans.PropertyEditorRegistry

class CustomPropertyEditorRegistrar implements PropertyEditorRegistrar{
    public void registerCustomEditors(PropertyEditorRegistry registry) {
        registry.registerCustomEditor(Cost.class, new com.intelligrape.example.CustomCostEditor(true));
    }
}

3. Add a spring bean to add an instance of this custom property editor registrar
Finally, we create a spring bean by adding the following line in resources.groovy

beans = {
    customPropertyEditorRegistrar(CustomPropertyEditorRegistrar)
}

Now, assuming that we have an embedded field cost of type Cost in a domain class Item, we can simply use

<input type="text" name="cost" value="${fieldValue(bean: item, field:'cost')}"/>

and input “$ 123″ to store $ in the cost.unit and 123 in the cost.amount.

I believe that the possibilities with such an approach are infinite!

FOUND THIS USEFUL? SHARE IT

comments (1 “Grails Custom Data Binding in 3 Simple Steps”)

  1. Alberto Brandolini

    Thanks for the post.

    Have you gone further on the road with CompositePropertyEditor? I am struggling to make this approach work with a composite attribute.

    Cheers

    Alberto

    Reply

Leave a comment -