Question

How can I apply defaults to a command object in Grails 2.3?

Note that I need to retrieve these defaults from a service when the corresponding url param is unspecified.

I have the following command object as the argument to my action

class SearchCommand {

    int page
    int pageSize     // todo: get default from configurationService

    String orderBy   // todo: get default from configurationService
    String search

}

I've looked at @BindUsing but it doesn't seem to be invoked when the corresponding request parameter is missing, defeating my attempt at applying a default value.

Was it helpful?

Solution

You could also do something like this:

A controller..

// grails-app/controllers/com/demo/DemoController.groovy

package com.demo

class DemoController {

    def createPerson(Person p) {
        render "First Name: ${p.firstName}, Last Name: ${p.lastName}"
    }
}

class Person {
    String firstName
    String lastName
}

A service...

// grails-app/services/com/demo/MyConfigurationService.groovy

package com.demo

class MyConfigurationService {

    def initializePerson(Person p) {
        p.firstName = 'Default First Name'
        p.lastName = 'Default Last Name'
    }
}

A binding listener...

// src/groovy/com/demo/PersonBindingListener.groovy
package com.demo

import org.grails.databinding.events.DataBindingListenerAdapter

class PersonBindingListener extends DataBindingListenerAdapter {

    def configService

    Boolean beforeBinding(Object target, Object errors) {
        configService.initializePerson target
        true
    }


    boolean supports(Class<?> clazz) {
        clazz == Person
    }
}

Register the listener bean...

// grails-app/conf/spring/resources.groovy

beans = {
    myListener(com.demo.PersonBindingListener) {
        configService = ref('myConfigurationService')
    }
}

OTHER TIPS

There isn't enough information here to say for sure what the best thing to do is but you have several options. There is no way to tell that framework that when it creates an instance of a command object that it should initialize properties that come from some service, but you could still use your service to help.

    class MyController {

        // there is no way to cause co to automatically be 
        // initialized with values from your service...
        def someAction(MyCommand co) {

        }

        // something like this might help...
        def someOtherAction() {
            // the service creates an instance of the object
            // and initializes values with
            def myCommand = someService.createCommand()

            // this will do data binding, overriding the default
            // values defined by the service with values that are
            // included in request params...
            bindData myCommand, params

            myCommand.validate()

            // carry on...
        }
    }

I hope that helps.

@Jeff's Answer above is great. I went with a simpler solution based on that answer:

Given the set up in the question... :

package com.whatevs

import org.grails.databinding.events.DataBindingListenerAdapter

/**
 * Binds the SearchCommand defaults
 */
class SearchCommandBindingListener extends DataBindingListenerAdapter{

    String ORDER_BY = 'lastName, firstName'
    int PAGE_SIZE = 100

    Boolean beforeBinding(Object target, Object errors) {
        SearchCommand searchCommand = (SearchCommand) target
        searchCommand.pageSize = PAGE_SIZE
        searchCommand.orderBy = ORDER_BY
        true
    }

    boolean supports(Class<?> clazz) {
        clazz == SearchCommand
    }
}

And in resources.groovy

searchCommandBindingListener(SearchCommandBindingListener)

You could override the values for ORDER_BY and PAGE_SIZE in resources.groovy as well.

searchCommandBindingListener(SearchCommandBindingListener) {
    ORDER_BY = 'firstName, lastName'
    PAGE_SIZE = 41
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top