HandlerResult now requires MethodParameter as input
HandlerAdapter's should always be able to provide a MethodParameter which in turn ensures that HandlerResultHandler's have full type information from method declarations. This commit also introduces ResolvableMethod for use in tests to make it easy to obtain MethodParameter return types. Issue: #128
This commit is contained in:
parent
dffd6d674a
commit
fb2e796048
|
@ -21,6 +21,7 @@ import java.util.function.Function;
|
|||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.ui.ExtendedModelMap;
|
||||
import org.springframework.ui.ModelMap;
|
||||
|
@ -35,6 +36,7 @@ public class HandlerResult {
|
|||
|
||||
private final Object handler;
|
||||
|
||||
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
|
||||
private final Optional<Object> returnValue;
|
||||
|
||||
private final ResolvableType returnType;
|
||||
|
@ -50,7 +52,7 @@ public class HandlerResult {
|
|||
* @param returnValue the return value from the handler possibly {@code null}
|
||||
* @param returnType the return value type
|
||||
*/
|
||||
public HandlerResult(Object handler, Object returnValue, ResolvableType returnType) {
|
||||
public HandlerResult(Object handler, Object returnValue, MethodParameter returnType) {
|
||||
this(handler, returnValue, returnType, null);
|
||||
}
|
||||
|
||||
|
@ -61,12 +63,12 @@ public class HandlerResult {
|
|||
* @param returnType the return value type
|
||||
* @param model the model used for request handling
|
||||
*/
|
||||
public HandlerResult(Object handler, Object returnValue, ResolvableType returnType, ModelMap model) {
|
||||
public HandlerResult(Object handler, Object returnValue, MethodParameter returnType, ModelMap model) {
|
||||
Assert.notNull(handler, "'handler' is required");
|
||||
Assert.notNull(returnType, "'returnType' is required");
|
||||
this.handler = handler;
|
||||
this.returnValue = Optional.ofNullable(returnValue);
|
||||
this.returnType = returnType;
|
||||
this.returnType = ResolvableType.forMethodParameter(returnType);
|
||||
this.model = (model != null ? model : new ExtendedModelMap());
|
||||
}
|
||||
|
||||
|
@ -92,6 +94,14 @@ public class HandlerResult {
|
|||
return this.returnType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the {@link MethodParameter} from which
|
||||
* {@link #getReturnType() returnType} was created.
|
||||
*/
|
||||
public MethodParameter getReturnTypeSource() {
|
||||
return (MethodParameter) this.returnType.getSource();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the model used during request handling with attributes that may be
|
||||
* used to render HTML templates with.
|
||||
|
|
|
@ -16,14 +16,16 @@
|
|||
|
||||
package org.springframework.web.reactive.result;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.web.reactive.DispatcherHandler;
|
||||
import org.springframework.web.reactive.HandlerAdapter;
|
||||
import org.springframework.web.reactive.HandlerResult;
|
||||
import org.springframework.web.server.WebHandler;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.WebHandler;
|
||||
|
||||
/**
|
||||
* HandlerAdapter that allows using the plain {@link WebHandler} contract with
|
||||
|
@ -34,8 +36,18 @@ import org.springframework.web.server.ServerWebExchange;
|
|||
*/
|
||||
public class SimpleHandlerAdapter implements HandlerAdapter {
|
||||
|
||||
private static final ResolvableType MONO_VOID = ResolvableType.forClassWithGenerics(
|
||||
Mono.class, Void.class);
|
||||
private static final MethodParameter RETURN_TYPE;
|
||||
|
||||
static {
|
||||
try {
|
||||
Method method = WebHandler.class.getMethod("handle", ServerWebExchange.class);
|
||||
RETURN_TYPE = new MethodParameter(method, -1);
|
||||
}
|
||||
catch (NoSuchMethodException ex) {
|
||||
throw new IllegalStateException(
|
||||
"Failed to initialize the return type for WebHandler: " + ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
|
@ -47,7 +59,7 @@ public class SimpleHandlerAdapter implements HandlerAdapter {
|
|||
public Mono<HandlerResult> handle(ServerWebExchange exchange, Object handler) {
|
||||
WebHandler webHandler = (WebHandler) handler;
|
||||
Mono<Void> mono = webHandler.handle(exchange);
|
||||
return Mono.just(new HandlerResult(webHandler, mono, MONO_VOID));
|
||||
return Mono.just(new HandlerResult(webHandler, mono, RETURN_TYPE));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -31,7 +31,6 @@ import org.springframework.core.DefaultParameterNameDiscoverer;
|
|||
import org.springframework.core.GenericTypeResolver;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ParameterNameDiscoverer;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
@ -90,8 +89,7 @@ public class InvocableHandlerMethod extends HandlerMethod {
|
|||
return resolveArguments(exchange, model, providedArgs).then(args -> {
|
||||
try {
|
||||
Object value = doInvoke(args);
|
||||
ResolvableType type = ResolvableType.forMethodParameter(getReturnType());
|
||||
HandlerResult handlerResult = new HandlerResult(this, value, type, model);
|
||||
HandlerResult handlerResult = new HandlerResult(this, value, getReturnType(), model);
|
||||
return Mono.just(handlerResult);
|
||||
}
|
||||
catch (InvocationTargetException ex) {
|
||||
|
|
|
@ -86,13 +86,8 @@ public class ResponseBodyResultHandler extends AbstractMessageConverterResultHan
|
|||
@Override
|
||||
public boolean supports(HandlerResult result) {
|
||||
ResolvableType returnType = result.getReturnType();
|
||||
if (returnType.getSource() instanceof MethodParameter) {
|
||||
MethodParameter parameter = (MethodParameter) returnType.getSource();
|
||||
if (hasResponseBodyAnnotation(parameter) && !isHttpEntityType(returnType)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
MethodParameter parameter = result.getReturnTypeSource();
|
||||
return hasResponseBodyAnnotation(parameter) && !isHttpEntityType(returnType);
|
||||
}
|
||||
|
||||
private boolean hasResponseBodyAnnotation(MethodParameter parameter) {
|
||||
|
|
|
@ -38,7 +38,6 @@ import org.springframework.http.MediaType;
|
|||
import org.springframework.ui.Model;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
import org.springframework.web.reactive.HandlerResult;
|
||||
import org.springframework.web.reactive.HandlerResultHandler;
|
||||
import org.springframework.web.reactive.accept.HeaderContentTypeResolver;
|
||||
|
@ -151,13 +150,8 @@ public class ViewResolutionResultHandler extends ContentNegotiatingResultHandler
|
|||
}
|
||||
|
||||
private boolean hasModelAttributeAnnotation(HandlerResult result) {
|
||||
if (result.getHandler() instanceof HandlerMethod) {
|
||||
MethodParameter returnType = ((HandlerMethod) result.getHandler()).getReturnType();
|
||||
if (returnType.hasMethodAnnotation(ModelAttribute.class)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
MethodParameter returnType = result.getReturnTypeSource();
|
||||
return returnType.hasMethodAnnotation(ModelAttribute.class);
|
||||
}
|
||||
|
||||
private boolean isSupportedType(Class<?> clazz) {
|
||||
|
@ -263,14 +257,11 @@ public class ViewResolutionResultHandler extends ContentNegotiatingResultHandler
|
|||
//noinspection unchecked
|
||||
result.getModel().addAllAttributes((Map<String, ?>) value);
|
||||
}
|
||||
else if (result.getHandler() instanceof HandlerMethod) {
|
||||
MethodParameter returnType = ((HandlerMethod) result.getHandler()).getReturnType();
|
||||
else {
|
||||
MethodParameter returnType = result.getReturnTypeSource();
|
||||
String name = getNameForReturnValue(value, returnType);
|
||||
result.getModel().addAttribute(name, value);
|
||||
}
|
||||
else {
|
||||
result.getModel().addAttribute(value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,141 @@
|
|||
/*
|
||||
* Copyright 2002-2016 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.web.reactive.result;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.core.MethodIntrospector;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
* Convenience class for use in tests to resolve a {@link Method} and/or any of
|
||||
* its {@link MethodParameter}s based on some hints.
|
||||
*
|
||||
* <p>In tests we often create a class (e.g. TestController) with diverse method
|
||||
* signatures and annotations to test with. Use of descriptive method and argument
|
||||
* names combined with using reflection, it becomes challenging to read and write
|
||||
* tests and it becomes necessary to navigate to the actual method declaration
|
||||
* which is cumbersome and involves several steps.
|
||||
*
|
||||
* <p>The idea here is to provide enough hints to resolving a method uniquely
|
||||
* where the hints document exactly what is being tested and there is usually no
|
||||
* need to navigate to the actual method declaration. For example if testing
|
||||
* response handling, the return type may be used as a hint:
|
||||
*
|
||||
* <pre>
|
||||
* ResolvableMethod resolvableMethod = ResolvableMethod.on(TestController.class);
|
||||
|
||||
* ResolvableType type = ResolvableType.forClassWithGenerics(Mono.class, View.class);
|
||||
* Method method = resolvableMethod.returning(type).resolve();
|
||||
*
|
||||
* type = ResolvableType.forClassWithGenerics(Mono.class, String.class);
|
||||
* method = resolvableMethod.returning(type).resolve();
|
||||
*
|
||||
* // ...
|
||||
* </pre>
|
||||
*
|
||||
* <p>Additional {@code resolve} methods provide options to obtain one of the method
|
||||
* arguments or return type as a {@link MethodParameter}.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class ResolvableMethod {
|
||||
|
||||
private final Class<?> targetClass;
|
||||
|
||||
private String methodName;
|
||||
|
||||
private ResolvableType returnType;
|
||||
|
||||
private final List<Class<? extends Annotation>> annotationTypes = new ArrayList<>(4);
|
||||
|
||||
|
||||
private ResolvableMethod(Class<?> targetClass) {
|
||||
this.targetClass = targetClass;
|
||||
}
|
||||
|
||||
|
||||
public ResolvableMethod name(String methodName) {
|
||||
this.methodName = methodName;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ResolvableMethod returning(ResolvableType resolvableType) {
|
||||
this.returnType = resolvableType;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ResolvableMethod annotated(Class<? extends Annotation> annotationType) {
|
||||
this.annotationTypes.add(annotationType);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public Method resolve() {
|
||||
// String comparison (ResolvableType's with different providers)
|
||||
String expected = this.returnType != null ? this.returnType.toString() : null;
|
||||
|
||||
Set<Method> methods = MethodIntrospector.selectMethods(this.targetClass,
|
||||
(ReflectionUtils.MethodFilter) method -> {
|
||||
String actual = ResolvableType.forMethodReturnType(method).toString();
|
||||
if (this.methodName != null && !this.methodName.equals(method.getName())) {
|
||||
return false;
|
||||
}
|
||||
if (expected != null) {
|
||||
if (!actual.equals(expected) && !Object.class.equals(method.getDeclaringClass())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (Class<? extends Annotation> annotationType : this.annotationTypes) {
|
||||
if (AnnotationUtils.findAnnotation(method, annotationType) == null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
Assert.isTrue(!methods.isEmpty(), "No matching method: " + this);
|
||||
Assert.isTrue(methods.size() == 1, "Multiple matching methods: " + this);
|
||||
|
||||
return methods.iterator().next();
|
||||
}
|
||||
|
||||
public MethodParameter resolveReturnType() {
|
||||
Method method = resolve();
|
||||
return new MethodParameter(method, -1);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Class=" + this.targetClass + ", name= " + this.methodName +
|
||||
", returnType=" + this.returnType + ", annotations=" + this.annotationTypes;
|
||||
}
|
||||
|
||||
|
||||
public static ResolvableMethod on(Class<?> clazz) {
|
||||
return new ResolvableMethod(clazz);
|
||||
}
|
||||
|
||||
}
|
|
@ -18,21 +18,21 @@ package org.springframework.web.reactive.result;
|
|||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.reactivestreams.Publisher;
|
||||
import reactor.core.publisher.Flux;
|
||||
import rx.Observable;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.convert.support.GenericConversionService;
|
||||
import org.springframework.core.convert.support.MonoToCompletableFutureConverter;
|
||||
import org.springframework.core.convert.support.PublisherToFluxConverter;
|
||||
import org.springframework.core.convert.support.ReactorToRxJava1Converter;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
import org.springframework.web.reactive.HandlerResult;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link SimpleResultHandler}.
|
||||
|
@ -41,72 +41,55 @@ import static org.junit.Assert.assertTrue;
|
|||
*/
|
||||
public class SimpleResultHandlerTests {
|
||||
|
||||
@Test
|
||||
public void supportsWithConversionService() throws NoSuchMethodException {
|
||||
private SimpleResultHandler resultHandler;
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
GenericConversionService conversionService = new GenericConversionService();
|
||||
conversionService.addConverter(new MonoToCompletableFutureConverter());
|
||||
conversionService.addConverter(new PublisherToFluxConverter());
|
||||
conversionService.addConverter(new ReactorToRxJava1Converter());
|
||||
|
||||
SimpleResultHandler resultHandler = new SimpleResultHandler(conversionService);
|
||||
TestController controller = new TestController();
|
||||
|
||||
HandlerMethod hm = new HandlerMethod(controller, TestController.class.getMethod("voidReturnValue"));
|
||||
ResolvableType type = ResolvableType.forMethodParameter(hm.getReturnType());
|
||||
assertTrue(resultHandler.supports(createHandlerResult(hm, type)));
|
||||
|
||||
hm = new HandlerMethod(controller, TestController.class.getMethod("publisherString"));
|
||||
type = ResolvableType.forMethodParameter(hm.getReturnType());
|
||||
assertFalse(resultHandler.supports(createHandlerResult(hm, type)));
|
||||
|
||||
hm = new HandlerMethod(controller, TestController.class.getMethod("publisherVoid"));
|
||||
type = ResolvableType.forMethodParameter(hm.getReturnType());
|
||||
assertTrue(resultHandler.supports(createHandlerResult(hm, type)));
|
||||
|
||||
hm = new HandlerMethod(controller, TestController.class.getMethod("streamVoid"));
|
||||
type = ResolvableType.forMethodParameter(hm.getReturnType());
|
||||
assertTrue(resultHandler.supports(createHandlerResult(hm, type)));
|
||||
|
||||
hm = new HandlerMethod(controller, TestController.class.getMethod("observableVoid"));
|
||||
type = ResolvableType.forMethodParameter(hm.getReturnType());
|
||||
assertTrue(resultHandler.supports(createHandlerResult(hm, type)));
|
||||
|
||||
hm = new HandlerMethod(controller, TestController.class.getMethod("completableFutureVoid"));
|
||||
type = ResolvableType.forMethodParameter(hm.getReturnType());
|
||||
assertTrue(resultHandler.supports(createHandlerResult(hm, type)));
|
||||
this.resultHandler = new SimpleResultHandler(conversionService);
|
||||
}
|
||||
|
||||
private HandlerResult createHandlerResult(HandlerMethod hm, ResolvableType type) {
|
||||
return new HandlerResult(hm, null, type);
|
||||
|
||||
@Test
|
||||
public void supportsWithConversionService() throws NoSuchMethodException {
|
||||
testSupports(ResolvableType.forClass(void.class), true);
|
||||
testSupports(ResolvableType.forClassWithGenerics(Publisher.class, Void.class), true);
|
||||
testSupports(ResolvableType.forClassWithGenerics(Flux.class, Void.class), true);
|
||||
testSupports(ResolvableType.forClassWithGenerics(Observable.class, Void.class), true);
|
||||
testSupports(ResolvableType.forClassWithGenerics(CompletableFuture.class, Void.class), true);
|
||||
|
||||
testSupports(ResolvableType.forClass(String.class), false);
|
||||
testSupports(ResolvableType.forClassWithGenerics(Publisher.class, String.class), false);
|
||||
}
|
||||
|
||||
private void testSupports(ResolvableType type, boolean result) {
|
||||
MethodParameter param = ResolvableMethod.on(TestController.class).returning(type).resolveReturnType();
|
||||
HandlerResult handlerResult = new HandlerResult(new TestController(), null, param);
|
||||
assertEquals(result, this.resultHandler.supports(handlerResult));
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static class TestController {
|
||||
|
||||
public void voidReturnValue() {
|
||||
}
|
||||
public void voidReturn() { }
|
||||
|
||||
public Publisher<String> publisherString() {
|
||||
return null;
|
||||
}
|
||||
public Publisher<String> publisherString() { return null; }
|
||||
|
||||
public Publisher<Void> publisherVoid() {
|
||||
return null;
|
||||
}
|
||||
public Flux<Void> flux() { return null; }
|
||||
|
||||
public Flux<Void> streamVoid() {
|
||||
return null;
|
||||
}
|
||||
public Observable<Void> observable() { return null; }
|
||||
|
||||
public Observable<Void> observableVoid() {
|
||||
return null;
|
||||
}
|
||||
public CompletableFuture<Void> completableFuture() { return null; }
|
||||
|
||||
public String string() { return null; }
|
||||
|
||||
public Publisher<Void> publisher() { return null; }
|
||||
|
||||
public CompletableFuture<Void> completableFutureVoid() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -25,7 +25,6 @@ import org.junit.Before;
|
|||
import org.junit.Test;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.codec.ByteBufferEncoder;
|
||||
import org.springframework.core.codec.StringEncoder;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
|
@ -123,8 +122,7 @@ public class ResponseBodyResultHandlerTests {
|
|||
|
||||
private void testSupports(Object controller, String method, boolean result) throws NoSuchMethodException {
|
||||
HandlerMethod hm = handlerMethod(controller, method);
|
||||
ResolvableType type = ResolvableType.forMethodParameter(hm.getReturnType());
|
||||
HandlerResult handlerResult = new HandlerResult(hm, null, type, new ExtendedModelMap());
|
||||
HandlerResult handlerResult = new HandlerResult(hm, null, hm.getReturnType(), new ExtendedModelMap());
|
||||
assertEquals(result, this.resultHandler.supports(handlerResult));
|
||||
}
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@ import reactor.core.publisher.Mono;
|
|||
import reactor.core.test.TestSubscriber;
|
||||
import rx.Single;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.codec.ByteBufferEncoder;
|
||||
import org.springframework.core.codec.StringEncoder;
|
||||
|
@ -48,12 +49,11 @@ import org.springframework.http.converter.reactive.ResourceHttpMessageConverter;
|
|||
import org.springframework.http.server.reactive.MockServerHttpRequest;
|
||||
import org.springframework.http.server.reactive.MockServerHttpResponse;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.ui.ExtendedModelMap;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.web.reactive.HandlerResult;
|
||||
import org.springframework.web.reactive.accept.RequestedContentTypeResolver;
|
||||
import org.springframework.web.reactive.accept.RequestedContentTypeResolverBuilder;
|
||||
import org.springframework.web.reactive.result.ResolvableMethod;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.adapter.DefaultServerWebExchange;
|
||||
import org.springframework.web.server.session.MockWebSessionManager;
|
||||
|
@ -75,9 +75,6 @@ import static org.springframework.core.ResolvableType.forClassWithGenerics;
|
|||
*/
|
||||
public class ResponseEntityResultHandlerTests {
|
||||
|
||||
private static final Object HANDLER = new Object();
|
||||
|
||||
|
||||
private ResponseEntityResultHandler resultHandler;
|
||||
|
||||
private MockServerHttpResponse response = new MockServerHttpResponse();
|
||||
|
@ -119,23 +116,22 @@ public class ResponseEntityResultHandlerTests {
|
|||
|
||||
@Test @SuppressWarnings("ConstantConditions")
|
||||
public void supports() throws NoSuchMethodException {
|
||||
ModelMap model = new ExtendedModelMap();
|
||||
|
||||
Object value = null;
|
||||
ResolvableType type = responseEntityType(String.class);
|
||||
assertTrue(this.resultHandler.supports(new HandlerResult(HANDLER, value, type, model)));
|
||||
ResolvableType type = responseEntity(String.class);
|
||||
assertTrue(this.resultHandler.supports(handlerResult(value, type)));
|
||||
|
||||
type = forClassWithGenerics(Mono.class, responseEntityType(String.class));
|
||||
assertTrue(this.resultHandler.supports(new HandlerResult(HANDLER, value, type, model)));
|
||||
type = classWithGenerics(Mono.class, responseEntity(String.class));
|
||||
assertTrue(this.resultHandler.supports(handlerResult(value, type)));
|
||||
|
||||
type = forClassWithGenerics(Single.class, responseEntityType(String.class));
|
||||
assertTrue(this.resultHandler.supports(new HandlerResult(HANDLER, value, type, model)));
|
||||
type = classWithGenerics(Single.class, responseEntity(String.class));
|
||||
assertTrue(this.resultHandler.supports(handlerResult(value, type)));
|
||||
|
||||
type = forClassWithGenerics(CompletableFuture.class, responseEntityType(String.class));
|
||||
assertTrue(this.resultHandler.supports(new HandlerResult(HANDLER, value, type, model)));
|
||||
type = classWithGenerics(CompletableFuture.class, responseEntity(String.class));
|
||||
assertTrue(this.resultHandler.supports(handlerResult(value, type)));
|
||||
|
||||
type = ResolvableType.forClass(String.class);
|
||||
assertFalse(this.resultHandler.supports(new HandlerResult(HANDLER, value, type, model)));
|
||||
assertFalse(this.resultHandler.supports(handlerResult(value, type)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -145,8 +141,9 @@ public class ResponseEntityResultHandlerTests {
|
|||
|
||||
@Test
|
||||
public void statusCode() throws Exception {
|
||||
ResolvableType type = responseEntityType(Void.class);
|
||||
HandlerResult result = new HandlerResult(HANDLER, ResponseEntity.noContent().build(), type);
|
||||
ResponseEntity<Void> value = ResponseEntity.noContent().build();
|
||||
ResolvableType type = responseEntity(Void.class);
|
||||
HandlerResult result = handlerResult(value, type);
|
||||
this.resultHandler.handleResult(exchange, result).block(Duration.ofSeconds(5));
|
||||
|
||||
assertEquals(HttpStatus.NO_CONTENT, this.response.getStatus());
|
||||
|
@ -157,8 +154,9 @@ public class ResponseEntityResultHandlerTests {
|
|||
@Test
|
||||
public void headers() throws Exception {
|
||||
URI location = new URI("/path");
|
||||
ResolvableType type = responseEntityType(Void.class);
|
||||
HandlerResult result = new HandlerResult(HANDLER, ResponseEntity.created(location).build(), type);
|
||||
ResolvableType type = responseEntity(Void.class);
|
||||
ResponseEntity<Void> value = ResponseEntity.created(location).build();
|
||||
HandlerResult result = handlerResult(value, type);
|
||||
this.resultHandler.handleResult(this.exchange, result).block(Duration.ofSeconds(5));
|
||||
|
||||
assertEquals(HttpStatus.CREATED, this.response.getStatus());
|
||||
|
@ -170,25 +168,25 @@ public class ResponseEntityResultHandlerTests {
|
|||
@Test
|
||||
public void handleReturnTypes() throws Exception {
|
||||
Object returnValue = ResponseEntity.ok("abc");
|
||||
ResolvableType returnType = responseEntityType(String.class);
|
||||
ResolvableType returnType = responseEntity(String.class);
|
||||
testHandle(returnValue, returnType);
|
||||
|
||||
returnValue = Mono.just(ResponseEntity.ok("abc"));
|
||||
returnType = forClassWithGenerics(Mono.class, responseEntityType(String.class));
|
||||
returnType = forClassWithGenerics(Mono.class, responseEntity(String.class));
|
||||
testHandle(returnValue, returnType);
|
||||
|
||||
returnValue = Mono.just(ResponseEntity.ok("abc"));
|
||||
returnType = forClassWithGenerics(Single.class, responseEntityType(String.class));
|
||||
returnType = forClassWithGenerics(Single.class, responseEntity(String.class));
|
||||
testHandle(returnValue, returnType);
|
||||
|
||||
returnValue = Mono.just(ResponseEntity.ok("abc"));
|
||||
returnType = forClassWithGenerics(CompletableFuture.class, responseEntityType(String.class));
|
||||
returnType = forClassWithGenerics(CompletableFuture.class, responseEntity(String.class));
|
||||
testHandle(returnValue, returnType);
|
||||
}
|
||||
|
||||
|
||||
private void testHandle(Object returnValue, ResolvableType returnType) {
|
||||
HandlerResult result = new HandlerResult(HANDLER, returnValue, returnType);
|
||||
private void testHandle(Object returnValue, ResolvableType type) {
|
||||
HandlerResult result = handlerResult(returnValue, type);
|
||||
this.resultHandler.handleResult(this.exchange, result).block(Duration.ofSeconds(5));
|
||||
|
||||
assertEquals(HttpStatus.OK, this.response.getStatus());
|
||||
|
@ -197,8 +195,17 @@ public class ResponseEntityResultHandlerTests {
|
|||
}
|
||||
|
||||
|
||||
private ResolvableType responseEntityType(Class<?> bodyType) {
|
||||
return forClassWithGenerics(ResponseEntity.class, bodyType);
|
||||
private ResolvableType responseEntity(Class<?> bodyType) {
|
||||
return classWithGenerics(ResponseEntity.class, ResolvableType.forClass(bodyType));
|
||||
}
|
||||
|
||||
private ResolvableType classWithGenerics(Class<?> sourceType, ResolvableType genericType) {
|
||||
return ResolvableType.forClassWithGenerics(sourceType, genericType);
|
||||
}
|
||||
|
||||
private HandlerResult handlerResult(Object returnValue, ResolvableType type) {
|
||||
MethodParameter param = ResolvableMethod.on(TestController.class).returning(type).resolveReturnType();
|
||||
return new HandlerResult(new TestController(), returnValue, param);
|
||||
}
|
||||
|
||||
private void assertResponseBody(String responseBody) {
|
||||
|
@ -207,4 +214,21 @@ public class ResponseEntityResultHandlerTests {
|
|||
DataBufferTestUtils.dumpString(buf, Charset.forName("UTF-8"))));
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static class TestController {
|
||||
|
||||
ResponseEntity<String> responseEntityString() { return null; }
|
||||
|
||||
ResponseEntity<Void> responseEntityVoid() { return null; }
|
||||
|
||||
Mono<ResponseEntity<String>> mono() { return null; }
|
||||
|
||||
Single<ResponseEntity<String>> single() { return null; }
|
||||
|
||||
CompletableFuture<ResponseEntity<String>> completableFuture() { return null; }
|
||||
|
||||
String string() { return null; }
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -31,19 +31,20 @@ import org.junit.Before;
|
|||
import org.junit.Test;
|
||||
import reactor.core.test.TestSubscriber;
|
||||
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.http.codec.json.JacksonJsonEncoder;
|
||||
import org.springframework.http.codec.xml.Jaxb2Encoder;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.codec.StringEncoder;
|
||||
import org.springframework.core.io.buffer.support.DataBufferTestUtils;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.codec.json.JacksonJsonEncoder;
|
||||
import org.springframework.http.codec.xml.Jaxb2Encoder;
|
||||
import org.springframework.http.server.reactive.MockServerHttpRequest;
|
||||
import org.springframework.http.server.reactive.MockServerHttpResponse;
|
||||
import org.springframework.ui.ExtendedModelMap;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.util.MimeType;
|
||||
import org.springframework.web.reactive.HandlerResult;
|
||||
import org.springframework.web.reactive.result.ResolvableMethod;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.adapter.DefaultServerWebExchange;
|
||||
import org.springframework.web.server.session.DefaultWebSessionManager;
|
||||
|
@ -62,18 +63,17 @@ import static org.junit.Assert.fail;
|
|||
*/
|
||||
public class HttpMessageConverterViewTests {
|
||||
|
||||
private HttpMessageConverterView view;
|
||||
private HttpMessageConverterView view = new HttpMessageConverterView(new JacksonJsonEncoder());
|
||||
|
||||
private HandlerResult result;
|
||||
|
||||
private ModelMap model;
|
||||
private ModelMap model = new ExtendedModelMap();
|
||||
|
||||
|
||||
@Before
|
||||
public void setup() throws Exception {
|
||||
this.view = new HttpMessageConverterView(new JacksonJsonEncoder());
|
||||
this.model = new ExtendedModelMap();
|
||||
this.result = new HandlerResult(new Object(), null, ResolvableType.NONE, model);
|
||||
MethodParameter param = ResolvableMethod.on(this.getClass()).name("handle").resolveReturnType();
|
||||
this.result = new HandlerResult(this, null, param, this.model);
|
||||
}
|
||||
|
||||
|
||||
|
@ -176,4 +176,9 @@ public class HttpMessageConverterViewTests {
|
|||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private String handle() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -19,11 +19,9 @@ import java.util.Locale;
|
|||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.context.support.StaticApplicationContext;
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
|
|
@ -35,6 +35,7 @@ import reactor.core.publisher.Mono;
|
|||
import reactor.core.test.TestSubscriber;
|
||||
import rx.Single;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.convert.support.ConfigurableConversionService;
|
||||
|
@ -49,13 +50,12 @@ import org.springframework.http.MediaType;
|
|||
import org.springframework.http.server.reactive.MockServerHttpRequest;
|
||||
import org.springframework.http.server.reactive.MockServerHttpResponse;
|
||||
import org.springframework.http.server.reactive.ServerHttpResponse;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ExtendedModelMap;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
import org.springframework.web.reactive.HandlerResult;
|
||||
import org.springframework.web.reactive.result.ResolvableMethod;
|
||||
import org.springframework.web.server.NotAcceptableStatusException;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.adapter.DefaultServerWebExchange;
|
||||
|
@ -90,26 +90,19 @@ public class ViewResolutionResultHandlerTests {
|
|||
|
||||
@Test
|
||||
public void supports() throws Exception {
|
||||
Object handler = new Object();
|
||||
HandlerMethod hm = handlerMethod(new TestController(), "modelAttributeMethod");
|
||||
|
||||
testSupports(handler, ResolvableType.forClass(String.class), true);
|
||||
testSupports(handler, ResolvableType.forClass(View.class), true);
|
||||
testSupports(handler, ResolvableType.forClassWithGenerics(Mono.class, String.class), true);
|
||||
testSupports(handler, ResolvableType.forClassWithGenerics(Mono.class, View.class), true);
|
||||
testSupports(handler, ResolvableType.forClassWithGenerics(Single.class, String.class), true);
|
||||
testSupports(handler, ResolvableType.forClassWithGenerics(Single.class, View.class), true);
|
||||
testSupports(handler, ResolvableType.forClass(Model.class), true);
|
||||
testSupports(handler, ResolvableType.forClass(Map.class), true);
|
||||
testSupports(handler, ResolvableType.forClass(TestBean.class), true);
|
||||
testSupports(handler, ResolvableType.forClass(Integer.class), false);
|
||||
testSupports(hm, ResolvableType.forMethodParameter(hm.getReturnType()), true);
|
||||
}
|
||||
testSupports(ResolvableType.forClass(String.class), true);
|
||||
testSupports(ResolvableType.forClass(View.class), true);
|
||||
testSupports(ResolvableType.forClassWithGenerics(Mono.class, String.class), true);
|
||||
testSupports(ResolvableType.forClassWithGenerics(Mono.class, View.class), true);
|
||||
testSupports(ResolvableType.forClassWithGenerics(Single.class, String.class), true);
|
||||
testSupports(ResolvableType.forClassWithGenerics(Single.class, View.class), true);
|
||||
testSupports(ResolvableType.forClass(Model.class), true);
|
||||
testSupports(ResolvableType.forClass(Map.class), true);
|
||||
testSupports(ResolvableType.forClass(TestBean.class), true);
|
||||
testSupports(ResolvableType.forClass(Integer.class), false);
|
||||
|
||||
private void testSupports(Object handler, ResolvableType returnType, boolean result) {
|
||||
ViewResolutionResultHandler resultHandler = createResultHandler(mock(ViewResolver.class));
|
||||
HandlerResult handlerResult = new HandlerResult(handler, null, returnType, new ExtendedModelMap());
|
||||
assertEquals(result, resultHandler.supports(handlerResult));
|
||||
testSupports(resolvableMethod().annotated(ModelAttribute.class), true);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -125,53 +118,50 @@ public class ViewResolutionResultHandlerTests {
|
|||
|
||||
@Test
|
||||
public void handleReturnValueTypes() throws Exception {
|
||||
Object handler = new Object();
|
||||
Object returnValue;
|
||||
ResolvableType returnType;
|
||||
ViewResolver resolver = new TestViewResolver("account");
|
||||
|
||||
returnValue = new TestView("account");
|
||||
returnType = ResolvableType.forClass(View.class);
|
||||
testHandle("/path", handler, returnValue, returnType, "account: {id=123}");
|
||||
returnValue = new TestView("account");
|
||||
testHandle("/path", returnType, returnValue, "account: {id=123}");
|
||||
|
||||
returnValue = Mono.just(new TestView("account"));
|
||||
returnType = ResolvableType.forClassWithGenerics(Mono.class, View.class);
|
||||
testHandle("/path", handler, returnValue, returnType, "account: {id=123}");
|
||||
returnValue = Mono.just(new TestView("account"));
|
||||
testHandle("/path", returnType, returnValue, "account: {id=123}");
|
||||
|
||||
returnValue = "account";
|
||||
returnType = ResolvableType.forClass(String.class);
|
||||
testHandle("/path", handler, returnValue, returnType, "account: {id=123}", resolver);
|
||||
returnValue = "account";
|
||||
testHandle("/path", returnType, returnValue, "account: {id=123}", resolver);
|
||||
|
||||
returnValue = Mono.just("account");
|
||||
returnType = ResolvableType.forClassWithGenerics(Mono.class, String.class);
|
||||
testHandle("/path", handler, returnValue, returnType, "account: {id=123}", resolver);
|
||||
returnValue = Mono.just("account");
|
||||
testHandle("/path", returnType, returnValue, "account: {id=123}", resolver);
|
||||
|
||||
returnValue = new ExtendedModelMap().addAttribute("name", "Joe");
|
||||
returnType = ResolvableType.forClass(Model.class);
|
||||
testHandle("/account", handler, returnValue, returnType, "account: {id=123, name=Joe}", resolver);
|
||||
returnValue = new ExtendedModelMap().addAttribute("name", "Joe");
|
||||
testHandle("/account", returnType, returnValue, "account: {id=123, name=Joe}", resolver);
|
||||
|
||||
returnValue = Collections.singletonMap("name", "Joe");
|
||||
returnType = ResolvableType.forClass(Map.class);
|
||||
testHandle("/account", handler, returnValue, returnType, "account: {id=123, name=Joe}", resolver);
|
||||
returnValue = Collections.singletonMap("name", "Joe");
|
||||
testHandle("/account", returnType, returnValue, "account: {id=123, name=Joe}", resolver);
|
||||
|
||||
HandlerMethod hm = handlerMethod(new TestController(), "modelAttributeMethod");
|
||||
returnValue = "Joe";
|
||||
returnType = ResolvableType.forMethodParameter(hm.getReturnType());
|
||||
testHandle("/account", hm, returnValue, returnType, "account: {id=123, name=Joe}", resolver);
|
||||
|
||||
returnValue = new TestBean("Joe");
|
||||
returnType = ResolvableType.forClass(TestBean.class);
|
||||
testHandle("/account", handler, returnValue, returnType, "account: {id=123, testBean=TestBean[name=Joe]}", resolver);
|
||||
returnValue = new TestBean("Joe");
|
||||
String responseBody = "account: {id=123, testBean=TestBean[name=Joe]}";
|
||||
testHandle("/account", returnType, returnValue, responseBody, resolver);
|
||||
|
||||
testHandle("/account", resolvableMethod().annotated(ModelAttribute.class),
|
||||
99L, "account: {id=123, num=99}", resolver);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handleWithMultipleResolvers() throws Exception {
|
||||
Object handler = new Object();
|
||||
Object returnValue = "profile";
|
||||
ResolvableType returnType = ResolvableType.forClass(String.class);
|
||||
ViewResolver[] resolvers = {new TestViewResolver("account"), new TestViewResolver("profile")};
|
||||
|
||||
testHandle("/account", handler, returnValue, returnType, "profile: {id=123}", resolvers);
|
||||
testHandle("/account", returnType, returnValue, "profile: {id=123}", resolvers);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -180,11 +170,11 @@ public class ViewResolutionResultHandlerTests {
|
|||
testDefaultViewName(Mono.empty(), ResolvableType.forClassWithGenerics(Mono.class, String.class));
|
||||
}
|
||||
|
||||
private void testDefaultViewName(Object returnValue, ResolvableType returnType)
|
||||
private void testDefaultViewName(Object returnValue, ResolvableType type)
|
||||
throws URISyntaxException {
|
||||
|
||||
ModelMap model = new ExtendedModelMap().addAttribute("id", "123");
|
||||
HandlerResult result = new HandlerResult(new Object(), returnValue, returnType, model);
|
||||
HandlerResult result = new HandlerResult(new Object(), returnValue, returnType(type), model);
|
||||
ViewResolutionResultHandler handler = createResultHandler(new TestViewResolver("account"));
|
||||
|
||||
this.request.setUri(new URI("/account"));
|
||||
|
@ -203,9 +193,9 @@ public class ViewResolutionResultHandlerTests {
|
|||
@Test
|
||||
public void unresolvedViewName() throws Exception {
|
||||
String returnValue = "account";
|
||||
ResolvableType returnType = ResolvableType.forClass(String.class);
|
||||
ResolvableType type = ResolvableType.forClass(String.class);
|
||||
ExtendedModelMap model = new ExtendedModelMap();
|
||||
HandlerResult handlerResult = new HandlerResult(new Object(), returnValue, returnType, model);
|
||||
HandlerResult handlerResult = new HandlerResult(new Object(), returnValue, returnType(type), model);
|
||||
|
||||
this.request.setUri(new URI("/path"));
|
||||
Mono<Void> mono = createResultHandler().handleResult(this.exchange, handlerResult);
|
||||
|
@ -217,7 +207,8 @@ public class ViewResolutionResultHandlerTests {
|
|||
public void contentNegotiation() throws Exception {
|
||||
TestBean value = new TestBean("Joe");
|
||||
ResolvableType type = ResolvableType.forClass(TestBean.class);
|
||||
HandlerResult handlerResult = new HandlerResult(new Object(), value, type, new ExtendedModelMap());
|
||||
ExtendedModelMap model = new ExtendedModelMap();
|
||||
HandlerResult handlerResult = new HandlerResult(new Object(), value, returnType(type), model);
|
||||
|
||||
this.request.getHeaders().setAccept(Collections.singletonList(APPLICATION_JSON));
|
||||
this.request.setUri(new URI("/account"));
|
||||
|
@ -236,7 +227,8 @@ public class ViewResolutionResultHandlerTests {
|
|||
public void contentNegotiationWith406() throws Exception {
|
||||
TestBean value = new TestBean("Joe");
|
||||
ResolvableType type = ResolvableType.forClass(TestBean.class);
|
||||
HandlerResult handlerResult = new HandlerResult(new Object(), value, type, new ExtendedModelMap());
|
||||
ExtendedModelMap model = new ExtendedModelMap();
|
||||
HandlerResult handlerResult = new HandlerResult(new Object(), value, returnType(type), model);
|
||||
|
||||
this.request.getHeaders().setAccept(Collections.singletonList(APPLICATION_JSON));
|
||||
this.request.setUri(new URI("/account"));
|
||||
|
@ -247,6 +239,26 @@ public class ViewResolutionResultHandlerTests {
|
|||
}
|
||||
|
||||
|
||||
private MethodParameter returnType(ResolvableType type) {
|
||||
return resolvableMethod().returning(type).resolveReturnType();
|
||||
}
|
||||
|
||||
private ResolvableMethod resolvableMethod() {
|
||||
return ResolvableMethod.on(TestController.class);
|
||||
}
|
||||
|
||||
private void testSupports(ResolvableType type, boolean result) {
|
||||
testSupports(resolvableMethod().returning(type), result);
|
||||
}
|
||||
|
||||
private void testSupports(ResolvableMethod resolvableMethod, boolean result) {
|
||||
ViewResolutionResultHandler resultHandler = createResultHandler(mock(ViewResolver.class));
|
||||
MethodParameter returnType = resolvableMethod.resolveReturnType();
|
||||
ExtendedModelMap model = new ExtendedModelMap();
|
||||
HandlerResult handlerResult = new HandlerResult(new Object(), null, returnType, model);
|
||||
assertEquals(result, resultHandler.supports(handlerResult));
|
||||
}
|
||||
|
||||
private ViewResolutionResultHandler createResultHandler(ViewResolver... resolvers) {
|
||||
return createResultHandler(Collections.emptyList(), resolvers);
|
||||
}
|
||||
|
@ -261,15 +273,18 @@ public class ViewResolutionResultHandlerTests {
|
|||
return handler;
|
||||
}
|
||||
|
||||
private HandlerMethod handlerMethod(Object controller, String method) throws NoSuchMethodException {
|
||||
return new HandlerMethod(controller, controller.getClass().getMethod(method));
|
||||
private void testHandle(String path, ResolvableType returnType, Object returnValue,
|
||||
String responseBody, ViewResolver... resolvers) throws URISyntaxException {
|
||||
|
||||
testHandle(path, resolvableMethod().returning(returnType), returnValue, responseBody, resolvers);
|
||||
}
|
||||
|
||||
private void testHandle(String path, Object handler, Object returnValue, ResolvableType returnType,
|
||||
private void testHandle(String path, ResolvableMethod resolvableMethod, Object returnValue,
|
||||
String responseBody, ViewResolver... resolvers) throws URISyntaxException {
|
||||
|
||||
ModelMap model = new ExtendedModelMap().addAttribute("id", "123");
|
||||
HandlerResult result = new HandlerResult(handler, returnValue, returnType, model);
|
||||
MethodParameter returnType = resolvableMethod.resolveReturnType();
|
||||
HandlerResult result = new HandlerResult(new Object(), returnValue, returnType, model);
|
||||
this.request.setUri(new URI(path));
|
||||
createResultHandler(resolvers).handleResult(this.exchange, result).block(Duration.ofSeconds(5));
|
||||
assertResponseBody(responseBody);
|
||||
|
@ -350,15 +365,6 @@ public class ViewResolutionResultHandlerTests {
|
|||
}
|
||||
}
|
||||
|
||||
@Controller @SuppressWarnings("unused")
|
||||
private static class TestController {
|
||||
|
||||
@ModelAttribute("name")
|
||||
public String modelAttributeMethod() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static class TestBean {
|
||||
|
||||
private final String name;
|
||||
|
@ -377,4 +383,31 @@ public class ViewResolutionResultHandlerTests {
|
|||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static class TestController {
|
||||
|
||||
String string() { return null; }
|
||||
|
||||
View view() { return null; }
|
||||
|
||||
Mono<String> monoString() { return null; }
|
||||
|
||||
Mono<View> monoView() { return null; }
|
||||
|
||||
Single<String> singleString() { return null; }
|
||||
|
||||
Single<View> singleView() { return null; }
|
||||
|
||||
Model model() { return null; }
|
||||
|
||||
Map map() { return null; }
|
||||
|
||||
TestBean testBean() { return null; }
|
||||
|
||||
Integer integer() { return null; }
|
||||
|
||||
@ModelAttribute("num")
|
||||
Long longAttribute() { return null; }
|
||||
}
|
||||
|
||||
}
|
|
@ -29,13 +29,14 @@ import reactor.core.test.TestSubscriber;
|
|||
|
||||
import org.springframework.context.ApplicationContextException;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.server.reactive.MockServerHttpRequest;
|
||||
import org.springframework.http.server.reactive.MockServerHttpResponse;
|
||||
import org.springframework.ui.ExtendedModelMap;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
import org.springframework.web.reactive.HandlerResult;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.adapter.DefaultServerWebExchange;
|
||||
|
@ -125,7 +126,8 @@ public class FreeMarkerViewTests {
|
|||
|
||||
ModelMap model = new ExtendedModelMap();
|
||||
model.addAttribute("hello", "hi FreeMarker");
|
||||
HandlerResult result = new HandlerResult(new Object(), "", ResolvableType.NONE, model);
|
||||
MethodParameter returnType = new MethodParameter(getClass().getDeclaredMethod("handle"), -1);
|
||||
HandlerResult result = new HandlerResult(new Object(), "", returnType, model);
|
||||
view.render(result, null, this.exchange);
|
||||
|
||||
TestSubscriber
|
||||
|
@ -142,4 +144,10 @@ public class FreeMarkerViewTests {
|
|||
return new String(bytes, UTF_8);
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private String handle() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue