Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Grails Goodness: Custom Data Binding with @DataBinding Annotation

DZone's Guide to

Grails Goodness: Custom Data Binding with @DataBinding Annotation

· Java Zone
Free Resource

Download Microservices for Java Developers: A hands-on introduction to frameworks and containers. Brought to you in partnership with Red Hat.

Grails has a data binding mechanism that will convert request parameters to properties of an object of different types. We can customize the default data binding in different ways. One of them is using the @DataBinding annotation. We use a closure as argument for the annotation in which we must return the converted value. We get two arguments, the first is the object the data binding is applied to and the second is the source with all original values of typeSimpleMapDataBindingSource. The source could for example be a map like structure or the parameters of a request object.

In the next example code we have a Product class with a ProductId class. We write a custom data binding to convert the String value with the pattern {code}-{identifier} to a ProductId object:

package mrhaki.grails.binding

import grails.databinding.BindUsing

class Product {

    // Use custom data binding with @BindUsing annotation.
    @BindUsing({ product, source ->

        // Source parameter contains the original values.
        final String productId = source['productId']

        // ID format is like {code}-{identifier},
        // eg. TOYS-067e6162.
        final productIdParts = productId.split('-')

        // Closure must return the actual for 
        // the property.
        new ProductId(
            code: productIdParts[0],
            identifier: productIdParts[1])

    })
    ProductId productId

    String name

}

// Class for product identifier.
class ProductId {
    String code
    String identifier
}

The following specification shows the data binding in action:

package mrhaki.grails.binding

import grails.test.mixin.TestMixin
import grails.test.mixin.support.GrailsUnitTestMixin
import spock.lang.Specification
import grails.databinding.SimpleMapDataBindingSource

@TestMixin(GrailsUnitTestMixin)
class ProductSpec extends Specification {

    def dataBinder

    def setup() {
        // Use Grails data binding
        dataBinder = applicationContext.getBean('grailsWebDataBinder')
    }

    void "productId parameter should be converted to a valid ProductId object"() {
        given:
        final Product product = new Product()

        and:
        final SimpleMapDataBindingSource source = 
            [productId: 'OFFCSPC-103910ab24', name: 'Swingline Stapler']

        when:
        dataBinder.bind(product, source)

        then:
        with(product) {
            name == 'Swingline Stapler'

            with(productId) {
                identifier == '103910ab24'
                code == 'OFFCSPC'
            }
        }
    }

}

If we would have a controller with the request parameters productId=OFFCSPC-103910ab24&name=Swingline%20Stapler the data binding of Grails can create a Product instance and set the properties with the correct values.

Written with Grails 2.5.0 and 3.0.1.


Download Building Reactive Microservices in Java: Asynchronous and Event-Based Application Design. Brought to you in partnership with Red Hat

Topics:

Published at DZone with permission of Hubert Klein Ikkink, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}