(Quick Reference)

7.1.10 Command Objects - Reference Documentation

Authors: Graeme Rocher, Peter Ledbrook, Marc Palmer, Jeff Brown, Luke Daley, Burt Beckwith

Version: 2.3.0

7.1.10 Command Objects

Grails controllers support the concept of command objects. A command object is a class that is used in conjunction with data binding, usually to allow validation of data that may not fit into an existing domain class.

Note: A class is only considered to be a command object when it is used as a parameter of an action.

Declaring Command Objects

Command object classes are defined just like any other class.

@grails.validation.Validateable
class LoginCommand {
    String username
    String password

static constraints = { username(blank: false, minSize: 6) password(blank: false, minSize: 6) } }

In this example, the command object is marked with the Validateable annotation. The Validateable annotation allows the definition of constraints just like in domain classes. If the command object is defined in the same source file as the controller that is using it, Grails will automatically mark it as Validateable. It is not required that command object classes be validateable.

Using Command Objects

To use command objects, controller actions may optionally specify any number of command object parameters. The parameter types must be supplied so that Grails knows what objects to create and initialize.

Before the controller action is executed Grails will automatically create an instance of the command object class and populate its properties by binding the request parameters. If the command object class is marked with Validateable then the command object will be validated. For example:

class LoginController {

def login(LoginCommand cmd) { if (cmd.hasErrors()) { redirect(action: 'loginForm') return }

// work with the command object data } }

If the command object's type is that of a domain class and there is an id request parameter then instead of invoking the domain class constructor to create a new instance a call will be made to the static get method on the domain class and the value of the id parameter will be passed as an argument. Whatever is returned from that call to get is what will be passed into the controller action. This means that if there is an id request parameter and no corresponding record is found in the database then the value of the command object will be null.

Command Objects and Dependency Injection

Command objects can participate in dependency injection. This is useful if your command object has some custom validation logic which uses a Grails service:

@grails.validation.Validateable
class LoginCommand {

def loginService

String username String password

static constraints = { username validator: { val, obj -> obj.loginService.canLogin(obj.username, obj.password) } } }

In this example the command object interacts with the loginService bean which is injected by name from the Spring ApplicationContext.

Binding The Request Body To Command Objects

When a request is made to a controller action which accepts a command object and the request contains a body, Grails will attempt to parse the body of the request based on the request content type and use the body to do data binding on the command object. See the following example.

// grails-app/controllers/bindingdemo/DemoController.groovy
package bindingdemo

class DemoController {

def createWidget(Widget w) { render "Name: ${w?.name}, Size: ${w?.size}" } }

class Widget { String name Integer size }

$ curl -H "Content-Type: application/json" -d '{"name":"Some Widget","size":"42"}' localhost:8080/myapp/demo/createWidget
 Name: Some Widget, Size: 42
~ $ 
$ curl -H "Content-Type: application/xml" -d '<widget><name>Some Other Widget</name><size>2112</size></widget>' localhost:8080/bodybind/demo/createWidget
 Name: Some Other Widget, Size: 2112
~ $

Note that the body of the request is being parsed to make that work. Any attempt to read the body of the request after that will fail since the corresponding input stream will be empty. The controller action can either use a command object or it can parse the body of the request on its own (either directly, or by referring to something like request.JSON), but cannot do both.

// grails-app/controllers/bindingdemo/DemoController.groovy
package bindingdemo

class DemoController {

def createWidget(Widget w) { // this will fail because it requires reading the body, // which has already been read. def json = request.JSON

// ...

} }