Apparenly, Spring (4.3) accepts query parameters preferentially over path variables, allowing them to override the path variables when using @RequestMapping with path variables, and binding the request values to a model class. Given a controller like below:
@Controller
@RequestMapping("/")
public class HelloWorldController {
@RequestMapping(value = "/hi/{name}", method = RequestMethod.GET)
public @ResponseBody Greeting sayHello(
@Valid HelloParams helloParams) {
return new Greeting(helloParams.toString());
}
If we request a URL such as /hi/good?name=bad, we will see that the name param takes the value "bad". Thus, the "good" value which was present in the URL path in the {name} position gets ignored or overridden by the query parameter. If we remove the "name" query parameter, we get the "good" value instead.
Note: I am using a model class so that I can do validation on multiple fields of the model. I can't fix this just by using @PathVariable on a simple method parameter.
Why is this? I don't see any mention of this behavior in the documentation.
Is there any workaround to prevent it from happening?
This behavior by Spring also appears to be confusing Springfox Swagger: in this case the Swagger UI generates URLs such as: /hi/{name}?name=foo (with literal curly brackets present in the URL). And, oddly enough, it works due to the behavior described above. However, it's misleading to people who use the API because they should use path params!