diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/view/ViewResolutionResultHandler.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/view/ViewResolutionResultHandler.java index 814588a915..71098648d3 100644 --- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/view/ViewResolutionResultHandler.java +++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/view/ViewResolutionResultHandler.java @@ -294,13 +294,20 @@ public class ViewResolutionResultHandler extends AbstractHandlerResultHandler private Mono resolveAsyncAttributes(Map model) { List names = new ArrayList<>(); - List> valueMonos = new ArrayList<>(); + List> valueMonos = new ArrayList<>(); for (Map.Entry entry : model.entrySet()) { ReactiveAdapter adapter = getAdapterRegistry().getAdapterFrom(null, entry.getValue()); if (adapter != null) { names.add(entry.getKey()); - valueMonos.add(adapter.toMono(entry.getValue()).defaultIfEmpty(NO_VALUE)); + if (adapter.getDescriptor().isMultiValue()) { + Flux value = adapter.toFlux(entry.getValue()); + valueMonos.add(value.collectList().defaultIfEmpty(Collections.emptyList())); + } + else { + Mono value = adapter.toMono(entry.getValue()); + valueMonos.add(value.defaultIfEmpty(NO_VALUE)); + } } } diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/view/ViewResolutionResultHandlerTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/view/ViewResolutionResultHandlerTests.java index 7c8e16194a..6c50b03ba3 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/view/ViewResolutionResultHandlerTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/view/ViewResolutionResultHandlerTests.java @@ -33,6 +33,7 @@ import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; import rx.Completable; +import rx.Observable; import rx.Single; import org.springframework.core.MethodParameter; @@ -270,9 +271,11 @@ public class ViewResolutionResultHandlerTests { @Test public void modelWithAsyncAttributes() throws Exception { this.bindingContext.getModel() - .addAttribute("bean1", Mono.just(new TestBean("Bean1"))) - .addAttribute("bean2", Single.just(new TestBean("Bean2"))) - .addAttribute("empty", Mono.empty()); + .addAttribute("attr1", Mono.just(new TestBean("Bean1"))) + .addAttribute("attr2", Flux.just(new TestBean("Bean1"), new TestBean("Bean2"))) + .addAttribute("attr3", Single.just(new TestBean("Bean2"))) + .addAttribute("attr4", Observable.just(new TestBean("Bean1"), new TestBean("Bean2"))) + .addAttribute("attr5", Mono.empty()); ResolvableType type = forClass(void.class); HandlerResult result = new HandlerResult(new Object(), null, returnType(type), this.bindingContext); @@ -281,11 +284,13 @@ public class ViewResolutionResultHandlerTests { this.request.setUri("/account"); handler.handleResult(this.exchange, result).blockMillis(5000); assertResponseBody("account: {" + - "bean1=TestBean[name=Bean1], " + - "bean2=TestBean[name=Bean2], " + - "org.springframework.validation.BindingResult.bean1=" + + "attr1=TestBean[name=Bean1], " + + "attr2=[TestBean[name=Bean1], TestBean[name=Bean2]], " + + "attr3=TestBean[name=Bean2], " + + "attr4=[TestBean[name=Bean1], TestBean[name=Bean2]], " + + "org.springframework.validation.BindingResult.attr1=" + "org.springframework.validation.BeanPropertyBindingResult: 0 errors, " + - "org.springframework.validation.BindingResult.bean2=" + + "org.springframework.validation.BindingResult.attr3=" + "org.springframework.validation.BeanPropertyBindingResult: 0 errors" + "}"); }