Properly handle Flux<?> and Flux<Object> in WebFlux

Issue: SPR-15464
This commit is contained in:
Rossen Stoyanchev
2017-04-20 08:40:15 -04:00
parent a93698487e
commit cc102c2fcd
22 changed files with 72 additions and 37 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,7 +24,6 @@ import reactor.core.publisher.Mono;
import org.springframework.core.MethodParameter;
import org.springframework.core.ReactiveAdapter;
import org.springframework.core.ReactiveAdapterRegistry;
import org.springframework.core.ResolvableType;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
@@ -79,16 +78,15 @@ public class ResponseEntityResultHandler extends AbstractMessageWriterResultHand
@Override
public boolean supports(HandlerResult result) {
if (isSupportedType(result.getReturnType())) {
if (isSupportedType(result.getReturnType().getRawClass())) {
return true;
}
ReactiveAdapter adapter = getAdapter(result);
return adapter != null && !adapter.isNoValue() &&
isSupportedType(result.getReturnType().getGeneric(0));
isSupportedType(result.getReturnType().getGeneric(0).resolve(Object.class));
}
private boolean isSupportedType(ResolvableType type) {
Class<?> clazz = type.getRawClass();
private boolean isSupportedType(Class<?> clazz) {
return (HttpEntity.class.isAssignableFrom(clazz) && !RequestEntity.class.isAssignableFrom(clazz));
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -156,7 +156,7 @@ public class ViewResolutionResultHandler extends HandlerResultHandlerSupport
if (adapter.isNoValue()) {
return true;
}
type = result.getReturnType().getGeneric(0).getRawClass();
type = result.getReturnType().getGeneric(0).resolve(Object.class);
}
return (CharSequence.class.isAssignableFrom(type) || Rendering.class.isAssignableFrom(type) ||
Model.class.isAssignableFrom(type) || Map.class.isAssignableFrom(type) ||

View File

@@ -29,6 +29,7 @@ import java.util.concurrent.CompletableFuture;
import org.junit.Before;
import org.junit.Test;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
import rx.Completable;
@@ -132,6 +133,10 @@ public class ResponseEntityResultHandlerTests {
returnType = on(TestController.class).resolveReturnType(Completable.class);
assertFalse(this.resultHandler.supports(handlerResult(value, returnType)));
// SPR-15464
returnType = on(TestController.class).resolveReturnType(Flux.class);
assertFalse(this.resultHandler.supports(handlerResult(value, returnType)));
}
@Test
@@ -381,6 +386,7 @@ public class ResponseEntityResultHandlerTests {
Mono<ResponseEntity<?>> monoResponseEntityWildcard() { return null; }
Flux<?> fluxWildcard() { return null; }
}
}

View File

@@ -97,6 +97,9 @@ public class ViewResolutionResultHandlerTests {
testSupports(on(Handler.class).annotPresent(ModelAttribute.class).resolveReturnType(Long.class));
testDoesNotSupport(on(Handler.class).annotNotPresent(ModelAttribute.class).resolveReturnType(Long.class));
// SPR-15464
testSupports(on(Handler.class).resolveReturnType(Mono.class));
}
private void testSupports(MethodParameter returnType) {
@@ -427,6 +430,7 @@ public class ViewResolutionResultHandlerTests {
Long longValue() { return null; }
@ModelAttribute("myLong") Long longModelAttribute() { return null; }
Mono<?> monoWildcard() { return null; }
}
}