Currently (Spring 5.2) we can not use constructor based bean binding of path variables as we can with request parameters. This is somewhat an inconsistent way of binding url data. Bean property binding is supported for both types of parameters but therefor a mutable object is required.

In method constructAttribute (ModelAttributeMethodProcessor.java:277) the values for constructor parameters are only taken from webRequest.getParameterValues(paramName) so no path variables are taken into account here. It's only when that constructed attribute object is bind by bindRequestParameters(binder, webRequest) in method resolveArgument (ModelAttributeMethodProcessor.java:160) that the path variables (as well as the request parameters again) are eventually added for bean property binding in method ServletRequestDataBinder#bind.

I mentioned this problem in issue 22600 and was correctly advised to create a separate issue for this to avoid a mixed conversation.

Comment From: rstoyanchev

Note that sub-class ServletModelAttributeMethodProcessor already has getRequestValueForAttribute that checks URI variables first. Possibly that can be elevated one level up. Either way it's quite straight-forward to obtain those variables.

Comment From: rob-valor

Indeed. However maybe something to take into account is that currently the request parameters take precedence over, well, no path variables at all when constructing the attribute instance. So taking the path variables's value first could suddenly change the data that is used in the constructor because the same name can be used for both path variable as request parameter like

@GetMapping("params/{parameter}") 
Something getSomething(@PathVariable("parameter") String pathVariable, @RequestParam("parameter") String requestParameter)

So to not change the current behavior (data used in the constructor) the value of the path variable should only be use when there is no value for the same request parameter (name). Although that isn't bullet proof either.

Comment From: rstoyanchev

Good point. Currently when binding via setters we skip URI variables if a request parameter is already present.