We are currently working on upgrading our project from Grails 2.2 to Grails 3.0 and have run into numerous issues. The one I'm currently working on has to do with Angular $http() and Command Objects not data binding correctly.
We currently let Grails bind all of our Command objects in our Controller methods. This is done EVERYWHERE and it would be a lot of work to go manually bind everything (Only solution I can come up with right now). We know we need to do this eventually (more control. Grails binds incorrectly constantly) but would rather not unless forced to.
class MyController {
def updateStatus(StatusCommand cmd) {
println("params: ${params}")
println("cmd: ${cmd}")
// example with objectId = 1 being passed in as http() data
// params will be: objectId: 1
// cmd will be: cmd.objectId: null
}
}
Our previous solution involved an interceptor which would take the request.JSON fields and dump them into params if there was no value already in params.
def beforeInterceptor = {
if (request.JSON) {
request.JSON?.each { key, value ->
if (!params[key]) {
params[key] = value
}
}
}
}
With Grails 3.0 Interceptors are now defined outside of the controller separately so I have created the following to replicate what we had before.
class MyInterceptor {
MyInterceptor {
matchAll()
}
boolean before() {
if (request.JSON) {
request.JSON?.each { key, value ->
if (!params[key]) {
params[key] = value
}
}
}
}
}
Unfortunately, this doesn't seem to work in Grails 3.0 like it did previously. While the values do seem to be mapped correctly on 'params' the Command Object has everything set to null. I can only assume that the Command Object is now being 'created' before the interceptor has run. Command Objects are correctly bound from our $.ajax() calls since the values are set into params and not request.JSON.
Is there a way to somehow get that created Command Object in the interceptor to set it manually or does anyone have any other ideas for a solution?
EDIT: Example of $http() angular call
var data = { objectId: 1 };
$http({
method: 'POST',
url: myUrl,
data: data
}).success(function() {
//stuff
});