[[webflux-config]]
= WebFlux Config

[.small]#xref:web/webmvc/mvc-config.adoc[See equivalent in the Servlet stack]#

The WebFlux Java configuration declares the components that are 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 configuration. However, if you want to understand them,
you can see them in `WebFluxConfigurationSupport` or read more about what they are
in xref:web/webflux/dispatcher-handler.adoc#webflux-special-bean-types[Special Bean Types].

For more advanced customizations, not available in the configuration API, you can
gain full control over the configuration through the
xref:web/webflux/config.adoc#webflux-config-advanced-java[Advanced Configuration Mode].


[[webflux-config-enable]]
== Enabling WebFlux Config
[.small]#xref:web/webmvc/mvc-config/enable.adoc[See equivalent in the Servlet stack]#

You can use the `@EnableWebFlux` annotation in your Java config, as the following example shows:

[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes"]
----
	@Configuration
	@EnableWebFlux
	public class WebConfig {
	}
----

Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
	@Configuration
	@EnableWebFlux
	class WebConfig
----
======

NOTE: When using Spring Boot, you may want to use `@Configuration` classes of type `WebFluxConfigurer` but without
`@EnableWebFlux` to keep Spring Boot WebFlux customizations. See more details in
xref:#webflux-config-customize[the WebFlux config API section] and in
{spring-boot-docs-ref}/web/reactive.html#web.reactive.webflux.auto-configuration[the dedicated Spring Boot documentation].

The preceding example registers a number of Spring WebFlux
xref:web/webflux/dispatcher-handler.adoc#webflux-special-bean-types[infrastructure beans] and adapts to dependencies
available on the classpath -- for JSON, XML, and others.


[[webflux-config-customize]]
== WebFlux config API
[.small]#xref:web/webmvc/mvc-config/customize.adoc[See equivalent in the Servlet stack]#

In your Java configuration, you can implement the `WebFluxConfigurer` interface,
as the following example shows:

[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes"]
----
	@Configuration
	public class WebConfig implements WebFluxConfigurer {

		// Implement configuration methods...
	}
----

Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Configuration
class WebConfig : WebFluxConfigurer {

	// Implement configuration methods...
}
----
======


[[webflux-config-conversion]]
== Conversion, formatting
[.small]#xref:web/webmvc/mvc-config/conversion.adoc[See equivalent in the Servlet stack]#

By default, formatters for various number and date types are installed, along with support
for customization via `@NumberFormat`, `@DurationFormat`, and `@DateTimeFormat` on fields
and parameters.

To register custom formatters and converters in Java config, use the following:

[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes"]
----
	@Configuration
	public class WebConfig implements WebFluxConfigurer {

		@Override
		public void addFormatters(FormatterRegistry registry) {
			// ...
		}

	}
----

Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
	@Configuration
	class WebConfig : WebFluxConfigurer {

		override fun addFormatters(registry: FormatterRegistry) {
			// ...
		}
	}
----
======

By default Spring WebFlux considers the request Locale when parsing and formatting date
values. This works for forms where dates are represented as Strings with "input" form
fields. For "date" and "time" form fields, however, browsers use a fixed format defined
in the HTML spec. For such cases date and time formatting can be customized as follows:

[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes"]
----
	@Configuration
	public class WebConfig implements WebFluxConfigurer {

		@Override
		public void addFormatters(FormatterRegistry registry) {
			DateTimeFormatterRegistrar registrar = new DateTimeFormatterRegistrar();
			registrar.setUseIsoFormat(true);
			registrar.registerFormatters(registry);
		}
	}
----

Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
	@Configuration
	class WebConfig : WebFluxConfigurer {

		override fun addFormatters(registry: FormatterRegistry) {
			val registrar = DateTimeFormatterRegistrar()
			registrar.setUseIsoFormat(true)
			registrar.registerFormatters(registry)
		}
	}
----
======

NOTE: See xref:core/validation/format.adoc#format-FormatterRegistrar-SPI[`FormatterRegistrar` SPI]
and the `FormattingConversionServiceFactoryBean` for more information on when to
use `FormatterRegistrar` implementations.


[[webflux-config-validation]]
== Validation
[.small]#xref:web/webmvc/mvc-config/validation.adoc[See equivalent in the Servlet stack]#

By default, if xref:core/validation/beanvalidation.adoc#validation-beanvalidation-overview[Bean Validation] is present
on the classpath (for example, the Hibernate Validator), the `LocalValidatorFactoryBean`
is registered as a global xref:core/validation/validator.adoc[validator] for use with `@Valid` and
`@Validated` on `@Controller` method arguments.

In your Java configuration, you can customize the global `Validator` instance,
as the following example shows:

[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes"]
----
	@Configuration
	public class WebConfig implements WebFluxConfigurer {

		@Override
		public Validator getValidator() {
			// ...
		}

	}
----

Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
	@Configuration
	class WebConfig : WebFluxConfigurer {

		override fun getValidator(): Validator {
			// ...
		}

	}
----
======

Note that you can also register `Validator` implementations locally,
as the following example shows:

[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes"]
----
	@Controller
	public class MyController {

		@InitBinder
		protected void initBinder(WebDataBinder binder) {
			binder.addValidators(new FooValidator());
		}

	}
----

Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
	@Controller
	class MyController {

		@InitBinder
		protected fun initBinder(binder: WebDataBinder) {
			binder.addValidators(FooValidator())
		}
	}
----
======

TIP: If you need to have a `LocalValidatorFactoryBean` injected somewhere, create a bean and
mark it with `@Primary` in order to avoid conflict with the one declared in the MVC config.


[[webflux-config-content-negotiation]]
== Content Type Resolvers
[.small]#xref:web/webmvc/mvc-config/content-negotiation.adoc[See equivalent in the Servlet stack]#

You can configure how Spring WebFlux determines the requested media types for
`@Controller` instances from the request. By default, only the `Accept` header is checked,
but you can also enable a query parameter-based strategy.

The following example shows how to customize the requested content type resolution:

[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes"]
----
	@Configuration
	public class WebConfig implements WebFluxConfigurer {

		@Override
		public void configureContentTypeResolver(RequestedContentTypeResolverBuilder builder) {
			// ...
		}
	}
----

Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
	@Configuration
	class WebConfig : WebFluxConfigurer {

		override fun configureContentTypeResolver(builder: RequestedContentTypeResolverBuilder) {
			// ...
		}
	}
----
======


[[webflux-config-message-codecs]]
== HTTP message codecs
[.small]#xref:web/webmvc/mvc-config/message-converters.adoc[See equivalent in the Servlet stack]#

The following example shows how to customize how the request and response body are read and written:

[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes"]
----
	@Configuration
	public class WebConfig implements WebFluxConfigurer {

		@Override
		public void configureHttpMessageCodecs(ServerCodecConfigurer configurer) {
			configurer.defaultCodecs().maxInMemorySize(512 * 1024);
		}
	}
----

Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
	@Configuration
	class WebConfig : WebFluxConfigurer {

		override fun configureHttpMessageCodecs(configurer: ServerCodecConfigurer) {
			configurer.defaultCodecs().maxInMemorySize(512 * 1024)
		}
	}
----
======

`ServerCodecConfigurer` provides a set of default readers and writers. You can use it to add
more readers and writers, customize the default ones, or replace the default ones completely.

For Jackson JSON and XML, consider using
{spring-framework-api}/http/converter/json/Jackson2ObjectMapperBuilder.html[`Jackson2ObjectMapperBuilder`],
which customizes Jackson's default properties with the following ones:

* {jackson-docs}/jackson-databind/javadoc/2.6/com/fasterxml/jackson/databind/DeserializationFeature.html#FAIL_ON_UNKNOWN_PROPERTIES[`DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES`] is disabled.
* {jackson-docs}/jackson-databind/javadoc/2.6/com/fasterxml/jackson/databind/MapperFeature.html#DEFAULT_VIEW_INCLUSION[`MapperFeature.DEFAULT_VIEW_INCLUSION`] is disabled.

It also automatically registers the following well-known modules if they are detected on the classpath:

* {jackson-github-org}/jackson-datatype-jsr310[`jackson-datatype-jsr310`]: Support for Java 8 Date and Time API types.
* {jackson-github-org}/jackson-datatype-jdk8[`jackson-datatype-jdk8`]: Support for other Java 8 types, such as `Optional`.
* {jackson-github-org}/jackson-module-kotlin[`jackson-module-kotlin`]: Support for Kotlin classes and data classes.


[[webflux-config-view-resolvers]]
== View Resolvers
[.small]#xref:web/webmvc/mvc-config/view-resolvers.adoc[See equivalent in the Servlet stack]#

The following example shows how to configure view resolution:

[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes"]
----
	@Configuration
	public class WebConfig implements WebFluxConfigurer {

		@Override
		public void configureViewResolvers(ViewResolverRegistry registry) {
			// ...
		}
	}
----

Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
	@Configuration
	class WebConfig : WebFluxConfigurer {

		override fun configureViewResolvers(registry: ViewResolverRegistry) {
			// ...
		}
	}
----
======

The `ViewResolverRegistry` has shortcuts for view technologies with which the Spring Framework
integrates. The following example uses FreeMarker (which also requires configuring the
underlying FreeMarker view technology):

[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes"]
----
	@Configuration
	public class WebConfig implements WebFluxConfigurer {


		@Override
		public void configureViewResolvers(ViewResolverRegistry registry) {
			registry.freeMarker();
		}

		// Configure Freemarker...

		@Bean
		public FreeMarkerConfigurer freeMarkerConfigurer() {
			FreeMarkerConfigurer configurer = new FreeMarkerConfigurer();
			configurer.setTemplateLoaderPath("classpath:/templates");
			return configurer;
		}
	}
----

Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
	@Configuration
	class WebConfig : WebFluxConfigurer {

		override fun configureViewResolvers(registry: ViewResolverRegistry) {
			registry.freeMarker()
		}

		// Configure Freemarker...

		@Bean
		fun freeMarkerConfigurer() = FreeMarkerConfigurer().apply {
			setTemplateLoaderPath("classpath:/templates")
		}
	}
----
======

You can also plug in any `ViewResolver` implementation, as the following example shows:

[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes"]
----
	@Configuration
	public class WebConfig implements WebFluxConfigurer {


		@Override
		public void configureViewResolvers(ViewResolverRegistry registry) {
			ViewResolver resolver = ... ;
			registry.viewResolver(resolver);
		}
	}
----

Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
	@Configuration
	class WebConfig : WebFluxConfigurer {

		override fun configureViewResolvers(registry: ViewResolverRegistry) {
			val resolver: ViewResolver = ...
			registry.viewResolver(resolver
		}
	}
----
======

To support xref:web/webflux/dispatcher-handler.adoc#webflux-multiple-representations[Content Negotiation] and rendering other formats
through view resolution (besides HTML), you can configure one or more default views based
on the `HttpMessageWriterView` implementation, which accepts any of the available
xref:web/webflux/reactive-spring.adoc#webflux-codecs[Codecs] from `spring-web`. The following example shows how to do so:

[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes"]
----
	@Configuration
	public class WebConfig implements WebFluxConfigurer {


		@Override
		public void configureViewResolvers(ViewResolverRegistry registry) {
			registry.freeMarker();

			Jackson2JsonEncoder encoder = new Jackson2JsonEncoder();
			registry.defaultViews(new HttpMessageWriterView(encoder));
		}

		// ...
	}
----

Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
	@Configuration
	class WebConfig : WebFluxConfigurer {


		override fun configureViewResolvers(registry: ViewResolverRegistry) {
			registry.freeMarker()

			val encoder = Jackson2JsonEncoder()
			registry.defaultViews(HttpMessageWriterView(encoder))
		}

		// ...
	}
----
======

See xref:web/webflux-view.adoc[View Technologies] for more on the view technologies that are integrated with Spring WebFlux.


[[webflux-config-static-resources]]
== Static Resources
[.small]#xref:web/webmvc/mvc-config/static-resources.adoc[See equivalent in the Servlet stack]#

This option provides a convenient way to serve static resources from a list of
{spring-framework-api}/core/io/Resource.html[`Resource`]-based locations.

In the next example, given a request that starts with `/resources`, the relative path is
used to find and serve static resources relative to `/static` on the classpath. Resources
are served with a one-year future expiration to ensure maximum use of the browser cache
and a reduction in HTTP requests made by the browser. The `Last-Modified` header is also
evaluated and, if present, a `304` status code is returned. The following listing shows
the example:

[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes"]
----
	@Configuration
	public class WebConfig implements WebFluxConfigurer {

		@Override
		public void addResourceHandlers(ResourceHandlerRegistry registry) {
			registry.addResourceHandler("/resources/**")
					.addResourceLocations("/public", "classpath:/static/")
					.setCacheControl(CacheControl.maxAge(365, TimeUnit.DAYS));
		}

	}
----

Kotlin::
+
[source,kotlin,indent=0,subs="verbatim"]
----
	@Configuration
	class WebConfig : WebFluxConfigurer {

		override fun addResourceHandlers(registry: ResourceHandlerRegistry) {
			registry.addResourceHandler("/resources/**")
					.addResourceLocations("/public", "classpath:/static/")
					.setCacheControl(CacheControl.maxAge(365, TimeUnit.DAYS))
		}
	}
----
======

See also xref:web/webflux/caching.adoc#webflux-caching-static-resources[HTTP caching support for static resources].

The resource handler also supports a chain of
{spring-framework-api}/web/reactive/resource/ResourceResolver.html[`ResourceResolver`] implementations and
{spring-framework-api}/web/reactive/resource/ResourceTransformer.html[`ResourceTransformer`] implementations,
which can be used to create a toolchain for working with optimized resources.

You can use the `VersionResourceResolver` for versioned resource URLs based on an MD5 hash
computed from the content, a fixed application version, or other information. A
`ContentVersionStrategy` (MD5 hash) is a good choice with some notable exceptions (such as
JavaScript resources used with a module loader).

The following example shows how to use `VersionResourceResolver` in your Java configuration:

[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim"]
----
	@Configuration
	public class WebConfig implements WebFluxConfigurer {

		@Override
		public void addResourceHandlers(ResourceHandlerRegistry registry) {
			registry.addResourceHandler("/resources/**")
					.addResourceLocations("/public/")
					.resourceChain(true)
					.addResolver(new VersionResourceResolver().addContentVersionStrategy("/**"));
		}

	}
----

Kotlin::
+
[source,kotlin,indent=0,subs="verbatim"]
----
	@Configuration
	class WebConfig : WebFluxConfigurer {

		override fun addResourceHandlers(registry: ResourceHandlerRegistry) {
			registry.addResourceHandler("/resources/**")
					.addResourceLocations("/public/")
					.resourceChain(true)
					.addResolver(VersionResourceResolver().addContentVersionStrategy("/**"))
		}

	}
----
======

You can use `ResourceUrlProvider` to rewrite URLs and apply the full chain of resolvers and
transformers (for example, to insert versions). The WebFlux configuration provides a `ResourceUrlProvider`
so that it can be injected into others.

Unlike Spring MVC, at present, in WebFlux, there is no way to transparently rewrite static
resource URLs, since there are no view technologies that can make use of a non-blocking chain
of resolvers and transformers. When serving only local resources, the workaround is to use
`ResourceUrlProvider` directly (for example, through a custom element) and block.

Note that, when using both `EncodedResourceResolver` (for example, Gzip, Brotli encoded) and
`VersionedResourceResolver`, they must be registered in that order, to ensure content-based
versions are always computed reliably based on the unencoded file.

For https://www.webjars.org/documentation[WebJars], versioned URLs like
`/webjars/jquery/1.2.0/jquery.min.js` are the recommended and most efficient way to use them.
The related resource location is configured out of the box with Spring Boot (or can be configured
manually via `ResourceHandlerRegistry`) and does not require to add the
`org.webjars:webjars-locator-lite` dependency.

Version-less URLs like `/webjars/jquery/jquery.min.js` are supported through the
`WebJarsResourceResolver` which is automatically registered when the
`org.webjars:webjars-locator-lite` library is present on the classpath. The resolver can re-write
URLs to include the version of the jar and can also match against incoming URLs without versions
-- for example, from `/webjars/jquery/jquery.min.js` to `/webjars/jquery/1.2.0/jquery.min.js`.

TIP: The Java configuration based on `ResourceHandlerRegistry` provides further options
for fine-grained control, for example, last-modified behavior and optimized resource resolution.


[[webflux-config-path-matching]]
== Path Matching
[.small]#xref:web/webmvc/mvc-config/path-matching.adoc[See equivalent in the Servlet stack]#

You can customize options related to path matching. For details on the individual options, see the
{spring-framework-api}/web/reactive/config/PathMatchConfigurer.html[`PathMatchConfigurer`] javadoc.
The following example shows how to use `PathMatchConfigurer`:

include-code::./WebConfig[]

[TIP]
====
Spring WebFlux relies on a parsed representation of the request path called
`RequestPath` for access to decoded path segment values, with semicolon content removed
(that is, path or matrix variables). That means, unlike in Spring MVC, you need not indicate
whether to decode the request path nor whether to remove semicolon content for
path matching purposes.

Spring WebFlux also does not support suffix pattern matching, unlike in Spring MVC, where we
are also xref:web/webmvc/mvc-controller/ann-requestmapping.adoc#mvc-ann-requestmapping-suffix-pattern-match[recommend] moving away from
reliance on it.
====


[[webflux-config-api-version]]
== API Version
[.small]#xref:web/webmvc/mvc-config/api-version.adoc[See equivalent in the Servlet stack]#

To enable API versioning, use the `ApiVersionConfigurer` callback of `WebFluxConfigurer`:

[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim"]
----
	@Configuration
	public class WebConfiguration implements WebFluxConfigurer {

		@Override
		public void configureApiVersioning(ApiVersionConfigurer configurer) {
			configurer.useRequestHeader("API-Version");
		}
	}
----

Kotlin::
+
[source,kotlin,indent=0,subs="verbatim"]
----
	@Configuration
	class WebConfiguration : WebMvcConfigurer {

		override fun configureApiVersioning(configurer: ApiVersionConfigurer) {
			configurer.useRequestHeader("API-Version")
		}
	}
----
======

You can resolve the version through one of the built-in options listed below, or
alternatively use a custom `ApiVersionResolver`:

- Request header
- Request parameter
- Path segment
- Media type parameter

To resolve from a path segment, you need to specify the index of the path segment expected
to contain the version. The path segment must be declared as a URI variable, e.g.
"/\{version}", "/api/\{version}", etc. where the actual name is not important.
As the version is typically at the start of the path, consider configuring it externally
as a common path prefix for all handlers through the
xref:web/webflux/config.adoc#webflux-config-path-matching[Path Matching] options.

By default, the version is parsed with `SemanticVersionParser`, but you can also configure
a custom xref:web/webflux-versioning.adoc#webflux-versioning-parser[ApiVersionParser].

Supported versions are transparently detected from versions declared in request mappings
for convenience, but you can turn that off through a flag in the WebFlux config, and
consider only the versions configured explicitly in the config as supported.
Requests with a version that is not supported are rejected with
`InvalidApiVersionException` resulting in a 400 response.

You can set an `ApiVersionDeprecationHandler` to send information about deprecated
versions to clients. The built-in standard handler can set "Deprecation", "Sunset", and
"Link" headers based on https://datatracker.ietf.org/doc/html/rfc9745[RFC 9745] and
https://datatracker.ietf.org/doc/html/rfc8594[RFC 8594].

Once API versioning is configured, you can begin to map requests to
xref:web/webflux/controller/ann-requestmapping.adoc#webflux-ann-requestmapping-version[controller methods]
according to the request version.


[[webflux-config-blocking-execution]]
== Blocking Execution

The WebFlux Java config allows you to customize blocking execution in WebFlux.

You can have blocking controller methods called on a separate thread by providing
an `AsyncTaskExecutor` such as the
{spring-framework-api}/core/task/VirtualThreadTaskExecutor.html[`VirtualThreadTaskExecutor`]
as follows:

[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes"]
----
	@Configuration
	public class WebConfig implements WebFluxConfigurer {

		@Override
		public void configureBlockingExecution(BlockingExecutionConfigurer configurer) {
			AsyncTaskExecutor executor = ...
			configurer.setExecutor(executor);
		}
	}
----

Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
	@Configuration
	class WebConfig : WebFluxConfigurer {

		@Override
		fun configureBlockingExecution(configurer: BlockingExecutionConfigurer) {
			val executor = ...
			configurer.setExecutor(executor)
		}
	}
----
======

By default, controller methods whose return type is not recognized by the configured
`ReactiveAdapterRegistry` are considered blocking, but you can set a custom controller
method predicate via `BlockingExecutionConfigurer`.


[[webflux-config-websocket-service]]
== WebSocketService

The WebFlux Java config declares of a `WebSocketHandlerAdapter` bean which provides
support for the invocation of WebSocket handlers. That means all that remains to do in
order to handle a WebSocket handshake request is to map a `WebSocketHandler` to a URL
via `SimpleUrlHandlerMapping`.

In some cases it may be necessary to create the `WebSocketHandlerAdapter` bean with a
provided `WebSocketService` service which allows configuring WebSocket server properties.
For example:

[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes"]
----
	@Configuration
	public class WebConfig implements WebFluxConfigurer {

		@Override
		public WebSocketService getWebSocketService() {
			TomcatRequestUpgradeStrategy strategy = new TomcatRequestUpgradeStrategy();
			strategy.setMaxSessionIdleTimeout(0L);
			return new HandshakeWebSocketService(strategy);
		}
	}
----

Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
	@Configuration
	class WebConfig : WebFluxConfigurer {

		@Override
		fun webSocketService(): WebSocketService {
			val strategy = TomcatRequestUpgradeStrategy().apply {
				setMaxSessionIdleTimeout(0L)
			}
			return HandshakeWebSocketService(strategy)
		}
	}
----
======


[[webflux-config-advanced-java]]
== Advanced Configuration Mode
[.small]#xref:web/webmvc/mvc-config/advanced-java.adoc[See equivalent in the Servlet stack]#

`@EnableWebFlux` imports `DelegatingWebFluxConfiguration` that:

*  Provides default Spring configuration for WebFlux applications

* detects and delegates to `WebFluxConfigurer` implementations to customize that configuration.

For advanced mode, you can remove `@EnableWebFlux` and extend directly from
`DelegatingWebFluxConfiguration` instead of implementing `WebFluxConfigurer`,
as the following example shows:

[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes"]
----
	@Configuration
	public class WebConfig extends DelegatingWebFluxConfiguration {

		// ...
	}
----

Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
	@Configuration
	class WebConfig : DelegatingWebFluxConfiguration {

		// ...
	}
----
======

You can keep existing methods in `WebConfig`, but you can now also override bean declarations
from the base class and still have any number of other `WebMvcConfigurer` implementations on
the classpath.
