diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/HandlerResult.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/HandlerResult.java index 6f4bd8220b..3c211e5644 100644 --- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/HandlerResult.java +++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/HandlerResult.java @@ -44,6 +44,16 @@ public class HandlerResult { private Function> exceptionHandler; + /** + * Create a new {@code HandlerResult}. + * @param handler the handler that handled the request + * @param returnValue the return value from the handler possibly {@code null} + * @param returnValueType the return value type + */ + public HandlerResult(Object handler, Object returnValue, ResolvableType returnValueType) { + this(handler, returnValue, returnValueType, null); + } + /** * Create a new {@code HandlerResult}. * @param handler the handler that handled the request @@ -54,11 +64,10 @@ public class HandlerResult { public HandlerResult(Object handler, Object returnValue, ResolvableType returnValueType, ModelMap model) { Assert.notNull(handler, "'handler' is required"); Assert.notNull(returnValueType, "'returnValueType' is required"); - Assert.notNull(model, "'model' is required"); this.handler = handler; this.returnValue = Optional.ofNullable(returnValue); this.returnValueType = returnValueType; - this.model = model; + this.model = (model != null ? model : new ExtendedModelMap()); } diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/handler/SimpleHandlerResultHandler.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/handler/SimpleResultHandler.java similarity index 58% rename from spring-web-reactive/src/main/java/org/springframework/web/reactive/handler/SimpleHandlerResultHandler.java rename to spring-web-reactive/src/main/java/org/springframework/web/reactive/handler/SimpleResultHandler.java index fc46f9d596..e8b56e4ce1 100644 --- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/handler/SimpleHandlerResultHandler.java +++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/handler/SimpleResultHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * 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. @@ -29,24 +29,28 @@ import org.springframework.web.reactive.HandlerResult; import org.springframework.web.reactive.HandlerResultHandler; import org.springframework.web.server.ServerWebExchange; + /** - * Supports {@link HandlerResult} with a {@code void} or {@code Publisher} value. - * An optional {link ConversionService} can be used to support types that can be converted to - * {@code Publisher}, like {@code Observable} or {@code CompletableFuture}. + * A simple handler for return values of type {@code void}, or + * {@code Publisher}, or if a {link ConversionService} is provided, also + * of any other async return value types that can be converted to + * {@code Publisher} such as {@code Observable} or + * {@code CompletableFuture}. * * @author Sebastien Deleuze + * @author Rossen Stoyanchev */ -public class SimpleHandlerResultHandler implements Ordered, HandlerResultHandler { +public class SimpleResultHandler implements Ordered, HandlerResultHandler { private int order = Ordered.LOWEST_PRECEDENCE; private ConversionService conversionService; - public SimpleHandlerResultHandler() { + public SimpleResultHandler() { } - public SimpleHandlerResultHandler(ConversionService conversionService) { + public SimpleResultHandler(ConversionService conversionService) { Assert.notNull(conversionService, "'conversionService' is required."); this.conversionService = conversionService; } @@ -61,30 +65,36 @@ public class SimpleHandlerResultHandler implements Ordered, HandlerResultHandler return this.order; } + @Override public boolean supports(HandlerResult result) { ResolvableType type = result.getReturnValueType(); - return (type != null && Void.TYPE.equals(type.getRawClass()) || - (isConvertibleToPublisher(type) && Void.class.isAssignableFrom(type.getGeneric(0).getRawClass()))); + return (type != null && (Void.TYPE.equals(type.getRawClass()) || isConvertibleToVoidPublisher(type))); + } + + private boolean isConvertibleToVoidPublisher(ResolvableType type) { + return (isConvertibleToPublisher(type) && + Void.class.isAssignableFrom(type.getGeneric(0).getRawClass())); } private boolean isConvertibleToPublisher(ResolvableType type) { - return Publisher.class.isAssignableFrom(type.getRawClass()) || - ((this.conversionService != null) && - this.conversionService.canConvert(type.getRawClass(), Publisher.class)); + Class clazz = type.getRawClass(); + return (Publisher.class.isAssignableFrom(clazz) || + ((this.conversionService != null) && this.conversionService.canConvert(clazz, Publisher.class))); } @SuppressWarnings("unchecked") @Override public Mono handleResult(ServerWebExchange exchange, HandlerResult result) { - Optional value = result.getReturnValue(); - if (!value.isPresent() || Void.TYPE.equals(result.getReturnValueType().getRawClass())) { + Optional optional = result.getReturnValue(); + if (!optional.isPresent()) { return Mono.empty(); } - if (value.get() instanceof Mono) { - return (Mono) value.get(); + Object returnValue = optional.get(); + if (returnValue instanceof Mono) { + return (Mono) returnValue; } - return Mono.from(this.conversionService.convert(value.get(), Publisher.class)); + return Mono.from(this.conversionService.convert(returnValue, Publisher.class)); } } diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/handler/HttpHandlerHandlerAdapter.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/handler/WebHandlerHandlerAdapter.java similarity index 81% rename from spring-web-reactive/src/main/java/org/springframework/web/reactive/handler/HttpHandlerHandlerAdapter.java rename to spring-web-reactive/src/main/java/org/springframework/web/reactive/handler/WebHandlerHandlerAdapter.java index 67cc1fc2cc..1dfec138e9 100644 --- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/handler/HttpHandlerHandlerAdapter.java +++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/handler/WebHandlerHandlerAdapter.java @@ -29,13 +29,12 @@ import org.springframework.web.server.WebHandler; import org.springframework.web.server.ServerWebExchange; /** - * Support use of {@link org.springframework.web.server.WebHandler} through the - * {@link DispatcherHandler}. + * Adapter to use a {@link WebHandler} through the {@link DispatcherHandler}. * * @author Rossen Stoyanchev * @author Sebastien Deleuze */ -public class HttpHandlerHandlerAdapter implements HandlerAdapter { +public class WebHandlerHandlerAdapter implements HandlerAdapter { private static final ResolvableType PUBLISHER_VOID = ResolvableType.forClassWithGenerics( Publisher.class, Void.class); @@ -49,9 +48,8 @@ public class HttpHandlerHandlerAdapter implements HandlerAdapter { @Override public Mono handle(ServerWebExchange exchange, Object handler) { WebHandler webHandler = (WebHandler) handler; - Mono completion = webHandler.handle(exchange); - ModelMap model = new ExtendedModelMap(); - return Mono.just(new HandlerResult(webHandler, completion, PUBLISHER_VOID, model)); + Mono mono = webHandler.handle(exchange); + return Mono.just(new HandlerResult(webHandler, mono, PUBLISHER_VOID)); } } diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/handler/SimpleHandlerResultHandlerTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/handler/SimpleResultHandlerTests.java similarity index 92% rename from spring-web-reactive/src/test/java/org/springframework/web/reactive/handler/SimpleHandlerResultHandlerTests.java rename to spring-web-reactive/src/test/java/org/springframework/web/reactive/handler/SimpleResultHandlerTests.java index 0056fc6858..9a94d4c2ee 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/handler/SimpleHandlerResultHandlerTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/handler/SimpleResultHandlerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * 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. @@ -27,7 +27,6 @@ import org.springframework.core.ResolvableType; import org.springframework.core.convert.support.GenericConversionService; import org.springframework.core.convert.support.ReactiveStreamsToCompletableFutureConverter; import org.springframework.core.convert.support.ReactiveStreamsToRxJava1Converter; -import org.springframework.ui.ExtendedModelMap; import org.springframework.web.method.HandlerMethod; import org.springframework.web.reactive.HandlerResult; @@ -37,12 +36,12 @@ import static org.junit.Assert.assertTrue; /** * @author Sebastien Deleuze */ -public class SimpleHandlerResultHandlerTests { +public class SimpleResultHandlerTests { @Test public void supports() throws NoSuchMethodException { - SimpleHandlerResultHandler resultHandler = new SimpleHandlerResultHandler(); + SimpleResultHandler resultHandler = new SimpleResultHandler(); TestController controller = new TestController(); HandlerMethod hm = new HandlerMethod(controller, TestController.class.getMethod("voidReturnValue")); @@ -77,7 +76,7 @@ public class SimpleHandlerResultHandlerTests { GenericConversionService conversionService = new GenericConversionService(); conversionService.addConverter(new ReactiveStreamsToCompletableFutureConverter()); conversionService.addConverter(new ReactiveStreamsToRxJava1Converter()); - SimpleHandlerResultHandler resultHandler = new SimpleHandlerResultHandler(conversionService); + SimpleResultHandler resultHandler = new SimpleResultHandler(conversionService); TestController controller = new TestController(); HandlerMethod hm = new HandlerMethod(controller, TestController.class.getMethod("voidReturnValue")); @@ -106,7 +105,7 @@ public class SimpleHandlerResultHandlerTests { } private HandlerResult createHandlerResult(HandlerMethod hm, ResolvableType type) { - return new HandlerResult(hm, null, type, new ExtendedModelMap()); + return new HandlerResult(hm, null, type); } diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/handler/SimpleUrlHandlerMappingIntegrationTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/handler/WebHandlerIntegrationTests.java similarity index 87% rename from spring-web-reactive/src/test/java/org/springframework/web/reactive/handler/SimpleUrlHandlerMappingIntegrationTests.java rename to spring-web-reactive/src/test/java/org/springframework/web/reactive/handler/WebHandlerIntegrationTests.java index a8fdd8b0aa..c6c8f1747a 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/handler/SimpleUrlHandlerMappingIntegrationTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/handler/WebHandlerIntegrationTests.java @@ -47,9 +47,11 @@ import static org.junit.Assert.assertEquals; /** + * Integration tests with simple WebHandler's processing requests. + * * @author Rossen Stoyanchev */ -public class SimpleUrlHandlerMappingIntegrationTests extends AbstractHttpHandlerIntegrationTests { +public class WebHandlerIntegrationTests extends AbstractHttpHandlerIntegrationTests { private static final Charset UTF_8 = Charset.forName("UTF-8"); @@ -59,14 +61,14 @@ public class SimpleUrlHandlerMappingIntegrationTests extends AbstractHttpHandler StaticApplicationContext wac = new StaticApplicationContext(); wac.registerSingleton("hm", TestHandlerMapping.class); - wac.registerSingleton("ha", HttpHandlerHandlerAdapter.class); - wac.registerSingleton("rh", SimpleHandlerResultHandler.class); + wac.registerSingleton("ha", WebHandlerHandlerAdapter.class); + wac.registerSingleton("rh", SimpleResultHandler.class); wac.refresh(); - DispatcherHandler webHandler = new DispatcherHandler(); - webHandler.setApplicationContext(wac); + DispatcherHandler dispatcherHandler = new DispatcherHandler(); + dispatcherHandler.setApplicationContext(wac); - return WebHttpHandlerBuilder.webHandler(webHandler) + return WebHttpHandlerBuilder.webHandler(dispatcherHandler) .exceptionHandlers(new ResponseStatusExceptionHandler()) .build(); } @@ -137,12 +139,16 @@ public class SimpleUrlHandlerMappingIntegrationTests extends AbstractHttpHandler } } + + private static DataBuffer asDataBuffer(String text) { + return new DefaultDataBufferAllocator().allocateBuffer().write(text.getBytes(StandardCharsets.UTF_8)); + } + private static class FooHandler implements WebHandler { @Override public Mono handle(ServerWebExchange exchange) { - DataBuffer buffer = new DefaultDataBufferAllocator().allocateBuffer() - .write("foo".getBytes(StandardCharsets.UTF_8)); + DataBuffer buffer = asDataBuffer("foo"); return exchange.getResponse().setBody(Flux.just(buffer)); } } @@ -151,8 +157,7 @@ public class SimpleUrlHandlerMappingIntegrationTests extends AbstractHttpHandler @Override public Mono handle(ServerWebExchange exchange) { - DataBuffer buffer = new DefaultDataBufferAllocator().allocateBuffer() - .write("bar".getBytes(StandardCharsets.UTF_8)); + DataBuffer buffer = asDataBuffer("bar"); return exchange.getResponse().setBody(Flux.just(buffer)); } } diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/method/annotation/RequestMappingIntegrationTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/method/annotation/RequestMappingIntegrationTests.java index 6a4ae62956..58bb05524e 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/method/annotation/RequestMappingIntegrationTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/method/annotation/RequestMappingIntegrationTests.java @@ -67,7 +67,7 @@ import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; import org.springframework.web.reactive.DispatcherHandler; import org.springframework.web.reactive.ViewResolver; -import org.springframework.web.reactive.handler.SimpleHandlerResultHandler; +import org.springframework.web.reactive.handler.SimpleResultHandler; import org.springframework.web.reactive.view.ViewResolverResultHandler; import org.springframework.web.reactive.view.freemarker.FreeMarkerConfigurer; import org.springframework.web.reactive.view.freemarker.FreeMarkerViewResolver; @@ -421,8 +421,8 @@ public class RequestMappingIntegrationTests extends AbstractHttpHandlerIntegrati } @Bean - public SimpleHandlerResultHandler simpleHandlerResultHandler() { - SimpleHandlerResultHandler resultHandler = new SimpleHandlerResultHandler(conversionService()); + public SimpleResultHandler simpleHandlerResultHandler() { + SimpleResultHandler resultHandler = new SimpleResultHandler(conversionService()); resultHandler.setOrder(2); return resultHandler; }