Hi,

I have issue after upgrading to Spring Boot 2.4.0. I'm using Spring Data JPA and I have controller methods like one below:

@GetMapping("/{parentId}/child/{childId}")
public String editChild(@PathVariable("parentId") ParentEntity parentEntity, @PathVariable("childId") ChildEntity childEntity, Map<String, Object> model) {
    return "edit-view";
}

ParentEntity and ChildEntity are Spring Data JPA entities.

This controller method is used for create or edit child entity. For creating new ChildEntity path variable childId is 0 and controller method is triggered with null as ChildEntity. For editing existing ChildEntity path variable childId is corresponding @Id of entity (e.g. 22 - GET /123/child/22) and controller method is triggered with corresponding instance of ChildEntity.

e.g.:

GET /123/child/0

With 2.3.6 (and older versions also) method is successfully processed, when I pass 0 as childId path variable, controller method is invoked with null as ChildEntity. With 2.4.0 and same request I get:

10:21:54.473  WARN [http-nio-8080-exec-8] o.s.w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.bind.MissingPathVariableException: Missing URI template variable 'childId' for method parameter of type ChildEntity]

Edit of existing entities with 2.4.0 is working OK.

Anyone has any idea why is this happening with 2.4.0 and how to fix this?

Here is minimal sample to reproduce this issue.

Comment From: bclozel

This is due to a change in Spring Framework 5.3. See spring-projects/spring-framework#26088 for a similar issue and spring-projects/spring-framework#23939 for the original change. There's a note about that in the Spring Framework migration guide.

I guess in you case, you could annotate with required=false the child entity pathvariable, which I think would reflect better your controller method here.

I'm closing this issue as I don't think we can improve things in Spring Boot about that, since it's a deliberate Spring Framework change.

Comment From: ztomic

Huh, thanks @bclozel. I have many controller methods like this in multiple products, this change is little paintful but it is what it is.

Maybe this should be mentioned in Spring Boot release notes / upgrading section also.

Comment From: drahkrub

That's really a big change in spring 5.3! Is there a chance to flexibly toggle this behaviour in spring-boot? [...] Just checked: resolveArgument(...) in AbstractNamedValueMethodArgumentResolver is "final" - not easy... I really think that was a bad (design) decision - I mean the complete change. We have a big code base here, an adjustment will cost us a lot of time...