spring-framework icon indicating copy to clipboard operation
spring-framework copied to clipboard

Support for @ModelAttribute dependency on webflux [SPR-16198]

Open spring-projects-issues opened this issue 8 years ago • 2 comments

Dongmin Shin opened SPR-16198 and commented

@ModelAttribute method arguments of @ModelAttribute annotated method are not resolved on webflux

@ModelAttribute("a")
public A attrA(@PathVariable String param1) {
    return new A(param1);
}

@ModelAttribute("b")
public B attrB(@ModelAttribute("a") A a, @RequestParam String param2) {
    // a.getParam1() is null
    return new B(a.getParam1(), param2);
}

cf.)

  • spring webmvc https://github.com/spring-projects/spring-framework/blob/master/spring-web/src/main/java/org/springframework/web/method/annotation/ModelFactory.java#L131

  • spring webflux https://github.com/spring-projects/spring-framework/blob/master/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/ModelInitializer.java#L110


Affects: 5.0.1

References: pull request https://github.com/spring-projects/spring-framework/pull/2003

spring-projects-issues avatar Nov 15 '17 07:11 spring-projects-issues

Kevin Binswanger commented

Related to #10965

spring-projects-issues avatar Oct 17 '18 18:10 spring-projects-issues

Rossen Stoyanchev commented

I will comment here on the proposed PR in order to add broader context about the feature.

In Spring MVC the it works regardless of how model attributes are added, i.e. via return value, from a method parameter, or by adding directly to an injected Model. To do that we continuously loop over model methods, each time selecting the first one to have all dependencies in the model already or none at all, until there are no more model methods left. By contrast the PR builds a graph upfront based on the declared return values from model methods, but doesn't take into account attributes that may be added from method parameters, or directly to Model

Unfortunately ModelFactoryTests doesn't demonstrate this capability so that's a failure on the part of the tests, but for example consider that you can change this code here to the one below and the tests still pass:

@ModelAttribute
public void getA(Model model) throws IOException {
    A a = new A();
    model.addAttribute("a", a);
    updateAndReturn(model, "getA", a);
}

There is also an important difference to keep in mind with WebFlux where unlike Spring MVC, the model can contain asynchronous attributes e.g. Mono<T>, and likewise model methods can declare asynchronous method parameters. fFr example, if methodA adds Mono<A> via model.addAttribute, then methodB could declare a Mono<A> method parameter and compose on that without resolving value A, or methodB could also choose to declare a method parameter of type A in which case the Mono would be resolved prior to calling methodB in order to pass the resolved value. For the most part this feature doesn't have too much to do for this because the invocation of model methods automatically takes care of resolving asynchronous values if necessary. However when checking dependencies it should be take into account the fact that the name of an attribute may vary slightly with or without a Mono/Single wrapper.

spring-projects-issues avatar Oct 31 '18 19:10 spring-projects-issues