## 6.1.6 Data Binding

Data binding is the act of "binding" incoming request parameters onto the properties of an object or an entire graph of objects. Data binding should deal with all necessary type conversion since request parameters, which are typically delivered via a form submission, are always strings whilst the properties of a Groovy or Java object may well not be.

Grails uses Spring's underlying data binding capability to perform data binding.

#### Binding Request Data to the Model

There are two ways to bind request parameters onto the properties of a domain class. The first involves using a domain classes' implicit constructor:

    def save = {
      def b = new Book(params)
      b.save()
    }

The data binding happens within the code `new Book(params)`. By passing the params object to the domain class constructor Grails automatically recognizes that you are trying to bind from request parameters. So if we had an incoming request like:

    /book/save?title=The%20Stand&author=Stephen%20King

Then the `title` and `author` request parameters would automatically get set on the domain class. If you need to perform data binding onto an existing instance then you can use the properties property:

    def save = {
      def b = Book.get(params.id)
      b.properties = params
      b.save()
    }

This has exactly the same effect as using the implicit constructor.

#### Data binding and Single-ended Associations

If you have a `one-to-one` or `many-to-one` association you can use Grails' data binding capability to update these relationships too. For example if you have an incoming request such as:

    /book/save?author.id=20

Grails will automatically detect the `.id` suffix on the request parameter and look-up the `Author` instance for the given id when doing data binding such as:

    def b = new Book(params)

An association property can be set to `null` by passing the literal `String` "null". For example:

    /book/save?author.id=null

#### Data Binding and Many-ended Associations

If you have a one-to-many or many-to-many association there are different techniques for data binding depending of the association type.

If you have a `Set` based association (default for a `hasMany`) then the simplest way to populate an association is to simply send a list of identifiers. For example consider the usage of `<g:select>` below:

    <g:select name="books"
              from="${Book.list()}"
              size="5" multiple="yes" optionKey="id"
              value="${author?.books}" />

This produces a select box that allows you to select multiple values. In this case if you submit the form Grails will automatically use the identifiers from the select box to populate the `books` association.

However, if you have a scenario where you want to update the properties of the associated objects the this technique won't work. Instead you have to use the subscript operator:

    <g:textField name="books[0].title" value="the Stand" />
    <g:textField name="books[1].title" value="the Shining" />

However, with `Set` based association it is critical that you render the mark-up in the same order that you plan to do the update in. This is because a `Set` has no concept of order, so although we're referring to `books0` and `books1` it is not guaranteed that the order of the association will be correct on the server side unless you apply some explicit sorting yourself.

This is not a problem if you use `List` based associations, since a `List` has a defined order and an index you can refer to. This is also true of `Map` based associations.

Note also that if the association you are binding to has a size of 2 and you refer to an element that is outside the size of association:

    <g:textField name="books[0].title" value="the Stand" />
    <g:textField name="books[1].title" value="the Shining" />
    <g:textField name="books[2].title" value="Red Madder" />

Then Grails will automatically create a new instance for you at the defined position. If you "skipped" a few elements in the middle:

    <g:textField name="books[0].title" value="the Stand" />
    <g:textField name="books[1].title" value="the Shining" />
    <g:textField name="books[5].title" value="Red Madder" />

Then Grails will automatically create instances in between. For example in the above case Grails will create 4 additional instances if the association being bound had a size of 2.

You can bind existing instances of the associated type to a `List` using the same `.id` syntax as you would use with a single-ended association. For example:

    <g:select name="books[0].id" from="${Book.list()}" value="${author?.books[0]?.id}" />
    <g:select name="books[1].id" from="${Book.list()}" value="${author?.books[1]?.id}" />
    <g:select name="books[2].id" from="${Book.list()}" value="${author?.books[2]?.id}" />

Would allow individual entries in the `books List` to be selected separately.

Entries at particular indexes can be removed in the same way too. For example:

    <g:select name="books[0].id" from="${Book.list()}" value="${author?.books[0]?.id}" noSelection="['null': '']"/>

Will render a select box that will remove the association at `books0` if the empty option is chosen.

Binding to a `Map` property works in exactly the same way except that the list index in the parameter name is replaced by the map key:

    <g:select name="images[cover].id" from="${Image.list()}" value="${book?.images[cover]?.id}" noSelection="['null': '']"/>

This would bind the selected image into the `Map` property `images` under a key of `"cover"`.

#### Data binding with Multiple domain classes

It is possible to bind data to multiple domain objects from the params object.

For example so you have an incoming request to:

    /book/save?book.title=The%20Stand&author.name=Stephen%20King

You'll notice the difference with the above request is that each parameter has a prefix such as `author.` or `book.` which is used to isolate which parameters belong to which type. Grails' `params` object is like a multi-dimensional hash and you can index into to isolate only a subset of the parameters to bind.

    def b = new Book(params['book'])

Notice how we use the prefix before the first dot of the `book.title` parameter to isolate only parameters below this level to bind. We could do the same with an `Author` domain class:

    def a = new Author(params['author'])

#### Data binding and type conversion errors

Sometimes when performing data binding it is not possible to convert a particular String into a particular target type. What you get is a type conversion error. Grails will retain type conversion errors inside the errors property of a Grails domain class. Take this example:

    class Book {
        …
        URL publisherURL
    }

Here we have a domain class `Book` that uses the Java concrete type `java.net.URL` to represent URLs. Now say we had an incoming request such as:

    /book/save?publisherURL=a-bad-url

In this case it is not possible to bind the string `a-bad-url` to the `publisherURL` property os a type mismatch error occurs. You can check for these like this:

    def b = new Book(params)if(b.hasErrors()) {
       println "The value ${b.errors.getFieldError('publisherURL').rejectedValue} is not a valid URL!"
    }

Although we have not yet covered error codes (for more information see the section on Validation), for type conversion errors you would want a message to use for the error inside the grails-app/i18n/messages.properties file. You can use a generic error message handler such as:

    typeMismatch.java.net.URL=The field {0} is not a valid URL

Or a more specific one:

    typeMismatch.Book.publisherURL=The publisher URL you specified is not a valid URL

#### Data Binding and Security concerns

When batch updating properties from request parameters you need to be careful not to allow clients to bind malicious data to domain classes that end up being persisted to the database. You can limit what properties are bound to a given domain class using the subscript operator:

    def p = Person.get(1)p.properties['firstName','lastName'] = params

In this case only the `firstName` and `lastName` properties will be bound.

Another way to do this is instead of using domain classes as the target of data binding you could use Command Objects. Alternatively there is also the flexible bindData method.

The `bindData` method allows the same data binding capability, but to arbitrary objects:

    def p = new Person()
    bindData(p, params)

However, the `bindData` method also allows you to exclude certain parameters that you don't want updated:

    def p = new Person()
    bindData(p, params, [exclude:'dateOfBirth'])

Or include only certain properties:

    def p = new Person()
    bindData(p, params, [include:['firstName','lastName]])