From 40eb9c2c81744156adeb65c09880138af3e244d3 Mon Sep 17 00:00:00 2001 From: rstoyanchev Date: Wed, 25 Jun 2025 12:03:22 +0100 Subject: [PATCH] Add docs for API version deprecation support Closes gh-35049 --- .../ROOT/pages/web/webflux-versioning.adoc | 14 ++++++++++ .../ROOT/pages/web/webflux/config.adoc | 27 ++++++++++++------ .../ROOT/pages/web/webmvc-versioning.adoc | 17 ++++++++++- .../web/webmvc/mvc-config/api-version.adoc | 27 ++++++++++++------ .../reactive/config/ApiVersionConfigurer.java | 28 +++++++++---------- .../annotation/ApiVersionConfigurer.java | 28 +++++++++---------- 6 files changed, 96 insertions(+), 45 deletions(-) diff --git a/framework-docs/modules/ROOT/pages/web/webflux-versioning.adoc b/framework-docs/modules/ROOT/pages/web/webflux-versioning.adoc index 3982f8243d..0793305cfa 100644 --- a/framework-docs/modules/ROOT/pages/web/webflux-versioning.adoc +++ b/framework-docs/modules/ROOT/pages/web/webflux-versioning.adoc @@ -79,6 +79,20 @@ You can also specify a default version to use. +[[webflux-versioning-deprecation-handler]] +== ApiVersionDeprecationHandler +[.small]#xref:web/webmvc-versioning.adoc#mvc-versioning-deprecation-handler[See equivalent in the Reactive stack]# + +This strategy can be configured to send hints and information about deprecated versions to +clients via response headers. The built-in `StandardApiVersionDeprecationHandler` +can set the "Deprecation" "Sunset" headers and "Link" headers as defined in +https://datatracker.ietf.org/doc/html/rfc9745[RFC 9745] and +https://datatracker.ietf.org/doc/html/rfc8594[RFC 8594]. You can also configure a custom +handler for different headers. + + + + [[webflux-versioning-mapping]] == Request Mapping [.small]#xref:web/webmvc-versioning.adoc#mvc-versioning-mapping[See equivalent in the Servlet stack]# diff --git a/framework-docs/modules/ROOT/pages/web/webflux/config.adoc b/framework-docs/modules/ROOT/pages/web/webflux/config.adoc index d6135ed8e8..a2a1c0b9ec 100644 --- a/framework-docs/modules/ROOT/pages/web/webflux/config.adoc +++ b/framework-docs/modules/ROOT/pages/web/webflux/config.adoc @@ -690,7 +690,7 @@ reliance on it. == API Version [.small]#xref:web/webmvc/mvc-config/api-version.adoc[See equivalent in the Servlet stack]# -To enable API versioning with a request header, use the following: +To enable API versioning, use the `ApiVersionConfigurer` callback of `WebFluxConfigurer`: [tabs] ====== @@ -722,19 +722,30 @@ Kotlin:: ---- ====== -Alternatively, the version can be resolved from a request parameter, from a path segment, -or through a custom `ApiVersionResolver`. +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 TIP: When using a path segment, consider configuring a shared path prefix externally in xref:web/webmvc/mvc-config/path-matching.adoc[Path Matching] options. -Raw version values are parsed with `SemanticVersionParser` by default, but you can use +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 use only -the versions configured explicitly in the config. Requests with a version that is not -supported are rejected with `InvalidApiVersionException` resulting in a 400 response. +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] diff --git a/framework-docs/modules/ROOT/pages/web/webmvc-versioning.adoc b/framework-docs/modules/ROOT/pages/web/webmvc-versioning.adoc index 8ba890cb94..0f0d3175a6 100644 --- a/framework-docs/modules/ROOT/pages/web/webmvc-versioning.adoc +++ b/framework-docs/modules/ROOT/pages/web/webmvc-versioning.adoc @@ -30,6 +30,7 @@ related to versioning. It does the following: - Resolves versions from the requests via xref:#mvc-versioning-resolver[ApiVersionResolver] - Parses raw version values into `Comparable` with an xref:#mvc-versioning-parser[ApiVersionParser] - xref:#mvc-versioning-validation[Validates] request versions +- Sends deprecation hints in the responses `ApiVersionStrategy` helps to map requests to `@RequestMapping` controller methods, and is initialized by the MVC config. Typically, applications do not interact @@ -40,7 +41,7 @@ directly with it. [[mvc-versioning-resolver]] == ApiVersionResolver -[.small]#xref:web/webmvc-versioning.adoc#mvc-versioning-resolver[See equivalent in the Reactive stack]# +[.small]#xref:web/webflux-versioning.adoc#webflux-versioning-resolver[See equivalent in the Reactive stack]# This strategy resolves the API version from a request. The MVC config provides built-in options to resolve from a header, from a request parameter, or from the URL path. @@ -78,6 +79,20 @@ You can also specify a default version to use. +[[mvc-versioning-deprecation-handler]] +== ApiVersionDeprecationHandler +[.small]#xref:web/webflux-versioning.adoc#webflux-versioning-deprecation-handler[See equivalent in the Reactive stack]# + +This strategy can be configured to send hints and information about deprecated versions to +clients via response headers. The built-in `StandardApiVersionDeprecationHandler` +can set the "Deprecation" "Sunset" headers and "Link" headers as defined in +https://datatracker.ietf.org/doc/html/rfc9745[RFC 9745] and +https://datatracker.ietf.org/doc/html/rfc8594[RFC 8594]. You can also configure a custom +handler for different headers. + + + + [[mvc-versioning-mapping]] == Request Mapping [.small]#xref:web/webflux-versioning.adoc#webflux-versioning-mapping[See equivalent in the Reactive stack]# diff --git a/framework-docs/modules/ROOT/pages/web/webmvc/mvc-config/api-version.adoc b/framework-docs/modules/ROOT/pages/web/webmvc/mvc-config/api-version.adoc index ab8a97b173..c989de0dcd 100644 --- a/framework-docs/modules/ROOT/pages/web/webmvc/mvc-config/api-version.adoc +++ b/framework-docs/modules/ROOT/pages/web/webmvc/mvc-config/api-version.adoc @@ -3,23 +3,34 @@ [.small]#xref:web/webflux/config.adoc#webflux-config-api-version[See equivalent in the Reactive stack]# -To enable API versioning with a request header, use the following: +To enable API versioning, use the `ApiVersionConfigurer` callback of `WebMvcConfigurer`: include-code::./WebConfiguration[tag=snippet,indent=0] -Alternatively, the version can be resolved from a request parameter, from a path segment, -or through a custom `ApiVersionResolver`. +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 TIP: When using a path segment, consider configuring a shared path prefix externally in xref:web/webmvc/mvc-config/path-matching.adoc[Path Matching] options. -Raw version values are parsed with `SemanticVersionParser` by default, but you can use +By default, the version is parsed with `SemanticVersionParser`, but you can also configure a custom xref:web/webmvc-versioning.adoc#mvc-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 MVC config, and use only -the versions configured explicitly in the config. Requests with a version that is not -supported are rejected with `InvalidApiVersionException` resulting in a 400 response. +Supported versions are transparently detected from versions declared in request mappings +for convenience, but you can turn that off through a flag in the MVC 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/webmvc/mvc-controller/ann-requestmapping.adoc#mvc-ann-requestmapping-version[controller methods] diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/config/ApiVersionConfigurer.java b/spring-webflux/src/main/java/org/springframework/web/reactive/config/ApiVersionConfigurer.java index f7874297dc..22119b0f14 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/config/ApiVersionConfigurer.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/config/ApiVersionConfigurer.java @@ -53,12 +53,12 @@ public class ApiVersionConfigurer { private @Nullable String defaultVersion; - private @Nullable ApiVersionDeprecationHandler deprecationHandler; - private final Set supportedVersions = new LinkedHashSet<>(); private boolean detectSupportedVersions = true; + private @Nullable ApiVersionDeprecationHandler deprecationHandler; + /** * Add a resolver that extracts the API version from a request header. @@ -145,18 +145,6 @@ public class ApiVersionConfigurer { return this; } - /** - * Configure a handler to add handling for requests with a deprecated API - * version. Typically, this involves sending hints and information about - * the deprecation in response headers. - * @param handler the handler to use - * @see StandardApiVersionDeprecationHandler - */ - public ApiVersionConfigurer setDeprecationHandler(ApiVersionDeprecationHandler handler) { - this.deprecationHandler = handler; - return this; - } - /** * Add to the list of supported versions to check against before raising * {@link InvalidApiVersionException} for unknown versions. @@ -187,6 +175,18 @@ public class ApiVersionConfigurer { return this; } + /** + * Configure a handler to add handling for requests with a deprecated API + * version. Typically, this involves sending hints and information about + * the deprecation in response headers. + * @param handler the handler to use + * @see StandardApiVersionDeprecationHandler + */ + public ApiVersionConfigurer setDeprecationHandler(ApiVersionDeprecationHandler handler) { + this.deprecationHandler = handler; + return this; + } + protected @Nullable ApiVersionStrategy getApiVersionStrategy() { if (this.versionResolvers.isEmpty()) { return null; diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ApiVersionConfigurer.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ApiVersionConfigurer.java index 0994f8b039..93e54192b5 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ApiVersionConfigurer.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ApiVersionConfigurer.java @@ -53,12 +53,12 @@ public class ApiVersionConfigurer { private @Nullable String defaultVersion; - private @Nullable ApiVersionDeprecationHandler deprecationHandler; - private final Set supportedVersions = new LinkedHashSet<>(); private boolean detectSupportedVersions = true; + private @Nullable ApiVersionDeprecationHandler deprecationHandler; + /** * Add resolver to extract the version from a request header. @@ -145,18 +145,6 @@ public class ApiVersionConfigurer { return this; } - /** - * Configure a handler to add handling for requests with a deprecated API - * version. Typically, this involves sending hints and information about - * the deprecation in response headers. - * @param handler the handler to use - * @see StandardApiVersionDeprecationHandler - */ - public ApiVersionConfigurer setDeprecationHandler(ApiVersionDeprecationHandler handler) { - this.deprecationHandler = handler; - return this; - } - /** * Add to the list of supported versions to check against before raising * {@link InvalidApiVersionException} for unknown versions. @@ -187,6 +175,18 @@ public class ApiVersionConfigurer { return this; } + /** + * Configure a handler to add handling for requests with a deprecated API + * version. Typically, this involves sending hints and information about + * the deprecation in response headers. + * @param handler the handler to use + * @see StandardApiVersionDeprecationHandler + */ + public ApiVersionConfigurer setDeprecationHandler(ApiVersionDeprecationHandler handler) { + this.deprecationHandler = handler; + return this; + } + protected @Nullable ApiVersionStrategy getApiVersionStrategy() { if (this.versionResolvers.isEmpty()) { return null;