0

We use the following general pattern with Grails controllers and command objects

SomeController {
    def someAction() {
        SomeCommandObject co = SomeCommandObject.valueOf(params)

        if(!co.validate()) {
            // return bad request
        }

        someService.doWork(co)
        // return ok
}

SomeService {
    def doWork(SomeCommandObject co) {
        notTrue(!co.hasErrors(), 'cant have errors') // Commons validation

        // do actual work
    }
}

Apparently, if co.validate() has not been called, .hasErrors() will always return false. Is there a better way to enforce that .validate() has been called before a command object is passed between application layers? We don't want to pass around invalid command objects but we don't want to force every new method to re-validate the command object either.

Note: We aren't using the default controller/command object creation pattern because we need to do some custom parameter map checking, we use a static valueOf method instead to create the command object. Answers that change that practice are also welcome.

EDIT: A little more info on why we aren't using the 'default' controller/command object creation. Specifically why we aren't doing ..

def someAction(SomeCommandObject co) {
}

We have a requirement to disallow random query parameters, eg. endpoint/object?color=blue. To do that we need access to the parameter map in the command object to verify that it doesn't contain any 'unexpected' parameter keys. As I understand it, the default way would just create a member on the CO named color, and I don't see how to prevent arbitrary members using even custom validators. I'd happily entertain suggestions for doing so, thereby allowing us to use this default means.

P. Deters
  • 815
  • 2
  • 9
  • 18

2 Answers2

1

Yes; what you can do is pass the command object as a parameter to the controller, and then the command will always be validated automatically.

Also, what you can do, is to make a filter or similar, so that you don't have to check for the hasErrors() each time, but handle all the cases in the same way (for example, by throwing an error, or returning with a specific response).

In an application we created, we had something like:

withValidCommand(cmd) {
     // do work
}

Which worked pretty well. But maybe you can come up something even more elegant.

Erik Pragt
  • 13,513
  • 11
  • 58
  • 64
0

You should be doing this:

def someAction(SomeCommandObject co) {
    if (!co.hasErrors()) {
       someService.doWork(co)
    }
}

By passing SomeCommandObject in as the argument grails will automatically populate it from params and validate. No need to do it manually.

Gregg
  • 34,973
  • 19
  • 109
  • 214
  • I added some more info to the question explaining why we can't just use this default way. If you have suggestion on how to achieve what we're after doing so, please. – P. Deters Sep 16 '13 at 22:17