From 72e3c43375e50f40d7ef52ede74ccc93455e8a97 Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Thu, 11 Jan 2018 11:55:37 -0500 Subject: [PATCH] Refine @EnableWebFlux docs for functional endpoints @EnableWebFlux bootstraps both annotated controllers and functional endpoints, so we need to be more explicit about which parts of the configuration apply to which. Issue: SPR-16360 --- .../web/reactive/config/EnableWebFlux.java | 38 ++++++++-------- .../reactive/config/WebFluxConfigurer.java | 44 ++++++++++++------- src/docs/asciidoc/web/webflux-functional.adoc | 25 ++++++----- src/docs/asciidoc/web/webflux.adoc | 15 ++++--- 4 files changed, 69 insertions(+), 53 deletions(-) diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/config/EnableWebFlux.java b/spring-webflux/src/main/java/org/springframework/web/reactive/config/EnableWebFlux.java index c1b83913140..708f7cc0e71 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/config/EnableWebFlux.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/config/EnableWebFlux.java @@ -25,8 +25,11 @@ import java.lang.annotation.Target; import org.springframework.context.annotation.Import; /** - * Adding this annotation to an {@code @Configuration} class imports the Spring Web - * Reactive configuration from {@link WebFluxConfigurationSupport}, e.g.: + * Adding this annotation to an {@code @Configuration} class imports the Spring + * WebFlux configuration from {@link WebFluxConfigurationSupport} that enables + * use of annotated controllers and functional endpoints. + * + *

For example: * *

  * @Configuration
@@ -36,8 +39,8 @@ import org.springframework.context.annotation.Import;
  * }
  * 
* - *

To customize the imported configuration implement - * {@link WebFluxConfigurer} and override individual methods as shown below: + *

To customize the imported configuration, implement + * {@link WebFluxConfigurer} and one or more of its methods: * *

  * @Configuration
@@ -46,33 +49,32 @@ import org.springframework.context.annotation.Import;
  * public class MyConfiguration implements WebFluxConfigurer {
  *
  * 	   @Override
- * 	   public void addFormatters(FormatterRegistry formatterRegistry) {
- *         formatterRegistry.addConverter(new MyConverter());
- * 	   }
- *
- * 	   @Override
  * 	   public void configureMessageWriters(List<HttpMessageWriter<?>> messageWriters) {
  *         messageWriters.add(new MyHttpMessageWriter());
  * 	   }
+ *
+ * 	   // ...
  * }
  * 
* - *

Note: only one {@code @Configuration} class may have the - * {@code @EnableWebFlux} annotation to import the Spring WebFlux configuration. - * There can however be multiple {@code @Configuration} classes implementing - * {@code WebFluxConfigurer} in order to customize the provided configuration. + *

Only one {@code @Configuration} class should have the {@code @EnableWebFlux} + * annotation in order to import the Spring WebFlux configuration. There can + * however be multiple {@code @Configuration} classes that implement + * {@code WebFluxConfigurer} that customize the provided configuration. * - *

If {@link WebFluxConfigurer} does not expose some more advanced setting - * that needs to be configured consider removing the {@code @EnableWebFlux} - * annotation and extending directly from {@link WebFluxConfigurationSupport} - * or {@link DelegatingWebFluxConfiguration} if you still want to allow - * {@link WebFluxConfigurer} instances to customize the configuration. + *

If {@code WebFluxConfigurer} does not expose some setting that needs to be + * configured, consider switching to an advanced mode by removing the + * {@code @EnableWebFlux} annotation and extending directly from + * {@link WebFluxConfigurationSupport} or {@link DelegatingWebFluxConfiguration} -- + * the latter allows detecting and delegating to one or more + * {@code WebFluxConfigurer} configuration classes. * * @author Brian Clozel * @author Rossen Stoyanchev * @since 5.0 * @see WebFluxConfigurer * @see WebFluxConfigurationSupport + * @see DelegatingWebFluxConfiguration */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/config/WebFluxConfigurer.java b/spring-webflux/src/main/java/org/springframework/web/reactive/config/WebFluxConfigurer.java index 11700ef2f58..142d818dd7d 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/config/WebFluxConfigurer.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/config/WebFluxConfigurer.java @@ -28,7 +28,7 @@ import org.springframework.web.reactive.result.method.annotation.ArgumentResolve /** * Defines callback methods to customize the configuration for WebFlux - * applications enabled via {@code @EnableWebFlux}. + * applications enabled via {@link EnableWebFlux @EnableWebFlux}. * *

{@code @EnableWebFlux}-annotated configuration classes may implement * this interface to be called back and given a chance to customize the @@ -38,18 +38,25 @@ import org.springframework.web.reactive.result.method.annotation.ArgumentResolve * @author Brian Clozel * @author Rossen Stoyanchev * @since 5.0 + * @see WebFluxConfigurationSupport + * @see DelegatingWebFluxConfiguration */ public interface WebFluxConfigurer { /** - * Configure how the content type requested for the response is resolved. + * Configure how the content type requested for the response is resolved + * when handling reqests with annotated controllers. * @param builder for configuring the resolvers to use */ default void configureContentTypeResolver(RequestedContentTypeResolverBuilder builder) { } /** - * Configure cross origin requests processing. + * Configure "global" cross origin request processing. + *

The configured readers and writers will apply to all requests including + * annotated controllers and functional endpoints. Annotated controllers can + * further declare more fine-grained configuration via + * {@link org.springframework.web.bind.annotation.CrossOrigin @CrossOrigin}. * @see CorsRegistry */ default void addCorsMappings(CorsRegistry registry) { @@ -57,8 +64,9 @@ public interface WebFluxConfigurer { /** * Configure path matching options. - * - * {@code HandlerMapping}s with path matching options. + *

The configured path matching options will be used for mapping to + * annotated controllers and also + * {@link #addResourceHandlers(ResourceHandlerRegistry) static resources}. * @param configurer the {@link PathMatchConfigurer} instance */ default void configurePathMatching(PathMatchConfigurer configurer) { @@ -72,7 +80,7 @@ public interface WebFluxConfigurer { } /** - * Configure resolvers for custom controller method arguments. + * Configure resolvers for custom {@code @RequestMapping} method arguments. * @param configurer to configurer to use */ default void configureArgumentResolvers(ArgumentResolverConfigurer configurer) { @@ -80,6 +88,8 @@ public interface WebFluxConfigurer { /** * Configure custom HTTP message readers and writers or override built-in ones. + *

The configured readers and writers will be used for both annotated + * controllers and functional endpoints. * @param configurer the configurer to use */ default void configureHttpMessageCodecs(ServerCodecConfigurer configurer) { @@ -87,7 +97,7 @@ public interface WebFluxConfigurer { /** * Add custom {@link Converter}s and {@link Formatter}s for performing type - * conversion and formatting of controller method arguments. + * conversion and formatting of annotated controller method arguments. */ default void addFormatters(FormatterRegistry registry) { } @@ -96,6 +106,8 @@ public interface WebFluxConfigurer { * Provide a custom {@link Validator}. *

By default a validator for standard bean validation is created if * bean validation api is present on the classpath. + *

The configured validator is used for validating annotated controller + * method arguments. */ @Nullable default Validator getValidator() { @@ -103,8 +115,9 @@ public interface WebFluxConfigurer { } /** - * Provide a custom {@link MessageCodesResolver} to use for data binding instead - * of the one created by default in {@link org.springframework.validation.DataBinder}. + * Provide a custom {@link MessageCodesResolver} to use for data binding in + * annotated controller method arguments instead of the one created by + * default in {@link org.springframework.validation.DataBinder}. */ @Nullable default MessageCodesResolver getMessageCodesResolver() { @@ -112,14 +125,11 @@ public interface WebFluxConfigurer { } /** - * Configure view resolution for processing the return values of controller - * methods that rely on resolving a - * {@link org.springframework.web.reactive.result.view.View} to render - * the response with. By default all controller methods rely on view - * resolution unless annotated with {@code @ResponseBody} or explicitly - * return {@code ResponseEntity}. A view may be specified explicitly with - * a String return value or implicitly, e.g. {@code void} return value. - * @see ViewResolverRegistry + * Configure view resolution for rendering responses with a view and a model, + * where the view is typically an HTML template but could also be based on + * an HTTP message writer (e.g. JSON, XML). + *

The configured view resolvers will be used for both annotated + * controllers and functional endpoints. */ default void configureViewResolvers(ViewResolverRegistry registry) { } diff --git a/src/docs/asciidoc/web/webflux-functional.adoc b/src/docs/asciidoc/web/webflux-functional.adoc index 3507fab8dc8..b0ab7f12336 100644 --- a/src/docs/asciidoc/web/webflux-functional.adoc +++ b/src/docs/asciidoc/web/webflux-functional.adoc @@ -205,20 +205,21 @@ The returned `HttpHandler` can then be used with a number of servers adapters by A more advanced option is to run with a <>-based setup through the <> which uses Spring configuration to declare the -components process requests. The WebFlux Java config declares the following components -related to functional endpoints: +components quired to process requests. The WebFlux Java config declares the following +infrastructure components to support functional endpoints: -* `RouterFunctionMapping` -- this detects one or more `RouterFunction` beans in the -Spring configuration, combines them via `RouterFunction.andOther`, and routes requests to -the resulting, composed `RouterFunction`. -* `HandlerFunctionAdapter` -- simple adapter to invoke a `HandlerFunction` selected to -handle a request. -* `ServerResponseResultHandler` -- invokes the `writeTo` method of the `ServerResponse` -returned by the `HandlerFunction`. +* `RouterFunctionMapping` -- detects one or more `RouterFunction` beans in the Spring +configuration, combines them via `RouterFunction.andOther`, and routes requests to the +resulting composed `RouterFunction`. +* `HandlerFunctionAdapter` -- simple adapter that allows the `DispatcherHandler` to invoke +a `HandlerFunction` that was mapped to a request. +* `ServerResponseResultHandler` -- handles the result from the invocation of a +`HandlerFunction` by invoking the `writeTo` method of the `ServerResponse`. -The above allows functional endpoints to fit within the `DispatcherHandler` request -processing lifecycle, and potentially to run side by side with annotated controllers, if -any are declared. This is also the mechanism used in the Spring Boot WebFlux starter. +The above components allow functional endpoints to fit within the `DispatcherHandler` request +processing lifecycle, and also potentially run side by side with annotated controllers, if +any are declared. It is also how functional endpoints are enabled the Spring Boot WebFlux +starter. Below is example WebFlux Java config (see <> for how to run): diff --git a/src/docs/asciidoc/web/webflux.adoc b/src/docs/asciidoc/web/webflux.adoc index c1793a5e744..c2c59e16db9 100644 --- a/src/docs/asciidoc/web/webflux.adoc +++ b/src/docs/asciidoc/web/webflux.adoc @@ -1098,13 +1098,16 @@ include::webflux-functional.adoc[leveloffset=+1] == WebFlux Java Config [.small]#<># -The WebFlux Java config provides default configuration suitable for most applications along -with a configuration API to customize it. For more advanced customizations, not available in -the configuration API, see <>. +The WebFlux Java config declares components required to process requests with annotated +controllers or functional endpoints, and it offers an API to customize the configuration. +That means you do not need to understand the underlying beans created by the Java config +but, if you want to, it's very easy to see them in `WebFluxConfigurationSupport` or read more +what they are in <>. + +For more advanced customizations, not available in the configuration API, it is also +possible to gain full control over the configuration through the +<>. -You do not need to understand the underlying beans created by the Java config, but it's -easy to seem them in `WebFluxConfigurationSupport`, and if you want to learn more, see -<>.