Dave
Dave

Reputation: 618

Request params not getting bound to grails command object

I've upgraded to use Grails 2.1.1 from Grails 1.3.6 and some command objects which were working are no longer getting data binding from the request parameters.

I created an experimental controller to reproduce the problem:

package my.controllers

import troubleshooting.*

class ExperimentalController {


    def toggle(ExperimentalCommand cmd){
        render "<pre>${this.properties}</pre>"
        render "<h3>Raw</h3>The cmd.id was/is '${cmd.id}'<br/>The params.id was/is '${params.id}'<br/>They should be the same but they aren't<br/>The target ala cmd then params was/is '${cmd.target}' '${params.target}'<br/><hr/><hr/>"
        bindData(cmd,params)//not even this works wtf?
        render "<h3>bindData(cmd,params)</h3>The cmd.id was/is '${cmd.id}'<br/>The params.id was/is '${params.id}'<br/>They should be the same but they aren't<br/>The target ala cmd then params was/is '${cmd.target}' '${params.target}'<br/><hr/><hr/>"
        cmd = new ExperimentalCommand()
        render "<h3>New Cmd</h3>The cmd.id was/is '${cmd.id}'<br/>The params.id was/is '${params.id}'<br/>They should be the same but they aren't<br/>The target ala cmd then params was/is '${cmd.target}' '${params.target}'<br/><hr/><hr/>"
        cmd = new ExperimentalCommand(params)
        render "<h3>New Cmd binding constructor</h3>The cmd.id was/is '${cmd.id}'<br/>The params.id was/is '${params.id}'<br/>They should be the same but they aren't<br/>The target ala cmd then params was/is '${cmd.target}' '${params.target}'<br/><hr/><hr/>"
        bindData(cmd,params,[include:["id","target"]])
        render "The cmd.id was/is '${cmd.id}'<br/>The params.id was/is '${params.id}'<br/>They should be the same but they aren't<br/>The target ala cmd then params was/is '${cmd.target}' '${params.target}'<br/><hr/><hr/>"

    }
}
class ExperimentalCommand{
    def id,target,action,controller

}

If you execute:

grails run-app

With that and then go to:

http://localhost:8080/YourApp/experimental/toggle/foo?target=bullseye&cmd.target=whatever

You'll see (under my circumstances) that the first attempt to render the cmd.id shows it as null despite the fact that the params.id is foo

From this excercise I've also discovered that the bindData calls that don't specify include id and target exclusively fail AND instantiating the command object explicitly with the params causes an exception.

I'm at a complete loss here. I've tried things like overriding the getInstanceControllersApi method to return a wrapper that logs the different bindData calls so I can see what happens and how I might controll it only that told me nothing.

I can add controller and action fields to the command object to prevent it from erroring out when I call new ExperimentalCommand(params) but I shouldn't have to do any of that the Grails documentation states that the binding will get done on the instance of the command object before the action is called however in my case it is not.

Google hasn't turned up anything so apparently I am one of the first to have to deal with this.

The question is HOW can I trouble shoot this?

Upvotes: 0

Views: 3329

Answers (1)

Ian Roberts
Ian Roberts

Reputation: 122364

There have been various changes to the data binding mechanism between 1.3.6 and 2.x, the first thing I would try is to give the command object properties proper types rather than just def

class ExperimentalCommand{
    String id
    String target
    String action
    String controller
}

The Grails 2.1.1 docs for data binding talk about the new CommandObject(params) and obj.properties = params forms of data binding and state that

These forms of data binding in Grails are very convenient, but also indiscriminate. In other words, they will bind all non-transient, typed [my bold] instance properties of the target object, including ones that you may not want bound.

Upvotes: 1

Related Questions