Grails - Data Binding



Description

Data binding is a process of binding an incoming request on the object properties or graph of objects.

def info() {
    [team: Team.get(params.id)]
}

The data binder converts Map values to object properties and updates the collections and map.

For instance, the below code snippet occupies List of objects in domain class:

class Team {
    String name
    static hasMany = [teams: Team1]
    List teams
}

class Team1 {
    String player
    Integer age
}

def bindingMap = [name: 'India',
                  'teams[0]': [player: 'Sachin', age: '40'],
                  'teams[1]': [player: 'Dravid', age: '38']]

def team = new Team(bindingMap)

assert team.name == 'India'
assert team.teams.size() == 2
assert team.teams[0].player == 'Sachin'
assert team.teams[0].age == 40
assert team.teams[1].player == 'Dravid'
assert team.teams[1].age == 38

Binding Data to Model

The dotted request parameter names can be converted into nested maps by using the controller's params object. For instance, if you have request parameters as person.name.fname and person.name.lname with values 'John' and 'Smith', then params will include entries as shown below:

[person: [name: [fname: 'John', lname: 'Smith']]]

The requested parameters can be bound on properties of a domain class by using map constructor of domain classes'.

def save() {
    def myteam = new Team(params)
    myteam.save()
}

You can bind the data to multiple domain classes from the params object. For instance, consider the below incoming request:

/team/save?team.player=MS%20Dhoni&board.name=ICC%20Board

In the above code, each parameter has a prefix called board. or team. which isolates which parameters belong to which type. Use the Grails' params object to bind the subset of parameters.

def var = new Team(params.team)
def var1 = new Board(params.board)

Data Binding and Type Conversion Errors

Sometimes you can't able to convert particular string into particular target type which results in type conversion error. For example, consider a domain class 'Team' which uses java.net.URL class to specify the URLs for the below incoming request:

/team/save?publisherURL=wrong-url

You can't bind wrong-url to publisherURL property which specifies the mismatch error.

def myvar = new Team(params)

if (myvar.hasErrors()) {
    println "The value ${myvar.errors.getFieldError('publisherURL').rejectedValue}" +
            " is not a valid URL!"
}

You can define the custom binding mechanism for a particular field by using the BindUsing annotation which contains two arguments (one is object in which data binding is applied and other one is DataSourceBinding source for the data binding).

For instance:

import grails.databinding.BindUsing

class SomeClass {
    @BindUsing({obj, source 

        //'source' is DataSourceBinding for the data binding 
        source['name']?.toUpperCase()
    })
    String name
}

Date Formats for Data Binding

The date format can be set for data binding by using the @BindingFormat annotation to Date field.

For instance:

import grails.databinding.BindingFormat

class Person {
    @BindingFormat('MMddyyyy')
    Date birthDate
}

You can configure the different types of date formats in the application.groovy file as shown below:

grails.databinding.dateFormats = ['MMddyyyy', 'yyyy-MM-dd HH:mm:ss.S', "yyyy-MM-dd'T'hh:mm:ss'Z'"]

Following are the different date formats which are configured by default:

  • yyyy-MM-dd HH:mm:ss.S

  • yyyy-MM-dd’T’hh:mm:ss’Z'

  • yyyy-MM-dd HH:mm:ss.S z

  • yyy-MM-dd’T’HH:mm:ss.SSSX

Advertisements