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

[java]

class Cost{

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

BigDecimal amount

}

[/java]

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

[java]

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’")
}
}
}
[/java]

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

[java]
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));
}
}
[/java]

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

[java]
beans = {
customPropertyEditorRegistrar(CustomPropertyEditorRegistrar)
}
[/java]

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

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

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 Reply

Your email address will not be published. Required fields are marked *