grails-core
grails-core copied to clipboard
Grails 3.1.1 - command object data binding does not play well with UrlMappings params
I have an issue regarding data binding from JSON body to command object. I can provide sample app, but for now here are relevant snippets
"/api/someEndpoint/$id?"(controller: 'book', action: 'index', method: 'POST')
class BookController {
def index(SomeCommandObject cmd) {
render ([paramsAre: params, commandIs: cmd] as JSON)
}
}
class SomeCommandObject {
Long id
String someString
Integer someInteger
}
When POST-ing empty request to :8080/api/someEndpoint/1 the 'id' field of a command object is bound correctly, however including JSON, like this (using httpie)
http POST :8080/api/someEndpoint/1 someString=abc
causes 'someString' to bind but 'id' is null. I would expect these two sources of data (body and params coming from UrlMappings) to be merged. This issue seems relevant https://jira.grails.org/browse/GRAILS-11263
This has come up before, multiple times.. the consensus seems to be that binding the body and params are separate things. Maybe @jeffbrown can comment.
Just one comment from me - changing this now would may be breaking change. There is question of what should have priority in case of the same param in both sources
Can be done. If we are going to do it, 3.2 would be the time. If we did it, I think the behavior should be setup to be turned off, or default to turned off and you have to turn it on. I think just changing it and making that the only way would be problematic for some folks.
I think the project at https://github.com/jeffbrown/paramsandbody demonstrates the behavior in question. The README.md there describes how it currently behaves. That app is currently a 2.5.3 app that I created to address someone else's question about how this used to work.
I think this could be accomplished by registering a custom data binding source creator. That isn't ideal, but isn't horrible either, and could be done without making any changes to core. We have no documentation on how to do that. One of the things that could come out of the exercise is those docs.
+1 for this task
+1 I would be interested in what would be involved, with creating a custom data binding source creator.
+1 for at least to have a documentation
Current behaviour doesn't make much sense to me: depends on the request it either includes or not URL parameters. I think URL parameters should override once from the body if colliding as they were used to find the action. If collision was not intended developer may easily fix it on the server side (UrlMapping and Command object) by renaming placeholder name and need no changes on the client side. Another solution may be to bind URL parameters into the Map inside Command object. If the name of the Map cannot be the name in the body it will create a separate namespace to avoid collision.
I will look into it. Thanks for the feedback.