diff --git a/CHANGELOG.md b/CHANGELOG.md
index 47b5a8111..41ba6e3c9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,16 +5,164 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
-## [2.5.0] - 2024-04-01
+## [2.8.4] - 2025-01-25
+
+### Added
+- #2873 - Improve performance of getGenericMapResponse
+- #2836 - Provide option to set allowed locales
+- 2862 - Align Swagger-UI Prefix Path with Swagger-WebMvc Behavior
+
+### Changed
+- Upgrade spring-boot to 3.4.2
+- Upgrade spring-cloud-function to 4.2.1
+- Upgrade swagger-core to 2.2.28
+
+### Fixed
+- #2870 - Springdoc 2.8.x + Spring Boot 3.4.1 breaks native image support
+- #2869 - Exception logged when generating schema for delete method of Spring Data repository.
+- #2856 - @JsonUnwrapped is ignored in new version of lib.
+- #2852 - @Schema(types = "xxx") does not work for multipart param with enabled springdoc.default-support-form-data config option.
+
+## [2.8.3] - 2025-01-12
+
+### Added
+- #2851 - Refine condition, for ignoring types when using PolymorphicModelConverter
+
+## [2.8.2] - 2025-01-12
+
+### Added
+- #2849 - Provide better compatibility for projects migrating from OAS 3.0 to OAS 3.1
+
+### Fixed
+- #2846 - ClassCastException with spring-data-rest and openapi version 3.1 bug
+- #2844 - PageableObject and SortObject are called Pageablenull and Sortnull
+
+## [2.8.1] - 2025-01-06
+
+### Fixed
+- #2834 - java.lang.ClassNotFoundException: kotlin.reflect.full.KClasses when upgrade from 2.7.0 to 2.8.0
+
+## [2.8.0] - 2025-01-03
+
+### Added
+- #2790 - Moving to OpenAPI 3.1 as the default implementation for springdoc-openapi
+- #2817 - Obey annotations when flattening ParameterObject fields
+- #2826 - Make it possible to mark parameters with @RequestParam annotation to be sent in form instead of query.
+- #2822 - Support returning null in ParameterCustomizer
+- #2830 - Add support for deprecated fields.
+- #2780 - Add Security Schema by AutoConfigure
+
+### Changed
+- Upgrade spring-boot to 3.4.1
+- Upgrade spring-cloud-function to 4.2.0
+- Upgrade swagger-core to 2.2.27
+
+### Fixed
+- #2804 - Stable release 2.7.0 depends on Spring Cloud Milestone 4.2.0-M1
+- #2828 - Required a bean of type 'org.springframework.data.rest.webmvc.mapping.Associations' that could not be found.
+- #2823 - Capturing pattern in identical paths only renders the path element of one method
+- #2817 - Automatically add required if a field is @notNull or @NotBlank.
+- #2814 - An unresolvable circular reference with management.endpoint.gateway.enabled=true.
+- #2798 - Object schema generated for Unit Kotlin type.
+- #2797 - Removing operationId via customizer does not work anymore.
+- #2833 - Resolve infinite recursion and add example test with OpenAPI v3.1
+- #2827 - Ignoring @Parameter(required = false)
+
+## [2.7.0] - 2024-23-11
+
+### Added
+- #2777 - Add SortAsQueryParam annotation
+- #2786 - No static resource swagger-ui/index.html error after migration to 2.7.0-RC1
+
+### Changed
+- Upgrade spring-boot to 3.4.0
+- Upgrade swagger-ui to 5.18.2
+- Upgrade spring-security-oauth2-authorization-server to 1.4.0
+
+## [2.7.0-RC1] - 2024-11-06
### Added
+- #2649 - Add Encoding to multiple files and JSON payloads request test case
+- #2653 - Trim indent apply schema description
+- #2664 - Refactor Replace hardcoded schema prefix length
+- #2509, #2668 - Replace swagger urls in org.springdoc.core.properties.AbstractSwaggerUiConfigProperties#urls only if url is changed
+- #2727 - Display nullable request body with map type
+- #2746 - Readme.md add gradle import
+- #2760 - Added support for RequestBody as a meta-annotation
+- #2703 - Display nullable request body with map type
+- #2657 - Add support for OAS v3.1 webhooks
+### Changed
+- Upgrade spring-boot to 3.4.0-RC1
+- Upgrade swagger-core to 2.2.25
+- Upgrade swagger-ui to 5.18.1
+- Upgrade spring-cloud-function to 4.2.0-M1
+- Upgrade spring-security-oauth2-authorization-server to 1.4.0-M2
+
+### Fixed
+- #2752 - Swagger doesn't work after custom annotation replacing request parameters
+- #2747 - Move to webjars-locator-lite, in preparation for spring-boot 3.4 GA
+- #2705 - @Schema oneOf config is ignored when generate the api-docs
+- #2744 - SpringDocUI doest add Javadoc into swagger from abstract class
+- #2708 - Spring Boot (Webflux) - Swagger UI - redirect URI does not include Gateway Prefix
+- #2725 - Serialization to openapi of org.springframework.data.domain.Sort is wrong for Spring Boot >2.x
+- #2740 - Swagger-ui ignores property springdoc.swagger-ui.supported-submit-methods
+- #2733 - Bad schema return type when created a generic wrapper class for response entity
+- #2687 - Failed to load api definition after spring boot 3.4.0-M2
+- #2642 - Calling Swagger UI via different context paths fails
+- #2709 - Annotation @Hidden on rest controller class level doesn't work due to spring default proxying mechanism CGLIB
+- #2642 - Calling Swagger UI via different context paths fails
+- #2663 - Content definition in @ApiResponse remove schema generated based on the returned value
+- #2646 - The operationId is unnecessarily deduplicated for a requestBody with multiple content types
+- #2643 - UpperSnakeCaseStrategy is not working with spring boot and ParameterObject
+- #2640 - @JsonUnwrapped is ignored when PolymorphicConverter is enabled
+- #2638 - Boolean Parameter with @Schema Annotation Changes Type to string in OpenAPI Documentation
+- #2659 - Fix typo in SpringSecurityLoginEndpointCustomizer method name
+- #2660 - Update Response Code
+- #2442, #2669 - Fix SpringDocApp193Test for Java 21 and above
+- #2671 - Ensure default media type order is preserved using LinkedHashSet in mergeArrays
+- #2711 - Missing descriptions on Kotlin ByteArray fields
+- #2733 - Bad schema return type when created a generic wrapper class for response entity
+
+## [2.6.0] - 2024-06-30
+
+### Added
+- #2561 - NPE occurs when outputting an OpenAPI document since 2.5.0
+- #2579 - Add support for leading tab characters with trim-kotlin-indent.
+- #2589 - Pass HttpRequest to ServerBaseUrlCustomizer
+- #2596, #2600 - consumes and produces calculation. Fixes
+- #2625, #2626 - Replace Page schema with PagedModel when pageSerializationMode is set to VIA_DTO
+- #2627 - Ensure compatibility with previous version of spring data
+- #2576 - GroupedApi orders by displayName instead of name.
+- #2584 - Dynamically define ApiGroups does not work.
+- #2595 - Spring security support of @RegisteredOAuth2AuthorizedClient
+
+### Changed
+- Upgrade spring-boot to 3.3.0
+- Upgrade swagger-core to 2.2.22
+- Upgrade swagger-ui to 5.17.14
+- Upgrade spring-cloud-function to 4.1.2
+- Upgrade spring-security-oauth2-authorization-server to 1.3.0
+
+### Fixed
+- #2577 - Fix missing exception response types in OpenAPI spec
+- #2591 - When an entity class contains fields of Class> type, an infinite loop.
+- #2603 - PolymorphicModelConverter only handles direct subtypes and misses indirect.
+- #2606 - Spring Authorization Server Metadata Endpoint not compatible.
+- #2621 - Content-type for POST endpoints with multipart/form-data does not work since v2.4.0.
+- #2622 - Kotlin enums are always marked as required if used in Java controllers.
+- #2601 - Multiple Superclasses Are Not Mapped To Multiple allOf If Used In Different Services.
+- #2597 - Polymorphic fields on polymorphic parents don't get correct oneOf docs generated.
+
+## [2.5.0] - 2024-04-01
+
+### Added
- #2318 - Add Info to GroupedOpenAPI properties
- #2554 - Remove duplicate words from comments
- #2418 - Improve support for externalizing strings in generated openapi
- #2535 - Add 'springdoc.trim-kotlin-indent' property to handle Kotlin multiline string indentation
-### Changed
+### Changed
- Upgrade spring-boot to 3.2.4
- Upgrade swagger-core to 2.2.21
- Upgrade swagger-ui to 5.13.0
@@ -28,19 +176,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [2.4.0] - 2024-03-12
### Added
-
- #2443 - Respect schema annotations when using spring mvc with kotlin
- #2492, #2488 - Support dynamic evaluation of description field in the RequestBody
- #2510 - Option to disable root api-docs path when using groups
### Changed
-
- Upgrade spring-boot to 3.2.3
- Upgrade swagger-core to 2.2.20
- Upgrade swagger-ui to 5.11.8
### Fixed
-
- #2453 - Fix CODE_OF_CONDUCT.md links
- #2454 - Fix typo in SwaggerWelcomeWebMvc
- #2507 - Fix typo in Constants
@@ -63,7 +208,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [2.3.0] - 2023-12-03
### Added
-
- #2340 - Add support OIDC with Spring Authorization Server
- #2345 - Support Schema added in OpenAPI Specification v3.1
- #2387 - Support get javadoc description from getter method
@@ -73,7 +217,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- #2438, #2315 - Support for @JsonProperty with Javadoc Change in springdoc-openapi
### Changed
-
- Upgrade spring-boot to 3.2.0
- Upgrade swagger-core to 2.2.19
- Upgrade swagger-ui to 5.10.3
@@ -92,7 +235,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [2.2.0] - 2023-08-06
### Added
-
- #2189 - Add support for swagger-ui.url property
- #2200 - Support schema.requiredMode() on ParameterObject
- #2309 - Added function to preload by specifying locale
diff --git a/README.md b/README.md
index 1295fcf39..180f3d560 100644
--- a/README.md
+++ b/README.md
@@ -29,6 +29,10 @@ This project is sponsored by
+
+
+
+
# Table of Contents
@@ -98,6 +102,7 @@ This is a community-based project, not maintained by the Spring Framework Contri
* Add the `springdoc-openapi-ui` library to the list of your project dependencies (No
additional configuration is needed):
+Maven
```xml
org.springdoc
@@ -106,6 +111,11 @@ This is a community-based project, not maintained by the Spring Framework Contri
```
+Gradle
+```groovy
+implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:latest'
+```
+
* This step is optional: For custom path of the swagger documentation in HTML format, add
a custom springdoc property, in your spring-boot configuration file:
@@ -144,6 +154,7 @@ springdoc.swagger-ui.path=/swagger-ui.html
* Add the library to the list of your project dependencies. (No additional configuration
is needed)
+Maven
```xml
org.springdoc
@@ -152,6 +163,11 @@ springdoc.swagger-ui.path=/swagger-ui.html
```
+Gradle
+```groovy
+implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:latest'
+```
+
* This step is optional: For custom path of the OpenAPI documentation in Json format, add
a custom springdoc property, in your spring-boot configuration file:
@@ -189,6 +205,7 @@ and `@SecurityScheme` annotations within a Spring managed bean.
* Add the library to the list of your project dependencies (No additional configuration
is needed)
+Maven
```xml
org.springdoc
@@ -197,6 +214,11 @@ and `@SecurityScheme` annotations within a Spring managed bean.
```
+Gradle
+```groovy
+implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:latest'
+```
+
* This step is optional: For custom path of the swagger documentation in HTML format, add
a custom springdoc property, in your spring-boot configuration file:
diff --git a/pom.xml b/pom.xml
index a5c49cdbb..5f72a3e70 100644
--- a/pom.xml
+++ b/pom.xml
@@ -2,7 +2,7 @@
4.0.0org.springdocspringdoc-openapi
- 2.5.0
+ 2.8.4pomSpring openapi documentationSpring openapi documentation
@@ -11,7 +11,7 @@
org.springframework.bootspring-boot-starter-parent
- 3.2.4
+ 3.4.2
@@ -35,7 +35,7 @@
scm:git:git@github.com:springdoc/springdoc-openapi.gitscm:git:git@github.com:springdoc/springdoc-openapi.git
- v2.5.0
+ v2.8.4
@@ -60,15 +60,13 @@
1.62.5.31.6.8
- 2.2.21
- 5.13.0
+ 2.2.28
+ 5.18.21.13.1
- 2.1
- 1.10.9.10.15.0
- 4.0.0
- 1.0.1
+ 4.2.1
+ 1.4.0
@@ -103,6 +101,11 @@
test
+
+ org.springframework.cloud
+ spring-cloud-function-core
+ ${spring-cloud-function.version}
+ org.springframework.cloudspring-cloud-function-web
@@ -321,6 +324,14 @@
true
+
+ spring-milestones
+ Spring Milestones
+ https://repo.spring.io/milestone
+
+ false
+
+
diff --git a/springdoc-openapi-starter-common/pom.xml b/springdoc-openapi-starter-common/pom.xml
index 958f25193..b3bdef137 100644
--- a/springdoc-openapi-starter-common/pom.xml
+++ b/springdoc-openapi-starter-common/pom.xml
@@ -3,7 +3,7 @@
org.springdocspringdoc-openapi
- 2.5.0
+ 2.8.4springdoc-openapi-starter-common
@@ -51,6 +51,11 @@
spring-security-oauth2-authorization-servertrue
+
+ org.springframework.security
+ spring-security-oauth2-client
+ true
+ com.fasterxml.jackson.module
@@ -67,6 +72,11 @@
kotlinx-coroutines-reactorprovided
+
+ org.jetbrains.kotlin
+ kotlin-reflect
+ provided
+ org.springframework.boot
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/api/AbstractOpenApiResource.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/api/AbstractOpenApiResource.java
index 2dda6e1c2..7c97a5e4c 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/api/AbstractOpenApiResource.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/api/AbstractOpenApiResource.java
@@ -3,23 +3,25 @@
* *
* * *
* * * *
- * * * * * Copyright 2019-2022 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
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
* * * * *
- * * * * * https://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.springdoc.api;
@@ -49,6 +51,8 @@
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import java.util.stream.Collectors;
import com.fasterxml.jackson.annotation.JsonView;
@@ -60,6 +64,8 @@
import io.swagger.v3.core.filter.SpecFilter;
import io.swagger.v3.core.util.ReflectionUtils;
import io.swagger.v3.oas.annotations.Hidden;
+import io.swagger.v3.oas.annotations.Webhook;
+import io.swagger.v3.oas.annotations.Webhooks;
import io.swagger.v3.oas.annotations.callbacks.Callback;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.models.Components;
@@ -69,6 +75,7 @@
import io.swagger.v3.oas.models.PathItem.HttpMethod;
import io.swagger.v3.oas.models.Paths;
import io.swagger.v3.oas.models.SpecVersion;
+import io.swagger.v3.oas.models.media.Schema;
import io.swagger.v3.oas.models.media.StringSchema;
import io.swagger.v3.oas.models.parameters.Parameter;
import io.swagger.v3.oas.models.responses.ApiResponses;
@@ -100,6 +107,7 @@
import org.springdoc.core.service.GenericResponseService;
import org.springdoc.core.service.OpenAPIService;
import org.springdoc.core.service.OperationService;
+import org.springdoc.core.utils.PropertyResolverUtils;
import org.springdoc.core.utils.SpringDocUtils;
import org.springframework.aop.support.AopUtils;
@@ -109,6 +117,7 @@
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.env.Environment;
import org.springframework.util.AntPathMatcher;
+import org.springframework.util.ClassUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
@@ -208,17 +217,23 @@ public abstract class AbstractOpenApiResource extends SpecFilter {
*/
private final Lock reentrantLock = new ReentrantLock();
+ /**
+ * The Path pattern.
+ */
+ private final Pattern pathPattern = Pattern.compile("\\{(.*?)}");
+
+
/**
* Instantiates a new Abstract open api resource.
*
- * @param groupName the group name
+ * @param groupName the group name
* @param openAPIBuilderObjectFactory the open api builder object factory
- * @param requestBuilder the request builder
- * @param responseBuilder the response builder
- * @param operationParser the operation parser
- * @param springDocConfigProperties the spring doc config properties
- * @param springDocProviders the spring doc providers
- * @param springDocCustomizers the spring doc customizers
+ * @param requestBuilder the request builder
+ * @param responseBuilder the response builder
+ * @param operationParser the operation parser
+ * @param springDocConfigProperties the spring doc config properties
+ * @param springDocProviders the spring doc providers
+ * @param springDocCustomizers the spring doc customizers
*/
protected AbstractOpenApiResource(String groupName, ObjectFactory openAPIBuilderObjectFactory,
AbstractRequestService requestBuilder,
@@ -237,7 +252,8 @@ protected AbstractOpenApiResource(String groupName, ObjectFactory this.getOpenApi(Locale.forLanguageTag(locale)));
}
@@ -301,7 +317,7 @@ public static boolean containsResponseBody(HandlerMethod handlerMethod) {
* @return the boolean
*/
public static boolean isHiddenRestControllers(Class> rawClass) {
- return HIDDEN_REST_CONTROLLERS.stream().anyMatch(clazz -> clazz.isAssignableFrom(rawClass));
+ return HIDDEN_REST_CONTROLLERS.stream().anyMatch(clazz -> ClassUtils.getUserClass(clazz).isAssignableFrom(rawClass));
}
/**
@@ -330,7 +346,7 @@ protected OpenAPI getOpenApi(Locale locale) {
this.reentrantLock.lock();
try {
final OpenAPI openAPI;
- final Locale finalLocale = locale == null ? Locale.getDefault() : locale;
+ final Locale finalLocale = selectLocale(locale);
if (openAPIService.getCachedOpenAPI(finalLocale) == null || springDocConfigProperties.isCacheDisabled()) {
Instant start = Instant.now();
openAPI = openAPIService.build(finalLocale);
@@ -341,9 +357,10 @@ protected OpenAPI getOpenApi(Locale locale) {
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (a1, a2) -> a1));
Map findControllerAdvice = openAPIService.getControllerAdviceMap();
- if (OpenApiVersion.OPENAPI_3_1 == springDocConfigProperties.getApiDocs().getVersion()){
+ if (OpenApiVersion.OPENAPI_3_1 == springDocConfigProperties.getApiDocs().getVersion()) {
openAPI.openapi(OpenApiVersion.OPENAPI_3_1.getVersion());
openAPI.specVersion(SpecVersion.V31);
+ calculateWebhooks(openAPI, locale);
}
if (springDocConfigProperties.isDefaultOverrideWithGenericResponse()) {
if (!CollectionUtils.isEmpty(mappingsMap))
@@ -352,6 +369,9 @@ protected OpenAPI getOpenApi(Locale locale) {
}
getPaths(mappingsMap, finalLocale, openAPI);
+ if (springDocConfigProperties.isTrimKotlinIndent())
+ this.trimIndent(openAPI);
+
Optional cloudFunctionProviderOptional = springDocProviders.getSpringCloudFunctionProvider();
cloudFunctionProviderOptional.ifPresent(cloudFunctionProvider -> {
List routerOperationList = cloudFunctionProvider.getRouterOperations(openAPI);
@@ -368,7 +388,7 @@ protected OpenAPI getOpenApi(Locale locale) {
if (springDocConfigProperties.isRemoveBrokenReferenceDefinitions())
this.removeBrokenReferenceDefinitions(openAPI);
- // run the optional customisers
+ // run the optional customizers
List servers = openAPI.getServers();
List serversCopy = null;
try {
@@ -384,7 +404,6 @@ protected OpenAPI getOpenApi(Locale locale) {
if (!CollectionUtils.isEmpty(openAPI.getServers()) && !openAPI.getServers().equals(serversCopy))
openAPIService.setServersPresent(true);
-
openAPIService.setCachedOpenAPI(openAPI, finalLocale);
LOGGER.info("Init duration for springdoc-openapi is: {} ms",
@@ -396,28 +415,136 @@ protected OpenAPI getOpenApi(Locale locale) {
openAPIService.updateServers(openAPI);
}
openAPIService.updateServers(openAPI);
- return openAPI; }
+ return openAPI;
+ }
finally {
this.reentrantLock.unlock();
}
}
+ private Locale selectLocale(Locale inputLocale) {
+ List allowedLocales = springDocConfigProperties.getAllowedLocales();
+ if (!CollectionUtils.isEmpty(allowedLocales)) {
+ Locale bestMatchingAllowedLocale = Locale.lookup(
+ Locale.LanguageRange.parse(inputLocale.toLanguageTag()),
+ allowedLocales.stream().map(Locale::forLanguageTag).collect(Collectors.toList())
+ );
+
+ return bestMatchingAllowedLocale == null ? Locale.forLanguageTag(allowedLocales.get(0)) : bestMatchingAllowedLocale;
+ }
+
+ return inputLocale == null ? Locale.getDefault() : inputLocale;
+ }
+
+ /**
+ * Indents are removed for properties that are mainly used as “explanations” using Open API.
+ *
+ * @param openAPI the open api
+ */
+ private void trimIndent(OpenAPI openAPI) {
+ trimComponents(openAPI);
+ trimPaths(openAPI);
+ }
+
+ /**
+ * Trim the indent for descriptions in the 'components' of open api.
+ *
+ * @param openAPI the open api
+ */
+ private void trimComponents(OpenAPI openAPI) {
+ final PropertyResolverUtils propertyResolverUtils = operationParser.getPropertyResolverUtils();
+ if (openAPI.getComponents() == null || openAPI.getComponents().getSchemas() == null) {
+ return;
+ }
+ for (Schema> schema : openAPI.getComponents().getSchemas().values()) {
+ schema.description(propertyResolverUtils.trimIndent(schema.getDescription()));
+ if (schema.getProperties() == null) {
+ continue;
+ }
+ for (Object prop : schema.getProperties().values()) {
+ if (prop instanceof Schema> schemaProp) {
+ schemaProp.setDescription(propertyResolverUtils.trimIndent(schemaProp.getDescription()));
+ }
+ }
+ }
+ }
+
+ /**
+ * Trim the indent for descriptions in the 'paths' of open api.
+ *
+ * @param openAPI the open api
+ */
+ private void trimPaths(OpenAPI openAPI) {
+ final PropertyResolverUtils propertyResolverUtils = operationParser.getPropertyResolverUtils();
+ if (openAPI.getPaths() == null) {
+ return;
+ }
+ for (PathItem value : openAPI.getPaths().values()) {
+ value.setDescription(propertyResolverUtils.trimIndent(value.getDescription()));
+ trimIndentOperation(value.getGet());
+ trimIndentOperation(value.getPut());
+ trimIndentOperation(value.getPost());
+ trimIndentOperation(value.getDelete());
+ trimIndentOperation(value.getOptions());
+ trimIndentOperation(value.getHead());
+ trimIndentOperation(value.getPatch());
+ trimIndentOperation(value.getTrace());
+ }
+ }
+
+ /**
+ * Trim the indent for 'operation'
+ *
+ * @param operation the operation
+ */
+ private void trimIndentOperation(Operation operation) {
+ final PropertyResolverUtils propertyResolverUtils = operationParser.getPropertyResolverUtils();
+ if (operation == null) {
+ return;
+ }
+ operation.setSummary(propertyResolverUtils.trimIndent(operation.getSummary()));
+ operation.setDescription(propertyResolverUtils.trimIndent(operation.getDescription()));
+ }
+
/**
* Gets paths.
*
* @param findRestControllers the find rest controllers
- * @param locale the locale
- * @param openAPI the open api
+ * @param locale the locale
+ * @param openAPI the open api
*/
protected abstract void getPaths(Map findRestControllers, Locale locale, OpenAPI openAPI);
+
+ /**
+ * Calculate webhooks.
+ *
+ * @param calculatedOpenAPI the calculated open api
+ * @param locale the locale
+ */
+ protected void calculateWebhooks(OpenAPI calculatedOpenAPI, Locale locale) {
+ Webhooks[] webhooksAttr = openAPIService.getWebhooks();
+ if(ArrayUtils.isEmpty(webhooksAttr))
+ return;
+ var webhooks = Arrays.stream(webhooksAttr).map(Webhooks::value).flatMap(Arrays::stream).toArray(Webhook[]::new);
+ Arrays.stream(webhooks).forEach(webhook -> {
+ io.swagger.v3.oas.annotations.Operation apiOperation = webhook.operation();
+ Operation operation = new Operation();
+ MethodAttributes methodAttributes = new MethodAttributes(springDocConfigProperties.getDefaultConsumesMediaType(),
+ springDocConfigProperties.getDefaultProducesMediaType(), locale);
+ operationParser.parse(apiOperation, operation, calculatedOpenAPI, methodAttributes);
+ PathItem pathItem = new PathItem().post(operation);
+ calculatedOpenAPI.addWebhooks(webhook.name(), pathItem);
+ });
+ }
+
/**
* Calculate path.
*
- * @param handlerMethod the handler method
+ * @param handlerMethod the handler method
* @param routerOperation the router operation
- * @param locale the locale
- * @param openAPI the open api
+ * @param locale the locale
+ * @param openAPI the open api
*/
protected void calculatePath(HandlerMethod handlerMethod, RouterOperation routerOperation, Locale locale, OpenAPI openAPI) {
routerOperation = customizeRouterOperation(routerOperation, handlerMethod);
@@ -524,18 +651,28 @@ protected void calculatePath(HandlerMethod handlerMethod, RouterOperation router
// allow for customisation
operation = customizeOperation(operation, handlerMethod);
+ if (StringUtils.contains(operationPath, "*")) {
+ Matcher matcher = pathPattern.matcher(operationPath);
+ while (matcher.find()) {
+ String pathParam = matcher.group(1);
+ String newPathParam = pathParam.replace("*", "");
+ operationPath = operationPath.replace("{" + pathParam + "}", "{" + newPathParam + "}");
+ }
+ }
+
PathItem pathItemObject = buildPathItem(requestMethod, operation, operationPath, paths);
- paths.addPathItem(operationPath, pathItemObject);
+ if (!StringUtils.contains(operationPath, "**"))
+ paths.addPathItem(operationPath, pathItemObject);
}
}
/**
* Build callbacks.
*
- * @param openAPI the open api
+ * @param openAPI the open api
* @param methodAttributes the method attributes
- * @param operation the operation
- * @param apiCallbacks the api callbacks
+ * @param operation the operation
+ * @param apiCallbacks the api callbacks
*/
private void buildCallbacks(OpenAPI openAPI, MethodAttributes methodAttributes, Operation operation, Set apiCallbacks) {
if (!CollectionUtils.isEmpty(apiCallbacks))
@@ -547,8 +684,8 @@ private void buildCallbacks(OpenAPI openAPI, MethodAttributes methodAttributes,
* Calculate path.
*
* @param routerOperationList the router operation list
- * @param locale the locale
- * @param openAPI the open api
+ * @param locale the locale
+ * @param openAPI the open api
*/
protected void calculatePath(List routerOperationList, Locale locale, OpenAPI openAPI) {
ApplicationContext applicationContext = openAPIService.getContext();
@@ -597,7 +734,8 @@ else if (routerOperation.getOperationModel() != null && StringUtils.isNotBlank(r
* Calculate path.
*
* @param routerOperation the router operation
- * @param locale the locale
+ * @param locale the locale
+ * @param openAPI the open api
*/
protected void calculatePath(RouterOperation routerOperation, Locale locale, OpenAPI openAPI) {
routerOperation = customizeDataRestRouterOperation(routerOperation);
@@ -623,7 +761,7 @@ protected void calculatePath(RouterOperation routerOperation, Locale locale, Ope
if (apiOperation != null)
openAPI = operationParser.parse(apiOperation, operation, openAPI, methodAttributes);
- String operationId = operationParser.getOperationId(operation.getOperationId(), openAPI);
+ String operationId = operation.getOperationId();
operation.setOperationId(operationId);
fillParametersList(operation, queryParams, methodAttributes);
@@ -650,9 +788,9 @@ protected void calculatePath(RouterOperation routerOperation, Locale locale, Ope
* @return the router operation
*/
private RouterOperation customizeDataRestRouterOperation(RouterOperation routerOperation) {
- Optional> optionalDataRestRouterOperationCustomizers = springDocCustomizers.getDataRestRouterOperationCustomizers();
+ Optional> optionalDataRestRouterOperationCustomizers = springDocCustomizers.getDataRestRouterOperationCustomizers();
if (optionalDataRestRouterOperationCustomizers.isPresent()) {
- List dataRestRouterOperationCustomizerList = optionalDataRestRouterOperationCustomizers.get();
+ Set dataRestRouterOperationCustomizerList = optionalDataRestRouterOperationCustomizers.get();
for (DataRestRouterOperationCustomizer dataRestRouterOperationCustomizer : dataRestRouterOperationCustomizerList) {
routerOperation = dataRestRouterOperationCustomizer.customize(routerOperation);
}
@@ -663,13 +801,15 @@ private RouterOperation customizeDataRestRouterOperation(RouterOperation routerO
/**
* Calculate path.
*
- * @param handlerMethod the handler method
- * @param operationPath the operation path
+ * @param handlerMethod the handler method
+ * @param operationPath the operation path
* @param requestMethods the request methods
- * @param consumes the consumes
- * @param produces the produces
- * @param headers the headers
- * @param locale the locale
+ * @param consumes the consumes
+ * @param produces the produces
+ * @param headers the headers
+ * @param params the params
+ * @param locale the locale
+ * @param openAPI the open api
*/
protected void calculatePath(HandlerMethod handlerMethod, String operationPath,
Set requestMethods, String[] consumes, String[] produces, String[] headers, String[] params, Locale locale, OpenAPI openAPI) {
@@ -679,10 +819,10 @@ protected void calculatePath(HandlerMethod handlerMethod, String operationPath,
/**
* Gets router function paths.
*
- * @param beanName the bean name
+ * @param beanName the bean name
* @param routerFunctionVisitor the router function visitor
- * @param locale the locale
- * @param openAPI the open api
+ * @param locale the locale
+ * @param openAPI the open api
*/
protected void getRouterFunctionPaths(String beanName, AbstractRouterFunctionVisitor routerFunctionVisitor,
Locale locale, OpenAPI openAPI) {
@@ -718,9 +858,9 @@ protected void getRouterFunctionPaths(String beanName, AbstractRouterFunctionVis
*
* @param handlerMethod the handler method
* @param operationPath the operation path
- * @param produces the produces
- * @param consumes the consumes
- * @param headers the headers
+ * @param produces the produces
+ * @param consumes the consumes
+ * @param headers the headers
* @return the boolean
*/
protected boolean isFilterCondition(HandlerMethod handlerMethod, String operationPath, String[] produces, String[] consumes, String[] headers) {
@@ -746,7 +886,7 @@ protected boolean isMethodToFilter(HandlerMethod handlerMethod) {
* Is condition to match boolean.
*
* @param existingConditions the existing conditions
- * @param conditionType the condition type
+ * @param conditionType the condition type
* @return the boolean
*/
protected boolean isConditionToMatch(String[] existingConditions, ConditionType conditionType) {
@@ -838,15 +978,15 @@ protected String decode(String requestURI) {
* @return the boolean
*/
protected boolean isAdditionalRestController(Class> rawClass) {
- return ADDITIONAL_REST_CONTROLLERS.stream().anyMatch(clazz -> clazz.isAssignableFrom(rawClass));
+ return ADDITIONAL_REST_CONTROLLERS.stream().anyMatch(clazz -> ClassUtils.getUserClass(clazz).isAssignableFrom(rawClass));
}
/**
* Is rest controller boolean.
*
* @param restControllers the rest controllers
- * @param handlerMethod the handler method
- * @param operationPath the operation path
+ * @param handlerMethod the handler method
+ * @param operationPath the operation path
* @return the boolean
*/
protected boolean isRestController(Map restControllers, HandlerMethod handlerMethod,
@@ -871,14 +1011,14 @@ protected Set getDefaultAllowedHttpMethods() {
/**
* Customise operation.
*
- * @param operation the operation
+ * @param operation the operation
* @param handlerMethod the handler method
* @return the operation
*/
protected Operation customizeOperation(Operation operation, HandlerMethod handlerMethod) {
- Optional> optionalOperationCustomizers = springDocCustomizers.getOperationCustomizers();
+ Optional> optionalOperationCustomizers = springDocCustomizers.getOperationCustomizers();
if (optionalOperationCustomizers.isPresent()) {
- List operationCustomizerList = optionalOperationCustomizers.get();
+ Set operationCustomizerList = optionalOperationCustomizers.get();
for (OperationCustomizer operationCustomizer : operationCustomizerList)
operation = operationCustomizer.customize(operation, handlerMethod);
}
@@ -889,13 +1029,13 @@ protected Operation customizeOperation(Operation operation, HandlerMethod handle
* Customise router operation
*
* @param routerOperation the router operation
- * @param handlerMethod the handler method
+ * @param handlerMethod the handler method
* @return the router operation
*/
protected RouterOperation customizeRouterOperation(RouterOperation routerOperation, HandlerMethod handlerMethod) {
- Optional> optionalRouterOperationCustomizers = springDocCustomizers.getRouterOperationCustomizers();
+ Optional> optionalRouterOperationCustomizers = springDocCustomizers.getRouterOperationCustomizers();
if (optionalRouterOperationCustomizers.isPresent()) {
- List routerOperationCustomizerList = optionalRouterOperationCustomizers.get();
+ Set routerOperationCustomizerList = optionalRouterOperationCustomizers.get();
for (RouterOperationCustomizer routerOperationCustomizer : routerOperationCustomizerList) {
routerOperation = routerOperationCustomizer.customize(routerOperation, handlerMethod);
}
@@ -994,9 +1134,9 @@ && isEqualArrays(routerFunctionData1.getConsumes(), routerOperation.getConsumes(
/**
* Calculate json view.
*
- * @param apiOperation the api operation
+ * @param apiOperation the api operation
* @param methodAttributes the method attributes
- * @param method the method
+ * @param method the method
*/
private void calculateJsonView(io.swagger.v3.oas.annotations.Operation apiOperation,
MethodAttributes methodAttributes, Method method) {
@@ -1053,8 +1193,8 @@ private boolean isEqualMethods(RequestMethod[] requestMethods1, RequestMethod[]
/**
* Fill parameters list.
*
- * @param operation the operation
- * @param queryParams the query params
+ * @param operation the operation
+ * @param queryParams the query params
* @param methodAttributes the method attributes
*/
private void fillParametersList(Operation operation, Map queryParams, MethodAttributes methodAttributes) {
@@ -1087,7 +1227,7 @@ private void fillParametersList(Operation operation, Map queryPa
* Fill router operation.
*
* @param routerFunctionData the router function data
- * @param routerOperation the router operation
+ * @param routerOperation the router operation
*/
private void fillRouterOperation(RouterFunctionData routerFunctionData, RouterOperation routerOperation) {
if (ArrayUtils.isEmpty(routerOperation.getConsumes()))
@@ -1106,9 +1246,9 @@ private void fillRouterOperation(RouterFunctionData routerFunctionData, RouterOp
* Build path item.
*
* @param requestMethod the request method
- * @param operation the operation
+ * @param operation the operation
* @param operationPath the operation path
- * @param paths the paths
+ * @param paths the paths
* @return the path item
*/
private PathItem buildPathItem(RequestMethod requestMethod, Operation operation, String operationPath,
@@ -1121,7 +1261,7 @@ private PathItem buildPathItem(RequestMethod requestMethod, Operation operation,
if (ParameterIn.PATH.toString().equals(parameter.getIn())) {
// check it's present in the path
String name = parameter.getName();
- if(!StringUtils.containsAny(operationPath, "{" + name + "}", "{*" + name + "}"))
+ if (!StringUtils.containsAny(operationPath, "{" + name + "}", "{*" + name + "}"))
paramIt.remove();
}
}
@@ -1166,7 +1306,7 @@ private PathItem buildPathItem(RequestMethod requestMethod, Operation operation,
/**
* Gets existing operation.
*
- * @param operationMap the operation map
+ * @param operationMap the operation map
* @param requestMethod the request method
* @return the existing operation
*/
@@ -1207,7 +1347,7 @@ private Operation getExistingOperation(Map operationMap,
/**
* Gets operation.
*
- * @param routerOperation the router operation
+ * @param routerOperation the router operation
* @param existingOperation the existing operation
* @return the operation
*/
@@ -1235,7 +1375,7 @@ else if (existingOperation != null) {
* @param locale the locale
*/
protected void initOpenAPIBuilder(Locale locale) {
- locale = locale == null ? Locale.getDefault() : locale;
+ locale = selectLocale(locale);
if (openAPIService.getCachedOpenAPI(locale) != null && springDocConfigProperties.isCacheDisabled()) {
openAPIService = openAPIBuilderObjectFactory.getObject();
}
@@ -1266,7 +1406,7 @@ protected byte[] writeYamlValue(OpenAPI openAPI) throws JsonProcessingException
* Gets actuator uri.
*
* @param scheme the scheme
- * @param host the host
+ * @param host the host
* @return the actuator uri
*/
protected URI getActuatorURI(String scheme, String host) {
@@ -1335,7 +1475,7 @@ protected byte[] writeJsonValue(OpenAPI openAPI) throws JsonProcessingException
* Gets conditions to match.
*
* @param conditionType the condition type
- * @param groupConfigs the group configs
+ * @param groupConfigs the group configs
* @return the conditions to match
*/
private List getConditionsToMatch(ConditionType conditionType, GroupConfig... groupConfigs) {
@@ -1363,9 +1503,9 @@ private List getConditionsToMatch(ConditionType conditionType, GroupConf
* Is filter condition boolean.
*
* @param operationPath the operation path
- * @param produces the produces
- * @param consumes the consumes
- * @param headers the headers
+ * @param produces the produces
+ * @param consumes the consumes
+ * @param headers the headers
* @return the boolean
*/
private boolean isFilterCondition(String operationPath, String[] produces, String[] consumes, String[] headers) {
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/api/ErrorMessage.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/api/ErrorMessage.java
index 35c9d48a9..7a076bfd0 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/api/ErrorMessage.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/api/ErrorMessage.java
@@ -3,23 +3,25 @@
* *
* * *
* * * *
- * * * * * Copyright 2019-2022 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
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
* * * * *
- * * * * * https://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.springdoc.api;
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/api/OpenApiResourceNotFoundException.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/api/OpenApiResourceNotFoundException.java
index 10d77eea4..3dd2e7e39 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/api/OpenApiResourceNotFoundException.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/api/OpenApiResourceNotFoundException.java
@@ -3,29 +3,32 @@
* *
* * *
* * * *
- * * * * * Copyright 2019-2022 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
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
* * * * *
- * * * * * https://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.springdoc.api;
/**
* The type Open api resource not found exception.
+ *
* @author bnasslahsen
*/
public class OpenApiResourceNotFoundException extends RuntimeException {
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/annotations/ParameterObject.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/annotations/ParameterObject.java
index 0fe189eb3..116b7f231 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/annotations/ParameterObject.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/annotations/ParameterObject.java
@@ -3,23 +3,25 @@
* *
* * *
* * * *
- * * * * * Copyright 2019-2022 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
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
* * * * *
- * * * * * https://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.springdoc.core.annotations;
@@ -31,6 +33,7 @@
/**
* The interface Parameter object.
+ *
* @author bnasslahsen
*/
@Target({ ElementType.PARAMETER, ElementType.TYPE })
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/annotations/RouterOperation.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/annotations/RouterOperation.java
index cb7364ea2..79f31ca43 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/annotations/RouterOperation.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/annotations/RouterOperation.java
@@ -3,23 +3,25 @@
* *
* * *
* * * *
- * * * * * Copyright 2019-2022 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
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
* * * * *
- * * * * * https://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.springdoc.core.annotations;
@@ -48,6 +50,7 @@
/**
* The path mapping URIs (e.g. {@code "/profile"}).
* Path mapping URIs may contain placeholders (e.g. "/${profile_path}").
+ *
* @return the string
*/
String path() default "";
@@ -55,6 +58,7 @@
/**
* The HTTP request methods to map to, narrowing the primary mapping:
* GET, POST, HEAD, OPTIONS, PUT, PATCH, DELETE, TRACE.
+ *
* @return the request method [ ]
*/
RequestMethod[] method() default {};
@@ -68,6 +72,7 @@
* consumes = {"text/plain", "application/*"}
* consumes = MediaType.TEXT_PLAIN_VALUE
*
+ *
* @return the string [ ]
*/
String[] consumes() default {};
@@ -84,6 +89,7 @@
* produces = MediaType.TEXT_PLAIN_VALUE
* produces = "text/plain;charset=UTF-8"
*
+ *
* @return the string [ ]
*/
String[] produces() default {};
@@ -93,6 +99,7 @@
*
Same format for any environment: a sequence of "My-Header=myValue" style
* expressions, with a request only mapped if each such header is found
* to have the given value.
+ *
* @return the string [ ]
*/
String[] headers() default {};
@@ -101,24 +108,28 @@
* The parameters of the mapped request, narrowing the primary mapping.
* Same format for any environment: a sequence of "myParam=myValue" style expressions,
* with a request only mapped if each such parameter is found to have the given value.
+ *
* @return the string [ ]
*/
String[] params() default {};
/**
* The class of the Handler bean.
+ *
* @return the class of the Bean
*/
Class> beanClass() default Void.class;
/**
* The method of the handler Bean.
+ *
* @return The method of the handler Bean.
*/
String beanMethod() default "";
/**
* The parameters of the handler method.
+ *
* @return The parameters of the handler method.
*/
Class>[] parameterTypes() default {};
@@ -126,6 +137,7 @@
/**
* The swagger operation description
* Alias for {@link Operation}.
+ *
* @return The operation
*/
Operation operation() default @Operation();
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/annotations/RouterOperations.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/annotations/RouterOperations.java
index 175a76916..a3495cb7f 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/annotations/RouterOperations.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/annotations/RouterOperations.java
@@ -3,23 +3,25 @@
* *
* * *
* * * *
- * * * * * Copyright 2019-2022 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
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
* * * * *
- * * * * * https://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.springdoc.core.annotations;
@@ -36,7 +38,7 @@
* Container for repeatable {@link RouterOperation} annotation
*
* @author bnasslahsen
- * @see RouterOperation
+ * @see RouterOperation
*/
@Target({ METHOD, ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME)
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/conditions/CacheOrGroupedOpenApiCondition.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/conditions/CacheOrGroupedOpenApiCondition.java
index 79497ccdc..ae8da1105 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/conditions/CacheOrGroupedOpenApiCondition.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/conditions/CacheOrGroupedOpenApiCondition.java
@@ -3,23 +3,25 @@
* *
* * *
* * * *
- * * * * * Copyright 2019-2022 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
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
* * * * *
- * * * * * https://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.springdoc.core.conditions;
@@ -35,6 +37,7 @@
/**
* The type Cache or grouped open api condition.
+ *
* @author bnasslahsen
*/
public class CacheOrGroupedOpenApiCondition extends AnyNestedCondition {
@@ -48,6 +51,7 @@ public class CacheOrGroupedOpenApiCondition extends AnyNestedCondition {
/**
* The type On multiple open api support condition.
+ *
* @author bnasslahsen
*/
@Conditional(MultipleOpenApiSupportCondition.class)
@@ -55,6 +59,7 @@ static class OnMultipleOpenApiSupportCondition {}
/**
* The type On cache disabled.
+ *
* @author bnasslahsen
*/
@ConditionalOnProperty(name = SPRINGDOC_CACHE_DISABLED)
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/conditions/MultipleOpenApiGroupsCondition.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/conditions/MultipleOpenApiGroupsCondition.java
index 63a1ab686..b7246fc9a 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/conditions/MultipleOpenApiGroupsCondition.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/conditions/MultipleOpenApiGroupsCondition.java
@@ -3,27 +3,31 @@
* *
* * *
* * * *
- * * * * * Copyright 2019-2022 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
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
* * * * *
- * * * * * https://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.springdoc.core.conditions;
+import java.util.Collection;
+
import org.springdoc.core.models.GroupedOpenApi;
import org.springframework.boot.autoconfigure.condition.AnyNestedCondition;
@@ -34,6 +38,7 @@
/**
* The type Multiple open api support condition.
+ *
* @author bnasslahsen
*/
public class MultipleOpenApiGroupsCondition extends AnyNestedCondition {
@@ -47,6 +52,7 @@ public class MultipleOpenApiGroupsCondition extends AnyNestedCondition {
/**
* The type On grouped open api bean.
+ *
* @author bnasslahsen
*/
@ConditionalOnBean(GroupedOpenApi.class)
@@ -54,9 +60,15 @@ static class OnGroupedOpenApiBean {}
/**
* The type On group config property.
+ *
* @author bnasslahsen
*/
@ConditionalOnProperty(name = GROUP_CONFIG_FIRST_PROPERTY)
static class OnGroupConfigProperty {}
+ /**
+ * The type On list grouped open api bean.
+ */
+ @ConditionalOnBean(value = GroupedOpenApi.class, parameterizedContainer = Collection.class)
+ static class OnListGroupedOpenApiBean {}
}
\ No newline at end of file
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/conditions/MultipleOpenApiSupportCondition.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/conditions/MultipleOpenApiSupportCondition.java
index bf2136c0b..3c050d0cd 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/conditions/MultipleOpenApiSupportCondition.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/conditions/MultipleOpenApiSupportCondition.java
@@ -3,23 +3,25 @@
* *
* * *
* * * *
- * * * * * Copyright 2019-2022 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
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
* * * * *
- * * * * * https://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.springdoc.core.conditions;
@@ -34,6 +36,7 @@
/**
* The type Multiple open api support condition.
+ *
* @author bnasslashen
*/
public class MultipleOpenApiSupportCondition extends AnyNestedCondition {
@@ -47,6 +50,7 @@ public class MultipleOpenApiSupportCondition extends AnyNestedCondition {
/**
* The type On multiple open api support condition.
+ *
* @author bnasslahsen
*/
@Conditional(MultipleOpenApiGroupsCondition.class)
@@ -54,6 +58,7 @@ static class OnMultipleOpenApiSupportCondition {}
/**
* The type On actuator different port.
+ *
* @author bnasslashen
*/
@ConditionalOnManagementPort(ManagementPortType.DIFFERENT)
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/conditions/SpecPropertiesCondition.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/conditions/SpecPropertiesCondition.java
index f7bc019fd..b964da9ec 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/conditions/SpecPropertiesCondition.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/conditions/SpecPropertiesCondition.java
@@ -1,3 +1,29 @@
+/*
+ *
+ * *
+ * * *
+ * * * *
+ * * * * *
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.springdoc.core.conditions;
/**
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocConfiguration.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocConfiguration.java
index 3a51f92e2..4c39763c9 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocConfiguration.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocConfiguration.java
@@ -3,19 +3,21 @@
* *
* * *
* * * *
- * * * * * Copyright 2019-2022 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
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
* * * * *
- * * * * * https://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.
* * * *
* * *
* *
@@ -31,6 +33,7 @@
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
+import java.util.Set;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.querydsl.core.types.Predicate;
@@ -49,12 +52,12 @@
import org.springdoc.core.converters.AdditionalModelsConverter;
import org.springdoc.core.converters.FileSupportConverter;
import org.springdoc.core.converters.ModelConverterRegistrar;
+import org.springdoc.core.converters.OAS31ModelConverter;
import org.springdoc.core.converters.PolymorphicModelConverter;
import org.springdoc.core.converters.PropertyCustomizingConverter;
import org.springdoc.core.converters.ResponseSupportConverter;
import org.springdoc.core.converters.SchemaPropertyDeprecatingConverter;
import org.springdoc.core.converters.WebFluxSupportConverter;
-import org.springdoc.core.customizers.ActuatorOpenApiCustomizer;
import org.springdoc.core.customizers.ActuatorOperationCustomizer;
import org.springdoc.core.customizers.DataRestRouterOperationCustomizer;
import org.springdoc.core.customizers.DelegatingMethodParameterCustomizer;
@@ -63,6 +66,8 @@
import org.springdoc.core.customizers.OpenApiBuilderCustomizer;
import org.springdoc.core.customizers.OpenApiCustomizer;
import org.springdoc.core.customizers.OperationCustomizer;
+import org.springdoc.core.customizers.OperationIdCustomizer;
+import org.springdoc.core.customizers.ParameterObjectNamingStrategyCustomizer;
import org.springdoc.core.customizers.PropertyCustomizer;
import org.springdoc.core.customizers.QuerydslPredicateOperationCustomizer;
import org.springdoc.core.customizers.RouterOperationCustomizer;
@@ -72,7 +77,6 @@
import org.springdoc.core.filters.GlobalOpenApiMethodFilter;
import org.springdoc.core.filters.OpenApiMethodFilter;
import org.springdoc.core.models.GroupedOpenApi;
-import org.springdoc.core.parsers.ReturnTypeParser;
import org.springdoc.core.properties.SpringDocConfigProperties;
import org.springdoc.core.providers.ActuatorProvider;
import org.springdoc.core.providers.CloudFunctionProvider;
@@ -131,6 +135,7 @@
/**
* The type Spring doc configuration.
+ *
* @author bnasslahsen
*/
@Lazy(false)
@@ -269,13 +274,13 @@ PolymorphicModelConverter polymorphicModelConverter(ObjectMapperProvider objectM
/**
* Open api builder open api builder.
*
- * @param openAPI the open api
- * @param securityParser the security parser
+ * @param openAPI the open api
+ * @param securityParser the security parser
* @param springDocConfigProperties the spring doc config properties
- * @param propertyResolverUtils the property resolver utils
+ * @param propertyResolverUtils the property resolver utils
* @param openApiBuilderCustomisers the open api builder customisers
- * @param serverBaseUrlCustomisers the server base url customisers
- * @param javadocProvider the javadoc provider
+ * @param serverBaseUrlCustomisers the server base url customisers
+ * @param javadocProvider the javadoc provider
* @return the open api builder
*/
@Bean
@@ -305,9 +310,9 @@ ModelConverterRegistrar modelConverterRegistrar(Optional> m
/**
* Operation builder operation service.
*
- * @param parameterBuilder the parameter builder
- * @param requestBodyService the request body service
- * @param securityParser the security parser
+ * @param parameterBuilder the parameter builder
+ * @param requestBodyService the request body service
+ * @param securityParser the security parser
* @param propertyResolverUtils the property resolver utils
* @return the operation service
*/
@@ -323,8 +328,8 @@ OperationService operationBuilder(GenericParameterService parameterBuilder, Requ
/**
* Property resolver utils property resolver utils.
*
- * @param factory the factory
- * @param messageSource the message source
+ * @param factory the factory
+ * @param messageSource the message source
* @param springDocConfigProperties the spring doc config properties
* @return the property resolver utils
*/
@@ -337,7 +342,8 @@ PropertyResolverUtils propertyResolverUtils(ConfigurableBeanFactory factory, Mes
/**
* Request body builder request body builder.
*
- * @param parameterBuilder the parameter builder
+ * @param parameterBuilder the parameter builder
+ * @param propertyResolverUtils the property resolver utils
* @return the request body builder
*/
@Bean
@@ -360,34 +366,23 @@ SecurityService securityParser(PropertyResolverUtils propertyResolverUtils) {
return new SecurityService(propertyResolverUtils);
}
- /**
- * Generic return type parser return type parser.
- *
- * @return the return type parser
- */
- @Bean
- @Lazy(false)
- ReturnTypeParser genericReturnTypeParser() {
- return new ReturnTypeParser() {};
- }
-
/**
* Parameter builder generic parameter builder.
*
- * @param propertyResolverUtils the property resolver utils
- * @param optionalDelegatingMethodParameterCustomizer the optional delegating method parameter customizer
- * @param optionalWebConversionServiceProvider the optional web conversion service provider
- * @param objectMapperProvider the object mapper provider
- * @param javadocProvider the javadoc provider
+ * @param propertyResolverUtils the property resolver utils
+ * @param optionalDelegatingMethodParameterCustomizers the optional list delegating method parameter customizer
+ * @param optionalWebConversionServiceProvider the optional web conversion service provider
+ * @param objectMapperProvider the object mapper provider
+ * @param javadocProvider the javadoc provider
* @return the generic parameter builder
*/
@Bean
@ConditionalOnMissingBean
@Lazy(false)
GenericParameterService parameterBuilder(PropertyResolverUtils propertyResolverUtils,
- Optional optionalDelegatingMethodParameterCustomizer,
+ Optional> optionalDelegatingMethodParameterCustomizers,
Optional optionalWebConversionServiceProvider, ObjectMapperProvider objectMapperProvider, Optional javadocProvider) {
- return new GenericParameterService(propertyResolverUtils, optionalDelegatingMethodParameterCustomizer,
+ return new GenericParameterService(propertyResolverUtils, optionalDelegatingMethodParameterCustomizers,
optionalWebConversionServiceProvider, objectMapperProvider, javadocProvider);
}
@@ -412,14 +407,13 @@ GlobalOpenApiCustomizer propertiesResolverForSchema(OpenAPIService openAPIServic
/**
* Spring doc providers spring doc providers.
*
- * @param actuatorProvider the actuator provider
- * @param springCloudFunctionProvider the spring cloud function provider
- * @param springSecurityOAuth2Provider the spring security o auth 2 provider
+ * @param actuatorProvider the actuator provider
+ * @param springCloudFunctionProvider the spring cloud function provider
+ * @param springSecurityOAuth2Provider the spring security o auth 2 provider
* @param repositoryRestResourceProvider the repository rest resource provider
- * @param routerFunctionProvider the router function provider
- * @param springWebProvider the spring web provider
- * @param webConversionServiceProvider the web conversion service provider
- * @param objectMapperProvider the object mapper provider
+ * @param routerFunctionProvider the router function provider
+ * @param springWebProvider the spring web provider
+ * @param objectMapperProvider the object mapper provider
* @return the spring doc providers
*/
@Bean
@@ -427,10 +421,10 @@ GlobalOpenApiCustomizer propertiesResolverForSchema(OpenAPIService openAPIServic
@Lazy(false)
SpringDocProviders springDocProviders(Optional actuatorProvider, Optional springCloudFunctionProvider, Optional springSecurityOAuth2Provider,
Optional repositoryRestResourceProvider, Optional routerFunctionProvider,
- Optional springWebProvider, Optional webConversionServiceProvider,
+ Optional springWebProvider,
ObjectMapperProvider objectMapperProvider) {
objectMapperProvider.jsonMapper().registerModule(new SpringDocRequiredModule());
- return new SpringDocProviders(actuatorProvider, springCloudFunctionProvider, springSecurityOAuth2Provider, repositoryRestResourceProvider, routerFunctionProvider, springWebProvider, webConversionServiceProvider, objectMapperProvider);
+ return new SpringDocProviders(actuatorProvider, springCloudFunctionProvider, springSecurityOAuth2Provider, repositoryRestResourceProvider, routerFunctionProvider, springWebProvider, objectMapperProvider);
}
/**
@@ -448,6 +442,7 @@ ObjectMapperProvider springdocObjectMapperProvider(SpringDocConfigProperties spr
/**
* The type Spring doc web mvc actuator configuration.
+ *
* @author bnasslashen
*/
@ConditionalOnClass(WebEndpointProperties.class)
@@ -457,7 +452,7 @@ static class SpringDocActuatorConfiguration {
/**
* Springdoc bean factory post processor 3 bean factory post processor.
*
- * @param groupedOpenApis the grouped open apis
+ * @param groupedOpenApis the grouped open apis
* @return the bean factory post processor
*/
@Bean
@@ -481,23 +476,11 @@ GlobalOperationCustomizer actuatorCustomizer(SpringDocConfigProperties springDoc
return new ActuatorOperationCustomizer(springDocConfigProperties);
}
- /**
- * Actuator customizer OpenAPI customiser.
- *
- * @param webEndpointProperties the web endpoint properties
- * @return the OpenAPI customiser
- */
- @Bean
- @Lazy(false)
- @ConditionalOnManagementPort(ManagementPortType.SAME)
- GlobalOpenApiCustomizer actuatorOpenApiCustomizer(WebEndpointProperties webEndpointProperties) {
- return new ActuatorOpenApiCustomizer(webEndpointProperties);
- }
-
}
/**
* The type Web conversion service configuration.
+ *
* @author bnasslashen
*/
@ConditionalOnClass(WebConversionService.class)
@@ -576,6 +559,7 @@ WebFluxSupportConverter webFluxSupportConverter(ObjectMapperProvider objectMappe
/**
* The type Open api resource advice.
+ *
* @author bnasslashen
*/
@RestControllerAdvice
@@ -597,34 +581,36 @@ public ResponseEntity handleNoHandlerFound(OpenApiResourceNotFound
/**
* Spring doc customizers spring doc customizers.
*
- * @param openApiCustomizers the open api customizers
- * @param operationCustomizers the operation customizers
- * @param routerOperationCustomizers the router operation customizers
+ * @param openApiCustomizers the open api customizers
+ * @param operationCustomizers the operation customizers
+ * @param routerOperationCustomizers the router operation customizers
* @param dataRestRouterOperationCustomizers the data rest router operation customizers
- * @param methodFilters the method filters
- * @param globalOpenApiCustomizers the global open api customizers
- * @param globalOperationCustomizers the global operation customizers
- * @param globalOpenApiMethodFilters the global open api method filters
+ * @param methodFilters the method filters
+ * @param globalOpenApiCustomizers the global open api customizers
+ * @param globalOperationCustomizers the global operation customizers
+ * @param globalOpenApiMethodFilters the global open api method filters
* @return the spring doc customizers
*/
@Bean
@ConditionalOnMissingBean
@Lazy(false)
- public SpringDocCustomizers springDocCustomizers(Optional> openApiCustomizers,
- Optional> operationCustomizers,
- Optional> routerOperationCustomizers,
- Optional> dataRestRouterOperationCustomizers,
- Optional> methodFilters, Optional> globalOpenApiCustomizers, Optional> globalOperationCustomizers,
- Optional> globalOpenApiMethodFilters){
+ public SpringDocCustomizers springDocCustomizers(Optional> openApiCustomizers,
+ Optional> operationCustomizers,
+ Optional> routerOperationCustomizers,
+ Optional> dataRestRouterOperationCustomizers,
+ Optional> methodFilters, Optional> globalOpenApiCustomizers,
+ Optional> globalOperationCustomizers,
+ Optional> globalOpenApiMethodFilters) {
return new SpringDocCustomizers(openApiCustomizers,
operationCustomizers,
- routerOperationCustomizers,
- dataRestRouterOperationCustomizers,
- methodFilters, globalOpenApiCustomizers, globalOperationCustomizers, globalOpenApiMethodFilters);
+ routerOperationCustomizers,
+ dataRestRouterOperationCustomizers,
+ methodFilters, globalOpenApiCustomizers, globalOperationCustomizers, globalOpenApiMethodFilters);
}
/**
* The type Querydsl provider.
+ *
* @author bnasslashen
*/
@ConditionalOnClass(value = QuerydslBindingsFactory.class)
@@ -649,4 +635,41 @@ QuerydslPredicateOperationCustomizer queryDslQuerydslPredicateOperationCustomize
return null;
}
}
+
+ /**
+ * Parameter object naming strategy customizer delegating method parameter customizer.
+ *
+ * @return the delegating method parameter customizer
+ */
+ @Bean
+ @ConditionalOnMissingBean
+ @Lazy(false)
+ ParameterObjectNamingStrategyCustomizer parameterObjectNamingStrategyCustomizer() {
+ return new ParameterObjectNamingStrategyCustomizer();
+ }
+
+ /**
+ * Global open api customizer global open api customizer.
+ *
+ * @return the global open api customizer
+ */
+ @Bean
+ @ConditionalOnMissingBean
+ @Lazy(false)
+ GlobalOpenApiCustomizer globalOpenApiCustomizer() {
+ return new OperationIdCustomizer();
+ }
+
+ /**
+ * Oas 31 model converter oas 31 model converter.
+ *
+ * @param springDocConfigProperties the spring doc config properties
+ * @return the oas 31 model converter
+ */
+ @Bean
+ @ConditionalOnMissingBean
+ @Lazy(false)
+ OAS31ModelConverter oas31ModelConverter(SpringDocConfigProperties springDocConfigProperties) {
+ return springDocConfigProperties.isOpenapi31() ? new OAS31ModelConverter() : null;
+ }
}
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocDataRestConfiguration.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocDataRestConfiguration.java
index f36393e54..f7d17aefb 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocDataRestConfiguration.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocDataRestConfiguration.java
@@ -3,23 +3,25 @@
* *
* * *
* * * *
- * * * * * Copyright 2019-2022 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
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
* * * * *
- * * * * * https://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.springdoc.core.configuration;
@@ -53,21 +55,16 @@
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.hateoas.HateoasProperties;
-import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportRuntimeHints;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Primary;
import org.springframework.data.domain.Sort;
-import org.springframework.data.mapping.context.PersistentEntities;
-import org.springframework.data.repository.support.Repositories;
import org.springframework.data.rest.core.config.RepositoryRestConfiguration;
-import org.springframework.data.rest.core.mapping.ResourceMappings;
import org.springframework.data.rest.webmvc.PersistentEntityResourceAssembler;
import org.springframework.data.rest.webmvc.RepositoryRestHandlerMapping;
import org.springframework.data.rest.webmvc.RootResourceInformation;
-import org.springframework.data.rest.webmvc.mapping.Associations;
import org.springframework.data.rest.webmvc.support.DefaultedPageable;
import org.springframework.data.rest.webmvc.support.ETag;
import org.springframework.hateoas.server.LinkRelationProvider;
@@ -76,6 +73,7 @@
/**
* The type Spring doc data rest configuration.
+ *
* @author bnasslashen
*/
@Lazy(false)
@@ -91,8 +89,8 @@ public class SpringDocDataRestConfiguration {
* Hal provider data rest hal provider.
*
* @param repositoryRestConfiguration the repository rest configuration
- * @param hateoasPropertiesOptional the hateoas properties optional
- * @param objectMapperProvider the object mapper provider
+ * @param hateoasPropertiesOptional the hateoas properties optional
+ * @param objectMapperProvider the object mapper provider
* @return the data rest hal provider
*/
@Bean
@@ -105,6 +103,7 @@ DataRestHalProvider halProvider(Optional repository
/**
* The type Spring repository rest resource provider configuration.
+ *
* @author bnasslashen
*/
@Lazy(false)
@@ -121,34 +120,28 @@ static class SpringRepositoryRestResourceProviderConfiguration {
/**
* Spring repository rest resource provider spring repository rest resource provider.
*
- * @param mappings the mappings
- * @param repositories the repositories
- * @param associations the associations
- * @param applicationContext the application context
* @param dataRestRouterOperationService the data rest router operation service
- * @param persistentEntities the persistent entities
- * @param mapper the mapper
- * @param springDocDataRestUtils the spring doc data rest utils
+ * @param mapper the mapper
+ * @param springDocDataRestUtils the spring doc data rest utils
* @return the spring repository rest resource provider
*/
@Bean
@ConditionalOnMissingBean
@Lazy(false)
- SpringRepositoryRestResourceProvider springRepositoryRestResourceProvider(ResourceMappings mappings,
- Repositories repositories, Associations associations, ApplicationContext applicationContext,
- DataRestRouterOperationService dataRestRouterOperationService, PersistentEntities persistentEntities,
- ObjectMapper mapper, SpringDocDataRestUtils springDocDataRestUtils) {
- return new SpringRepositoryRestResourceProvider(mappings, repositories, associations, applicationContext,
- dataRestRouterOperationService, persistentEntities, mapper, springDocDataRestUtils);
+ SpringRepositoryRestResourceProvider springRepositoryRestResourceProvider(DataRestRouterOperationService dataRestRouterOperationService,
+ ObjectMapper mapper,
+ SpringDocDataRestUtils springDocDataRestUtils) {
+ return new SpringRepositoryRestResourceProvider(
+ dataRestRouterOperationService, mapper, springDocDataRestUtils);
}
/**
* Data rest router operation builder data rest router operation service.
*
- * @param dataRestOperationService the data rest operation service
- * @param springDocConfigProperties the spring doc config properties
+ * @param dataRestOperationService the data rest operation service
+ * @param springDocConfigProperties the spring doc config properties
* @param repositoryRestConfiguration the repository rest configuration
- * @param dataRestHalProvider the data rest hal provider
+ * @param dataRestHalProvider the data rest hal provider
* @return the data rest router operation service
*/
@Bean
@@ -162,10 +155,10 @@ DataRestRouterOperationService dataRestRouterOperationBuilder(DataRestOperationS
/**
* Data rest operation builder data rest operation builder.
*
- * @param dataRestRequestService the data rest request builder
- * @param tagsBuilder the tags builder
+ * @param dataRestRequestService the data rest request builder
+ * @param tagsBuilder the tags builder
* @param dataRestResponseService the data rest response builder
- * @param operationService the operation service
+ * @param operationService the operation service
* @return the data rest operation builder
*/
@Bean
@@ -180,10 +173,10 @@ DataRestOperationService dataRestOperationBuilder(DataRestRequestService dataRes
* Data rest request builder data rest request builder.
*
* @param localSpringDocParameterNameDiscoverer the local spring doc parameter name discoverer
- * @param parameterBuilder the parameter builder
- * @param requestBodyService the request body builder
- * @param requestBuilder the request builder
- * @param springDocDataRestUtils the spring doc data rest utils
+ * @param parameterBuilder the parameter builder
+ * @param requestBodyService the request body builder
+ * @param requestBuilder the request builder
+ * @param springDocDataRestUtils the spring doc data rest utils
* @return the data rest request builder
*/
@Bean
@@ -225,7 +218,7 @@ DataRestTagsService dataRestTagsBuilder(OpenAPIService openAPIService) {
/**
* Spring doc data rest utils spring doc data rest utils.
*
- * @param linkRelationProvider the link relation provider
+ * @param linkRelationProvider the link relation provider
* @param repositoryRestConfiguration the repository rest configuration
* @return the spring doc data rest utils
*/
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocFunctionCatalogConfiguration.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocFunctionCatalogConfiguration.java
index 6735bfe6d..e50f4b00f 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocFunctionCatalogConfiguration.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocFunctionCatalogConfiguration.java
@@ -3,23 +3,25 @@
* *
* * *
* * * *
- * * * * * Copyright 2019-2022 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
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
* * * * *
- * * * * * https://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.springdoc.core.configuration;
@@ -43,6 +45,7 @@
/**
* The type Spring doc function catalog configuration.
+ *
* @author bnasslahsen
*/
@Lazy(false)
@@ -56,7 +59,7 @@ public class SpringDocFunctionCatalogConfiguration {
/**
* Spring cloud function provider spring cloud function provider.
*
- * @param functionCatalog the function catalog
+ * @param functionCatalog the function catalog
* @param springDocConfigProperties the spring doc config properties
* @return the spring cloud function provider
*/
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocGroovyConfiguration.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocGroovyConfiguration.java
index 68d96b7fc..a5d19c91b 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocGroovyConfiguration.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocGroovyConfiguration.java
@@ -3,23 +3,25 @@
* *
* * *
* * * *
- * * * * * Copyright 2019-2022 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
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
* * * * *
- * * * * * https://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.springdoc.core.configuration;
@@ -40,6 +42,7 @@
/**
* The type Spring doc groovy configuration.
+ *
* @author bnasslahsen
*/
@Lazy(false)
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocHateoasConfiguration.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocHateoasConfiguration.java
index 54f13f9b2..5c35852ba 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocHateoasConfiguration.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocHateoasConfiguration.java
@@ -3,23 +3,25 @@
* *
* * *
* * * *
- * * * * * Copyright 2019-2022 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
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
* * * * *
- * * * * * https://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.springdoc.core.configuration;
@@ -29,7 +31,7 @@
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import org.springdoc.core.converters.CollectionModelContentConverter;
-import org.springdoc.core.converters.RepresentationModelLinksOASMixin;
+import org.springdoc.core.converters.HateoasLinksConverter;
import org.springdoc.core.customizers.GlobalOpenApiCustomizer;
import org.springdoc.core.customizers.OpenApiHateoasLinksCustomizer;
import org.springdoc.core.properties.SpringDocConfigProperties;
@@ -47,11 +49,11 @@
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.hateoas.Links;
-import org.springframework.hateoas.RepresentationModel;
import org.springframework.hateoas.server.LinkRelationProvider;
/**
* The type Spring doc hateoas configuration.
+ *
* @author bnasslahsen
*/
@Lazy(false)
@@ -66,7 +68,7 @@ public class SpringDocHateoasConfiguration {
* Hateoas hal provider hateoas hal provider.
*
* @param hateoasPropertiesOptional the hateoas properties optional
- * @param objectMapperProvider the object mapper provider
+ * @param objectMapperProvider the object mapper provider
* @return the hateoas hal provider
*/
@Bean
@@ -79,7 +81,7 @@ HateoasHalProvider hateoasHalProvider(Optional hateoasPropert
/**
* Collection model content converter collection model content converter.
*
- * @param halProvider the hal provider
+ * @param halProvider the hal provider
* @param linkRelationProvider the link relation provider
* @return the collection model content converter
*/
@@ -94,22 +96,34 @@ CollectionModelContentConverter collectionModelContentConverter(HateoasHalProvid
* Registers an OpenApiCustomizer and a jackson mixin to ensure the definition of `Links` matches the serialized
* output. This is done because the customer serializer converts the data to a map before serializing it.
*
- * @param halProvider the hal provider
+ * @param halProvider the hal provider
* @param springDocConfigProperties the spring doc config properties
- * @param objectMapperProvider the object mapper provider
* @return the open api customizer
- * @see org.springframework.hateoas.mediatype.hal.Jackson2HalModule.HalLinkListSerializer#serialize(Links, JsonGenerator, SerializerProvider) org.springframework.hateoas.mediatype.hal.Jackson2HalModule.HalLinkListSerializer#serialize(Links, JsonGenerator, SerializerProvider)org.springframework.hateoas.mediatype.hal.Jackson2HalModule.HalLinkListSerializer#serialize(Links, JsonGenerator, SerializerProvider)org.springframework.hateoas.mediatype.hal.Jackson2HalModule.HalLinkListSerializer#serialize(Links, JsonGenerator, SerializerProvider)org.springframework.hateoas.mediatype.hal.Jackson2HalModule.HalLinkListSerializer#serialize(Links, JsonGenerator, SerializerProvider)org.springframework.hateoas.mediatype.hal.Jackson2HalModule.HalLinkListSerializer#serialize(Links, JsonGenerator, SerializerProvider)
+ * @see org.springframework.hateoas.mediatype.hal.Jackson2HalModule.HalLinkListSerializer#serialize(Links, JsonGenerator, SerializerProvider) org.springframework.hateoas.mediatype.hal.Jackson2HalModule.HalLinkListSerializer#serialize(Links, JsonGenerator, SerializerProvider)org.springframework.hateoas.mediatype.hal.Jackson2HalModule.HalLinkListSerializer#serialize(Links, JsonGenerator, SerializerProvider)org.springframework.hateoas.mediatype.hal.Jackson2HalModule.HalLinkListSerializer#serialize(Links, JsonGenerator, SerializerProvider)org.springframework.hateoas.mediatype.hal.Jackson2HalModule.HalLinkListSerializer#serialize(Links, JsonGenerator, SerializerProvider)org.springframework.hateoas.mediatype.hal.Jackson2HalModule.HalLinkListSerializer#serialize(Links, JsonGenerator, SerializerProvider)org.springframework.hateoas.mediatype.hal.Jackson2HalModule.HalLinkListSerializer#serialize(Links, JsonGenerator, SerializerProvider)org.springframework.hateoas.mediatype.hal.Jackson2HalModule.HalLinkListSerializer#serialize(Links, JsonGenerator, SerializerProvider)
*/
@Bean(Constants.LINKS_SCHEMA_CUSTOMISER)
@ConditionalOnMissingBean(name = Constants.LINKS_SCHEMA_CUSTOMISER)
@Lazy(false)
- GlobalOpenApiCustomizer linksSchemaCustomizer(HateoasHalProvider halProvider, SpringDocConfigProperties springDocConfigProperties,
- ObjectMapperProvider objectMapperProvider) {
+ GlobalOpenApiCustomizer linksSchemaCustomizer(HateoasHalProvider halProvider, SpringDocConfigProperties springDocConfigProperties) {
if (!halProvider.isHalEnabled()) {
return openApi -> {
};
}
- objectMapperProvider.jsonMapper().addMixIn(RepresentationModel.class, RepresentationModelLinksOASMixin.class);
return new OpenApiHateoasLinksCustomizer(springDocConfigProperties);
}
+
+ /**
+ * Hateoas links converter hateoas links converter.
+ *
+ * @param springDocObjectMapper the spring doc object mapper
+ * @return the hateoas links converter
+ */
+ @Bean
+ @ConditionalOnMissingBean
+ @Lazy(false)
+ HateoasLinksConverter hateoasLinksConverter(ObjectMapperProvider springDocObjectMapper) {
+ return new HateoasLinksConverter(springDocObjectMapper) ;
+ }
+
+
}
\ No newline at end of file
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocJacksonKotlinModuleConfiguration.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocJacksonKotlinModuleConfiguration.java
index a8fb5b41a..5316593b0 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocJacksonKotlinModuleConfiguration.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocJacksonKotlinModuleConfiguration.java
@@ -1,3 +1,29 @@
+/*
+ *
+ * *
+ * * *
+ * * * *
+ * * * * *
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.springdoc.core.configuration;
import com.fasterxml.jackson.module.kotlin.KotlinModule;
@@ -24,14 +50,14 @@
@ConditionalOnExpression("${springdoc.api-docs.enabled:true} and ${springdoc.enable-kotlin:true}")
@ConditionalOnWebApplication
@ConditionalOnBean(SpringDocConfiguration.class)
-class SpringDocJacksonKotlinModuleConfiguration {
+public class SpringDocJacksonKotlinModuleConfiguration {
/**
* Instantiates a new objectMapperProvider with a kotlin module.
*
* @param springDocConfigProperties the spring doc config properties
+ * @return the object mapper provider
*/
-
@Bean
@Primary
ObjectMapperProvider springdocKotlinObjectMapperProvider(SpringDocConfigProperties springDocConfigProperties) {
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocJavadocConfiguration.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocJavadocConfiguration.java
index 76adbdcbf..981878603 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocJavadocConfiguration.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocJavadocConfiguration.java
@@ -3,23 +3,25 @@
* *
* * *
* * * *
- * * * * * Copyright 2019-2022 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
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
* * * * *
- * * * * * https://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.springdoc.core.configuration;
@@ -38,9 +40,12 @@
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
+import org.springframework.core.Ordered;
+import org.springframework.core.annotation.Order;
/**
* The type Spring doc security configuration.
+ *
* @author bnasslahsen
*/
@Lazy(false)
@@ -66,13 +71,14 @@ SpringDocJavadocProvider springDocJavadocProvider() {
/**
* Javadoc property customizer javadoc property customizer.
*
- * @param javadocProvider the javadoc provider
+ * @param javadocProvider the javadoc provider
* @param objectMapperProvider the object mapper provider
* @return the javadoc property customizer
*/
@Bean
@ConditionalOnMissingBean
@Lazy(false)
+ @Order(Ordered.HIGHEST_PRECEDENCE)
JavadocPropertyCustomizer javadocPropertyCustomizer(JavadocProvider javadocProvider, ObjectMapperProvider objectMapperProvider) {
return new JavadocPropertyCustomizer(javadocProvider, objectMapperProvider);
}
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocKotlinConfiguration.kt b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocKotlinConfiguration.kt
index 7c7dd6070..d11d0cb91 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocKotlinConfiguration.kt
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocKotlinConfiguration.kt
@@ -1,9 +1,35 @@
+/*
+ *
+ * *
+ * * *
+ * * * *
+ * * * * *
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.springdoc.core.configuration
import io.swagger.v3.oas.annotations.Parameter
-import io.swagger.v3.oas.models.media.ByteArraySchema
+import org.springdoc.core.customizers.KotlinDeprecatedPropertyCustomizer
import org.springdoc.core.customizers.ParameterCustomizer
-import org.springdoc.core.parsers.KotlinCoroutinesReturnTypeParser
+import org.springdoc.core.providers.ObjectMapperProvider
import org.springdoc.core.utils.Constants
import org.springdoc.core.utils.SpringDocUtils
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean
@@ -43,23 +69,11 @@ class SpringDocKotlinConfiguration() {
*/
init {
SpringDocUtils.getConfig()
+ .addResponseTypeToIgnore(Unit::class.java)
.addRequestWrapperToIgnore(Continuation::class.java)
- .replaceWithSchema(ByteArray::class.java, ByteArraySchema())
.addDeprecatedType(Deprecated::class.java)
}
- /**
- * Kotlin coroutines return type parser kotlin coroutines return type parser.
- *
- * @return the kotlin coroutines return type parser
- */
- @Bean
- @Lazy(false)
- @ConditionalOnMissingBean
- fun kotlinCoroutinesReturnTypeParser(): KotlinCoroutinesReturnTypeParser {
- return KotlinCoroutinesReturnTypeParser()
- }
-
/**
* Kotlin springdoc-openapi ParameterCustomizer
*
@@ -92,9 +106,13 @@ class SpringDocKotlinConfiguration() {
// parameter is not required if a default value is provided in @RequestParam
else if (requestParam != null && requestParam.defaultValue != ValueConstants.DEFAULT_NONE)
parameterModel.required = false
- else
+ else{
+ val isJavaNullableAnnotationPresent = methodParameter.parameterAnnotations.any {
+ it.annotationClass.qualifiedName == "jakarta.annotation.Nullable"
+ }
parameterModel.required =
- kParameter.type.isMarkedNullable == false
+ kParameter.type.isMarkedNullable == false && !isJavaNullableAnnotationPresent
+ }
}
}
return@ParameterCustomizer parameterModel
@@ -110,4 +128,15 @@ class SpringDocKotlinConfiguration() {
return kotlinFunction.parameters[parameterIndex + 1]
}
+ @ConditionalOnClass(name = ["kotlin.reflect.full.KClasses"])
+ class KotlinReflectDependingConfiguration {
+
+ @Bean
+ @Lazy(false)
+ @ConditionalOnMissingBean
+ fun kotlinDeprecatedPropertyCustomizer(objectMapperProvider: ObjectMapperProvider): KotlinDeprecatedPropertyCustomizer {
+ return KotlinDeprecatedPropertyCustomizer(objectMapperProvider)
+ }
+ }
+
}
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocKotlinxConfiguration.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocKotlinxConfiguration.java
index f80b58154..ca51110ad 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocKotlinxConfiguration.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocKotlinxConfiguration.java
@@ -3,23 +3,25 @@
* *
* * *
* * * *
- * * * * * Copyright 2019-2022 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
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
* * * * *
- * * * * * https://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.springdoc.core.configuration;
@@ -37,6 +39,7 @@
/**
* The type Spring doc kotlinx configuration.
+ *
* @author bnasslahsen
*/
@Lazy(false)
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocPageableConfiguration.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocPageableConfiguration.java
index 0dd0a9e50..d77d5dbc0 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocPageableConfiguration.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocPageableConfiguration.java
@@ -3,32 +3,34 @@
* *
* * *
* * * *
- * * * * * Copyright 2019-2022 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
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
* * * * *
- * * * * * https://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.springdoc.core.configuration;
import java.util.Optional;
+import org.springdoc.core.converters.PageOpenAPIConverter;
import org.springdoc.core.converters.PageableOpenAPIConverter;
import org.springdoc.core.customizers.DataRestDelegatingMethodParameterCustomizer;
-import org.springdoc.core.customizers.DelegatingMethodParameterCustomizer;
import org.springdoc.core.providers.ObjectMapperProvider;
import org.springdoc.core.providers.RepositoryRestConfigurationProvider;
import org.springdoc.core.providers.SpringDataWebPropertiesProvider;
@@ -42,6 +44,9 @@
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.domain.Pageable;
+import org.springframework.data.web.PagedModel;
+import org.springframework.data.web.config.EnableSpringDataWebSupport;
+import org.springframework.data.web.config.SpringDataWebSettings;
import static org.springdoc.core.utils.Constants.SPRINGDOC_ENABLED;
import static org.springdoc.core.utils.Constants.SPRINGDOC_PAGEABLE_CONVERTER_ENABLED;
@@ -49,6 +54,7 @@
/**
* The type Spring doc pageable configuration.
+ *
* @author bnasslahsen
*/
@Lazy(false)
@@ -75,17 +81,36 @@ PageableOpenAPIConverter pageableOpenAPIConverter(ObjectMapperProvider objectMap
return new PageableOpenAPIConverter(objectMapperProvider);
}
+ /**
+ * Page open api converter.
+ *
+ * @param settings the settings
+ * @param objectMapperProvider the object mapper provider
+ * @return the page open api converter
+ */
+ @Bean
+ @ConditionalOnMissingBean
+ @ConditionalOnClass({ PagedModel.class, SpringDataWebSettings.class })
+ @Lazy(false)
+ PageOpenAPIConverter pageOpenAPIConverter(Optional settings,
+ ObjectMapperProvider objectMapperProvider) {
+ boolean replacePageWithPagedModel = settings.map(SpringDataWebSettings::pageSerializationMode)
+ .map(EnableSpringDataWebSupport.PageSerializationMode.VIA_DTO::equals)
+ .orElse(false);
+ return new PageOpenAPIConverter(replacePageWithPagedModel, objectMapperProvider);
+ }
+
/**
* Delegating method parameter customizer delegating method parameter customizer.
*
* @param optionalSpringDataWebPropertiesProvider the optional spring data web properties
- * @param optionalRepositoryRestConfiguration the optional repository rest configuration
+ * @param optionalRepositoryRestConfiguration the optional repository rest configuration
* @return the delegating method parameter customizer
*/
@Bean
@ConditionalOnMissingBean
@Lazy(false)
- DelegatingMethodParameterCustomizer delegatingMethodParameterCustomizer(Optional optionalSpringDataWebPropertiesProvider, Optional optionalRepositoryRestConfiguration) {
+ DataRestDelegatingMethodParameterCustomizer dataRestDelegatingMethodParameterCustomizer(Optional optionalSpringDataWebPropertiesProvider, Optional optionalRepositoryRestConfiguration) {
return new DataRestDelegatingMethodParameterCustomizer(optionalSpringDataWebPropertiesProvider, optionalRepositoryRestConfiguration);
}
}
\ No newline at end of file
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocRequiredModule.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocRequiredModule.java
index 7278ca597..1c2380106 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocRequiredModule.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocRequiredModule.java
@@ -2,22 +2,26 @@
*
* *
* * *
- * * * * Copyright 2019-2022 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
+ * * * * *
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
+ * * * * *
* * * *
- * * * * https://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.springdoc.core.configuration;
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocSecurityConfiguration.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocSecurityConfiguration.java
index 465a9bc4a..051b2b20e 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocSecurityConfiguration.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocSecurityConfiguration.java
@@ -3,29 +3,30 @@
* *
* * *
* * * *
- * * * * * Copyright 2019-2022 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
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
* * * * *
- * * * * * https://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.springdoc.core.configuration;
-import java.lang.reflect.Field;
import java.util.Optional;
import io.swagger.v3.oas.models.Operation;
@@ -58,10 +59,10 @@
import org.springframework.http.HttpStatus;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
+import org.springframework.security.oauth2.client.annotation.RegisteredOAuth2AuthorizedClient;
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
import org.springframework.security.web.FilterChainProxy;
import org.springframework.security.web.SecurityFilterChain;
-import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
@@ -73,6 +74,7 @@
/**
* The type Spring doc security configuration.
+ *
* @author bnasslahsen
*/
@Lazy(false)
@@ -84,6 +86,9 @@
@ImportRuntimeHints(SpringDocSecurityHints.class)
public class SpringDocSecurityConfiguration {
+ /**
+ * The constant LOGGER.
+ */
private static final Logger LOGGER = LoggerFactory.getLogger(SpringDocSecurityConfiguration.class);
static {
@@ -109,7 +114,7 @@ class SpringSecurityLoginEndpointConfiguration {
@Bean
@ConditionalOnProperty(SPRINGDOC_SHOW_LOGIN_ENDPOINT)
@Lazy(false)
- OpenApiCustomizer springSecurityLoginEndpointCustomiser(ApplicationContext applicationContext) {
+ OpenApiCustomizer springSecurityLoginEndpointCustomizer(ApplicationContext applicationContext) {
FilterChainProxy filterChainProxy = applicationContext.getBean(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME, FilterChainProxy.class);
return openAPI -> {
for (SecurityFilterChain filterChain : filterChainProxy.getFilterChains()) {
@@ -132,9 +137,8 @@ OpenApiCustomizer springSecurityLoginEndpointCustomiser(ApplicationContext appli
String mediaType = org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
if (optionalDefaultLoginPageGeneratingFilter.isPresent()) {
DefaultLoginPageGeneratingFilter defaultLoginPageGeneratingFilter = optionalDefaultLoginPageGeneratingFilter.get();
- Field formLoginEnabledField = FieldUtils.getDeclaredField(DefaultLoginPageGeneratingFilter.class, "formLoginEnabled", true);
try {
- boolean formLoginEnabled = (boolean) formLoginEnabledField.get(defaultLoginPageGeneratingFilter);
+ boolean formLoginEnabled = (boolean) FieldUtils.readDeclaredField(defaultLoginPageGeneratingFilter, "formLoginEnabled", true);
if (formLoginEnabled)
mediaType = org.springframework.http.MediaType.APPLICATION_FORM_URLENCODED_VALUE;
}
@@ -146,19 +150,16 @@ OpenApiCustomizer springSecurityLoginEndpointCustomiser(ApplicationContext appli
operation.requestBody(requestBody);
ApiResponses apiResponses = new ApiResponses();
apiResponses.addApiResponse(String.valueOf(HttpStatus.OK.value()), new ApiResponse().description(HttpStatus.OK.getReasonPhrase()));
- apiResponses.addApiResponse(String.valueOf(HttpStatus.FORBIDDEN.value()), new ApiResponse().description(HttpStatus.FORBIDDEN.getReasonPhrase()));
+ apiResponses.addApiResponse(String.valueOf(HttpStatus.UNAUTHORIZED.value()), new ApiResponse().description(HttpStatus.UNAUTHORIZED.getReasonPhrase()));
operation.responses(apiResponses);
operation.addTagsItem("login-endpoint");
PathItem pathItem = new PathItem().post(operation);
try {
- Field requestMatcherField = AbstractAuthenticationProcessingFilter.class.getDeclaredField("requiresAuthenticationRequestMatcher");
- requestMatcherField.setAccessible(true);
- AntPathRequestMatcher requestMatcher = (AntPathRequestMatcher) requestMatcherField.get(usernamePasswordAuthenticationFilter);
+ AntPathRequestMatcher requestMatcher = (AntPathRequestMatcher)FieldUtils.readField(usernamePasswordAuthenticationFilter, "requiresAuthenticationRequestMatcher", true);
String loginPath = requestMatcher.getPattern();
- requestMatcherField.setAccessible(false);
openAPI.getPaths().addPathItem(loginPath, pathItem);
}
- catch (NoSuchFieldException | IllegalAccessException |
+ catch (IllegalAccessException |
ClassCastException ignored) {
// Exception escaped
LOGGER.trace(ignored.getMessage());
@@ -169,6 +170,9 @@ OpenApiCustomizer springSecurityLoginEndpointCustomiser(ApplicationContext appli
}
}
+ /**
+ * The type Spring doc security o auth 2 configuration.
+ */
@Lazy(false)
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(OAuth2AuthorizationService.class)
@@ -186,4 +190,19 @@ GlobalOpenApiCustomizer springDocSecurityOAuth2Customizer() {
return new SpringDocSecurityOAuth2Customizer();
}
}
+
+ /**
+ * The type Spring doc security o auth 2 client configuration.
+ */
+ @Lazy(false)
+ @Configuration(proxyBeanMethods = false)
+ @ConditionalOnClass(RegisteredOAuth2AuthorizedClient.class)
+ class SpringDocSecurityOAuth2ClientConfiguration {
+
+ static {
+ getConfig()
+ .addAnnotationsToIgnore(RegisteredOAuth2AuthorizedClient.class);
+ }
+
+ }
}
\ No newline at end of file
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocSecurityOAuth2Customizer.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocSecurityOAuth2Customizer.java
index 871ebdbb6..94b933eca 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocSecurityOAuth2Customizer.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocSecurityOAuth2Customizer.java
@@ -1,3 +1,29 @@
+/*
+ *
+ * *
+ * * *
+ * * * *
+ * * * * *
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.springdoc.core.configuration;
import java.lang.reflect.Field;
@@ -18,6 +44,7 @@
import io.swagger.v3.oas.models.media.StringSchema;
import io.swagger.v3.oas.models.parameters.HeaderParameter;
import io.swagger.v3.oas.models.parameters.Parameter;
+import io.swagger.v3.oas.models.parameters.PathParameter;
import io.swagger.v3.oas.models.parameters.RequestBody;
import io.swagger.v3.oas.models.responses.ApiResponse;
import io.swagger.v3.oas.models.responses.ApiResponses;
@@ -55,6 +82,7 @@
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.OrRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
+import org.springframework.util.ReflectionUtils;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
import static org.springframework.http.MediaType.TEXT_HTML_VALUE;
@@ -110,7 +138,7 @@ public void customise(OpenAPI openAPI) {
* @param securityFilterChain the security filter chain
* @param openapi31 the openapi 31
*/
- private void getOAuth2TokenRevocationEndpointFilter(OpenAPI openAPI, SecurityFilterChain securityFilterChain, boolean openapi31) {
+ private void getOAuth2TokenRevocationEndpointFilter(OpenAPI openAPI, SecurityFilterChain securityFilterChain, boolean openapi31) {
Object oAuth2EndpointFilter =
new SpringDocSecurityOAuth2EndpointUtils(OAuth2TokenRevocationEndpointFilter.class).findEndpoint(securityFilterChain);
if (oAuth2EndpointFilter != null) {
@@ -168,14 +196,24 @@ private void getOAuth2TokenIntrospectionEndpointFilter(OpenAPI openAPI, Security
* @param openapi31 the openapi 31
*/
private void getOAuth2AuthorizationServerMetadataEndpoint(OpenAPI openAPI, SecurityFilterChain securityFilterChain, boolean openapi31) {
+ ClassauthorizationServerMetadataEndpointClass = OAuth2AuthorizationServerMetadataEndpointFilter.class;
Object oAuth2EndpointFilter =
- new SpringDocSecurityOAuth2EndpointUtils(OAuth2AuthorizationServerMetadataEndpointFilter.class).findEndpoint(securityFilterChain);
+ new SpringDocSecurityOAuth2EndpointUtils(authorizationServerMetadataEndpointClass).findEndpoint(securityFilterChain);
if (oAuth2EndpointFilter != null) {
ApiResponses apiResponses = new ApiResponses();
buildApiResponsesOnSuccess(apiResponses, AnnotationsUtils.resolveSchemaFromType(SpringDocOAuth2AuthorizationServerMetadata.class, openAPI.getComponents(), null, openapi31));
buildApiResponsesOnInternalServerError(apiResponses);
Operation operation = buildOperation(apiResponses);
- buildPath(oAuth2EndpointFilter, REQUEST_MATCHER, openAPI, operation, HttpMethod.GET);
+ Field field = ReflectionUtils.findField(authorizationServerMetadataEndpointClass, "DEFAULT_OAUTH2_AUTHORIZATION_SERVER_METADATA_ENDPOINT_URI");
+ if (field != null) {
+ ReflectionUtils.makeAccessible(field);
+ String defaultOauth2MetadataUri = (String) ReflectionUtils.getField(field, null);
+ openAPI.getPaths().addPathItem(defaultOauth2MetadataUri , new PathItem().get(operation));
+ operation = buildOperation(apiResponses);
+ operation.addParametersItem(new PathParameter().name("subpath").schema(new StringSchema()));
+ operation.summary("Valid when multiple issuers are allowed");
+ openAPI.getPaths().addPathItem(defaultOauth2MetadataUri+"/{subpath}" , new PathItem().get(operation));
+ }
}
}
@@ -245,7 +283,7 @@ private void getOAuth2TokenEndpoint(OpenAPI openAPI, SecurityFilterChain securit
String mediaType = org.springframework.http.MediaType.APPLICATION_FORM_URLENCODED_VALUE;
RequestBody requestBody = new RequestBody().content(new Content().addMediaType(mediaType, new MediaType().schema(requestSchema)));
operation.setRequestBody(requestBody);
- operation.addParametersItem(new HeaderParameter().name("Authorization"));
+ operation.addParametersItem(new HeaderParameter().name("Authorization").schema(new StringSchema()));
buildPath(oAuth2EndpointFilter, "tokenEndpointMatcher", openAPI, operation, HttpMethod.POST);
}
@@ -270,8 +308,8 @@ private void getOAuth2AuthorizationEndpoint(OpenAPI openAPI, SecurityFilterChain
apiResponses.addApiResponse(String.valueOf(HttpStatus.OK.value()), response);
buildApiResponsesOnInternalServerError(apiResponses);
buildApiResponsesOnBadRequest(apiResponses, openAPI, openapi31);
- apiResponses.addApiResponse(String.valueOf(HttpStatus.MOVED_TEMPORARILY.value()),
- new ApiResponse().description(HttpStatus.MOVED_TEMPORARILY.getReasonPhrase())
+ apiResponses.addApiResponse(String.valueOf(HttpStatus.FOUND.value()),
+ new ApiResponse().description(HttpStatus.FOUND.getReasonPhrase())
.addHeaderObject("Location", new Header().schema(new StringSchema())));
Operation operation = buildOperation(apiResponses);
Schema> schema = new ObjectSchema().additionalProperties(new StringSchema());
@@ -288,22 +326,33 @@ private void getOAuth2AuthorizationEndpoint(OpenAPI openAPI, SecurityFilterChain
* @param openapi31 the openapi 31
*/
private void getOidcProviderConfigurationEndpoint(OpenAPI openAPI, SecurityFilterChain securityFilterChain, boolean openapi31) {
+ Class oidcProviderConfigurationEndpointFilterClass = OidcProviderConfigurationEndpointFilter.class;
Object oAuth2EndpointFilter =
- new SpringDocSecurityOAuth2EndpointUtils(OidcProviderConfigurationEndpointFilter.class).findEndpoint(securityFilterChain);
+ new SpringDocSecurityOAuth2EndpointUtils(oidcProviderConfigurationEndpointFilterClass).findEndpoint(securityFilterChain);
if (oAuth2EndpointFilter != null) {
ApiResponses apiResponses = new ApiResponses();
buildApiResponsesOnSuccess(apiResponses, AnnotationsUtils.resolveSchemaFromType(SpringDocOidcProviderConfiguration.class, openAPI.getComponents(), null, openapi31));
buildApiResponsesOnInternalServerError(apiResponses);
Operation operation = buildOperation(apiResponses);
- buildPath(oAuth2EndpointFilter, REQUEST_MATCHER, openAPI, operation, HttpMethod.GET);
+
+ Field field = ReflectionUtils.findField(oidcProviderConfigurationEndpointFilterClass, "DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI");
+ if (field != null) {
+ ReflectionUtils.makeAccessible(field);
+ String defaultOidcConfigUri = (String) ReflectionUtils.getField(field, null);
+ openAPI.getPaths().addPathItem(defaultOidcConfigUri , new PathItem().get(operation));
+ operation = buildOperation(apiResponses);
+ operation.addParametersItem(new PathParameter().name("subpath").schema(new StringSchema()));
+ operation.summary("Valid when multiple issuers are allowed");
+ openAPI.getPaths().addPathItem("/{subpath}"+defaultOidcConfigUri , new PathItem().get(operation));
+ }
}
}
/**
* Gets OpenID UserInfo endpoint filter
*
- * @param openAPI the open api
+ * @param openAPI the open api
* @param securityFilterChain the security filter chain
*/
private void getOidcUserInfoEndpoint(OpenAPI openAPI, SecurityFilterChain securityFilterChain) {
@@ -346,7 +395,7 @@ private void getOidcClientRegistrationEndpoint(OpenAPI openAPI, SecurityFilterCh
String mediaType = APPLICATION_JSON_VALUE;
RequestBody requestBody = new RequestBody().content(new Content().addMediaType(mediaType, new MediaType().schema(schema)));
operation.setRequestBody(requestBody);
- operation.addParametersItem(new HeaderParameter().name("Authorization"));
+ operation.addParametersItem(new HeaderParameter().name("Authorization").schema(new StringSchema()));
buildPath(oAuth2EndpointFilter, "clientRegistrationEndpointMatcher", openAPI, operation, HttpMethod.POST);
}
@@ -369,7 +418,7 @@ private Operation buildOperation(ApiResponses apiResponses) {
* Build api responses api responses on success.
*
* @param apiResponses the api responses
- * @param schema the schema
+ * @param schema the schema
* @return the api responses
*/
private ApiResponses buildApiResponsesOnSuccess(ApiResponses apiResponses, Schema schema) {
@@ -384,7 +433,7 @@ private ApiResponses buildApiResponsesOnSuccess(ApiResponses apiResponses, Schem
* Build api responses api responses on created.
*
* @param apiResponses the api responses
- * @param schema the schema
+ * @param schema the schema
* @return the api responses
*/
private ApiResponses buildApiResponsesOnCreated(ApiResponses apiResponses, Schema schema) {
@@ -437,26 +486,23 @@ private static void buildOAuth2Error(OpenAPI openAPI, ApiResponses apiResponses,
/**
* Build path.
*
- * @param oAuth2EndpointFilter the o auth 2 endpoint filter
+ * @param oAuth2EndpointFilter the o auth 2 endpoint filter
* @param authorizationEndpointMatcher the authorization endpoint matcher
- * @param openAPI the open api
- * @param operation the operation
- * @param requestMethod the request method
+ * @param openAPI the open api
+ * @param operation the operation
+ * @param requestMethod the request method
*/
private void buildPath(Object oAuth2EndpointFilter, String authorizationEndpointMatcher, OpenAPI openAPI, Operation operation, HttpMethod requestMethod) {
try {
- Field tokenEndpointMatcherField = FieldUtils.getDeclaredField(oAuth2EndpointFilter.getClass(), authorizationEndpointMatcher, true);
- RequestMatcher endpointMatcher = (RequestMatcher) tokenEndpointMatcherField.get(oAuth2EndpointFilter);
+ RequestMatcher endpointMatcher = (RequestMatcher) FieldUtils.readDeclaredField(oAuth2EndpointFilter, authorizationEndpointMatcher, true);
String path = null;
if (endpointMatcher instanceof AntPathRequestMatcher antPathRequestMatcher)
path = antPathRequestMatcher.getPattern();
else if (endpointMatcher instanceof OrRequestMatcher endpointMatchers) {
- Field requestMatchersField = FieldUtils.getDeclaredField(OrRequestMatcher.class, "requestMatchers", true);
- Iterable requestMatchers = (Iterable) requestMatchersField.get(endpointMatchers);
+ Iterable requestMatchers = (Iterable) FieldUtils.readDeclaredField(endpointMatchers, "requestMatchers", true);
for (RequestMatcher requestMatcher : requestMatchers) {
if (requestMatcher instanceof OrRequestMatcher orRequestMatcher) {
- requestMatchersField = FieldUtils.getDeclaredField(OrRequestMatcher.class, "requestMatchers", true);
- requestMatchers = (Iterable) requestMatchersField.get(orRequestMatcher);
+ requestMatchers = (Iterable) FieldUtils.readDeclaredField(orRequestMatcher, "requestMatchers", true);
for (RequestMatcher matcher : requestMatchers) {
if (matcher instanceof AntPathRequestMatcher antPathRequestMatcher)
path = antPathRequestMatcher.getPattern();
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocSecurityOAuth2EndpointUtils.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocSecurityOAuth2EndpointUtils.java
index 7d9881357..201db0de2 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocSecurityOAuth2EndpointUtils.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocSecurityOAuth2EndpointUtils.java
@@ -1,3 +1,29 @@
+/*
+ *
+ * *
+ * * *
+ * * * *
+ * * * * *
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.springdoc.core.configuration;
import java.util.Optional;
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocSortConfiguration.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocSortConfiguration.java
index 5e512d170..ff751eb5e 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocSortConfiguration.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocSortConfiguration.java
@@ -3,23 +3,25 @@
* *
* * *
* * * *
- * * * * * Copyright 2019-2022 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
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
* * * * *
- * * * * * https://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.springdoc.core.configuration;
@@ -27,9 +29,7 @@
import java.util.Optional;
import org.springdoc.core.converters.SortOpenAPIConverter;
-import org.springdoc.core.converters.models.SortObject;
import org.springdoc.core.customizers.DataRestDelegatingMethodParameterCustomizer;
-import org.springdoc.core.customizers.DelegatingMethodParameterCustomizer;
import org.springdoc.core.providers.ObjectMapperProvider;
import org.springdoc.core.providers.RepositoryRestConfigurationProvider;
import org.springdoc.core.providers.SpringDataWebPropertiesProvider;
@@ -50,6 +50,7 @@
/**
* The type Spring doc pageable configuration.
+ *
* @author bnasslahsen
*/
@Lazy(false)
@@ -72,7 +73,6 @@ public class SpringDocSortConfiguration {
@Lazy(false)
SortOpenAPIConverter sortOpenAPIConverter(ObjectMapperProvider objectMapperProvider) {
getConfig().replaceParameterObjectWithClass(org.springframework.data.domain.Sort.class, org.springdoc.core.converters.models.Sort.class);
- getConfig().replaceWithClass(org.springframework.data.domain.Sort.class, SortObject.class);
return new SortOpenAPIConverter(objectMapperProvider);
}
@@ -80,13 +80,13 @@ SortOpenAPIConverter sortOpenAPIConverter(ObjectMapperProvider objectMapperProvi
* Delegating method parameter customizer delegating method parameter customizer.
*
* @param optionalSpringDataWebPropertiesProvider the optional spring data web properties
- * @param optionalRepositoryRestConfiguration the optional repository rest configuration
+ * @param optionalRepositoryRestConfiguration the optional repository rest configuration
* @return the delegating method parameter customizer
*/
@Bean
@ConditionalOnMissingBean
@Lazy(false)
- DelegatingMethodParameterCustomizer delegatingMethodParameterCustomizer(Optional optionalSpringDataWebPropertiesProvider, Optional optionalRepositoryRestConfiguration) {
+ DataRestDelegatingMethodParameterCustomizer dataRestDelegatingMethodParameterCustomizer(Optional optionalSpringDataWebPropertiesProvider, Optional optionalRepositoryRestConfiguration) {
return new DataRestDelegatingMethodParameterCustomizer(optionalSpringDataWebPropertiesProvider, optionalRepositoryRestConfiguration);
}
}
\ No newline at end of file
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocSpecPropertiesConfiguration.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocSpecPropertiesConfiguration.java
index bc2deb485..5e87fb67e 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocSpecPropertiesConfiguration.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocSpecPropertiesConfiguration.java
@@ -3,23 +3,25 @@
* *
* * *
* * * *
- * * * * * Copyright 2019-2022 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
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
* * * * *
- * * * * * https://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.springdoc.core.configuration;
@@ -53,13 +55,14 @@
@Conditional(SpecPropertiesCondition.class)
public class SpringDocSpecPropertiesConfiguration {
- /**
- * Springdoc customizer that takes care of the specification string properties customization.
- * Will be applied to general openapi schema.
- *
- * @return the springdoc customizer
- */
- @Bean
+ /**
+ * Springdoc customizer that takes care of the specification string properties customization.
+ * Will be applied to general openapi schema.
+ *
+ * @param springDocConfigProperties the spring doc config properties
+ * @return the springdoc customizer
+ */
+ @Bean
@ConditionalOnMissingBean
@Lazy(false)
SpecPropertiesCustomizer specificationStringPropertiesCustomizer(
@@ -68,13 +71,14 @@ SpecPropertiesCustomizer specificationStringPropertiesCustomizer(
return new SpecPropertiesCustomizer(springDocConfigProperties);
}
- /**
- * Bean post processor that applies the specification string properties customization to
- * grouped openapi schemas by using group name as a prefix for properties.
- *
- * @return the bean post processor
- */
- @Bean
+ /**
+ * Bean post processor that applies the specification string properties customization to
+ * grouped openapi schemas by using group name as a prefix for properties.
+ *
+ * @param springDocConfigProperties the spring doc config properties
+ * @return the bean post processor
+ */
+ @Bean
@ConditionalOnMissingBean
@Lazy(false)
SpecificationStringPropertiesCustomizerBeanPostProcessor specificationStringPropertiesCustomizerBeanPostProcessor(
@@ -89,9 +93,17 @@ SpecificationStringPropertiesCustomizerBeanPostProcessor specificationStringProp
*/
private static class SpecificationStringPropertiesCustomizerBeanPostProcessor implements BeanPostProcessor {
- private final SpringDocConfigProperties springDocConfigProperties;
+ /**
+ * The Spring doc config properties.
+ */
+ private final SpringDocConfigProperties springDocConfigProperties;
- public SpecificationStringPropertiesCustomizerBeanPostProcessor(
+ /**
+ * Instantiates a new Specification string properties customizer bean post processor.
+ *
+ * @param springDocConfigProperties the spring doc config properties
+ */
+ public SpecificationStringPropertiesCustomizerBeanPostProcessor(
SpringDocConfigProperties springDocConfigProperties
) {
this.springDocConfigProperties = springDocConfigProperties;
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocUIConfiguration.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocUIConfiguration.java
deleted file mode 100644
index 07da137fa..000000000
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocUIConfiguration.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- *
- * *
- * * *
- * * * *
- * * * * * Copyright 2019-2022 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
- * * * * *
- * * * * * https://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.springdoc.core.configuration;
-
-import java.io.IOException;
-import java.util.Optional;
-import java.util.Properties;
-
-import org.apache.commons.lang3.StringUtils;
-import org.springdoc.core.properties.SwaggerUiConfigProperties;
-
-import org.springframework.beans.factory.InitializingBean;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.Lazy;
-import org.springframework.core.io.ClassPathResource;
-import org.springframework.core.io.Resource;
-import org.springframework.core.io.support.PropertiesLoaderUtils;
-import org.springframework.util.AntPathMatcher;
-
-/**
- * The type Spring doc Native Configuration.
- * @author bnasslahsen
- */
-@Lazy(false)
-@ConditionalOnWebApplication
-@Configuration(proxyBeanMethods = false)
-@ConditionalOnBean(SpringDocConfiguration.class)
-public class SpringDocUIConfiguration implements InitializingBean {
-
- /**
- * The constant SPRINGDOC_CONFIG_PROPERTIES.
- */
- public static final String SPRINGDOC_CONFIG_PROPERTIES = "springdoc.config.properties";
-
- /**
- * The constant SPRINGDOC_SWAGGERUI_VERSION.
- */
- private static final String SPRINGDOC_SWAGGERUI_VERSION = "springdoc.swagger-ui.version";
-
- /**
- * The Swagger ui config properties.
- */
- private final Optional optionalSwaggerUiConfigProperties;
-
- /**
- * Instantiates a new Spring doc hints.
- *
- * @param optionalSwaggerUiConfigProperties the swagger ui config properties
- */
- public SpringDocUIConfiguration(Optional optionalSwaggerUiConfigProperties) {
- this.optionalSwaggerUiConfigProperties = optionalSwaggerUiConfigProperties;
- }
-
- @Override
- public void afterPropertiesSet() {
- optionalSwaggerUiConfigProperties.ifPresent(swaggerUiConfigProperties -> {
- if (StringUtils.isEmpty(swaggerUiConfigProperties.getVersion())) {
- try {
- Resource resource = new ClassPathResource(AntPathMatcher.DEFAULT_PATH_SEPARATOR + SPRINGDOC_CONFIG_PROPERTIES);
- Properties props = PropertiesLoaderUtils.loadProperties(resource);
- swaggerUiConfigProperties.setVersion(props.getProperty(SPRINGDOC_SWAGGERUI_VERSION));
- }
- catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
- });
- }
-}
-
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/hints/SpringDocDataRestHints.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/hints/SpringDocDataRestHints.java
index ea83aa73a..27538ccaf 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/hints/SpringDocDataRestHints.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/hints/SpringDocDataRestHints.java
@@ -3,23 +3,25 @@
* *
* * *
* * * *
- * * * * * Copyright 2019-2022 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
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
* * * * *
- * * * * * https://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.springdoc.core.configuration.hints;
@@ -36,11 +38,15 @@
/**
* The type Spring doc DataRest hints.
+ *
* @author bnasslahsen
*/
public class SpringDocDataRestHints implements RuntimeHintsRegistrar {
- //spring-data-rest
+ /**
+ * The Spring data rest type names.
+ */
+//spring-data-rest
static String[] springDataRestTypeNames = { "org.springframework.data.rest.webmvc.config.DelegatingHandlerMapping",
"org.springframework.data.rest.webmvc.support.DelegatingHandlerMapping",
"org.springframework.data.rest.webmvc.RepositoryPropertyReferenceController",
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/hints/SpringDocHints.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/hints/SpringDocHints.java
index e4ac1f7b3..37e457135 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/hints/SpringDocHints.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/hints/SpringDocHints.java
@@ -3,29 +3,32 @@
* *
* * *
* * * *
- * * * * * Copyright 2019-2022 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
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
* * * * *
- * * * * * https://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.springdoc.core.configuration.hints;
import java.util.Arrays;
+import com.fasterxml.jackson.databind.BeanDescription;
import io.swagger.v3.core.converter.ModelConverter;
import io.swagger.v3.core.filter.SpecFilter;
import io.swagger.v3.core.jackson.ApiResponsesSerializer;
@@ -36,6 +39,7 @@
import io.swagger.v3.core.jackson.mixin.Discriminator31Mixin;
import io.swagger.v3.core.jackson.mixin.ExampleMixin;
import io.swagger.v3.core.jackson.mixin.ExtensionsMixin;
+import io.swagger.v3.core.jackson.mixin.Info31Mixin;
import io.swagger.v3.core.jackson.mixin.MediaTypeMixin;
import io.swagger.v3.core.jackson.mixin.OpenAPI31Mixin;
import io.swagger.v3.core.jackson.mixin.OpenAPIMixin;
@@ -58,6 +62,7 @@
import io.swagger.v3.oas.models.media.EncodingProperty;
import io.swagger.v3.oas.models.media.FileSchema;
import io.swagger.v3.oas.models.media.IntegerSchema;
+import io.swagger.v3.oas.models.media.JsonSchema;
import io.swagger.v3.oas.models.media.MapSchema;
import io.swagger.v3.oas.models.media.MediaType;
import io.swagger.v3.oas.models.media.NumberSchema;
@@ -73,8 +78,8 @@
import io.swagger.v3.oas.models.security.Scopes;
import io.swagger.v3.oas.models.servers.ServerVariables;
import org.apache.commons.lang3.reflect.FieldUtils;
-import org.springdoc.core.configuration.SpringDocUIConfiguration;
import org.springdoc.core.properties.SpringDocConfigProperties.ModelConverters;
+import org.springdoc.core.properties.SwaggerUiConfigProperties;
import org.springframework.aot.hint.MemberCategory;
import org.springframework.aot.hint.RuntimeHints;
@@ -82,10 +87,14 @@
/**
* The type Spring doc hints.
+ *
* @author bnasslahsen
*/
public class SpringDocHints implements RuntimeHintsRegistrar {
+ /**
+ * The Types to register.
+ */
static Class[] typesToRegister = {
//swagger-models
io.swagger.v3.oas.models.security.SecurityScheme.Type.class,
@@ -123,10 +132,6 @@ public class SpringDocHints implements RuntimeHintsRegistrar {
OpenAPIMixin.class,
OperationMixin.class,
SchemaMixin.class,
- Schema31Mixin.class,
- Components31Mixin.class,
- OpenAPI31Mixin.class,
- Discriminator31Mixin.class,
Paths.class,
XML.class,
UUIDSchema.class,
@@ -159,12 +164,22 @@ public class SpringDocHints implements RuntimeHintsRegistrar {
DateSchemaMixin.class,
ExampleMixin.class,
MediaTypeMixin.class,
+ //oas 3.1
+ Schema31Mixin.class,
+ Components31Mixin.class,
+ OpenAPI31Mixin.class,
+ Discriminator31Mixin.class,
+ Info31Mixin.class,
+ Schema31Mixin.TypeSerializer.class,
+ JsonSchema.class,
//springdoc classes
org.springdoc.core.annotations.ParameterObject.class,
org.springdoc.core.converters.models.Pageable.class,
org.springdoc.core.extractor.DelegatingMethodParameter.class,
// spring
- org.springframework.core.MethodParameter.class
+ org.springframework.core.MethodParameter.class,
+ // jackson
+ BeanDescription.class,
};
@Override
@@ -191,7 +206,7 @@ public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
//springdoc
hints.reflection().registerField(FieldUtils.getDeclaredField(io.swagger.v3.core.converter.ModelConverters.class, "converters", true));
hints.reflection().registerType(org.springdoc.core.utils.Constants.class, hint -> hint.withMembers(MemberCategory.DECLARED_FIELDS));
- hints.resources().registerPattern(SpringDocUIConfiguration.SPRINGDOC_CONFIG_PROPERTIES)
+ hints.resources().registerPattern(SwaggerUiConfigProperties.SPRINGDOC_CONFIG_PROPERTIES)
.registerResourceBundle("sun.util.resources.LocaleNames");
}
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/hints/SpringDocSecurityHints.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/hints/SpringDocSecurityHints.java
index 22930100e..0af857d8e 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/hints/SpringDocSecurityHints.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/hints/SpringDocSecurityHints.java
@@ -3,23 +3,25 @@
* *
* * *
* * * *
- * * * * * Copyright 2019-2022 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
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
* * * * *
- * * * * * https://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.springdoc.core.configuration.hints;
@@ -32,11 +34,15 @@
/**
* The type Spring doc DataRest hints.
+ *
* @author bnasslahsen
*/
public class SpringDocSecurityHints implements RuntimeHintsRegistrar {
- //spring-security
+ /**
+ * The Spring security type names.
+ */
+//spring-security
static String[] springSecurityTypeNames = { "org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter",
"org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter",
"org.springframework.security.web.util.matcher.OrRequestMatcher"
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/oauth2/SpringDocOAuth2AuthorizationServerMetadata.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/oauth2/SpringDocOAuth2AuthorizationServerMetadata.java
index f16e14158..6ffccf630 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/oauth2/SpringDocOAuth2AuthorizationServerMetadata.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/oauth2/SpringDocOAuth2AuthorizationServerMetadata.java
@@ -1,3 +1,29 @@
+/*
+ *
+ * *
+ * * *
+ * * * *
+ * * * * *
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.springdoc.core.configuration.oauth2;
import java.util.List;
@@ -10,45 +36,105 @@
/**
* The type Spring doc o auth 2 authorization server metadata.
*
- * @see OAuth2AuthorizationServerMetadata
* @author bnasslahsen
* @author yuta.saito
+ * @see OAuth2AuthorizationServerMetadata
*/
@Schema(name = "OAuth2AuthorizationServerMetadata")
public interface SpringDocOAuth2AuthorizationServerMetadata {
+ /**
+ * Issuer string.
+ *
+ * @return the string
+ */
@JsonProperty(OAuth2AuthorizationServerMetadataClaimNames.ISSUER)
String issuer();
+ /**
+ * Authorization endpoint string.
+ *
+ * @return the string
+ */
@JsonProperty(OAuth2AuthorizationServerMetadataClaimNames.AUTHORIZATION_ENDPOINT)
String authorizationEndpoint();
+ /**
+ * Token endpoint string.
+ *
+ * @return the string
+ */
@JsonProperty(OAuth2AuthorizationServerMetadataClaimNames.TOKEN_ENDPOINT)
String tokenEndpoint();
+ /**
+ * Token endpoint auth methods supported list.
+ *
+ * @return the list
+ */
@JsonProperty(OAuth2AuthorizationServerMetadataClaimNames.TOKEN_ENDPOINT_AUTH_METHODS_SUPPORTED)
List tokenEndpointAuthMethodsSupported();
+ /**
+ * Jwks uri string.
+ *
+ * @return the string
+ */
@JsonProperty(OAuth2AuthorizationServerMetadataClaimNames.JWKS_URI)
String jwksUri();
+ /**
+ * Response types supported list.
+ *
+ * @return the list
+ */
@JsonProperty(OAuth2AuthorizationServerMetadataClaimNames.RESPONSE_TYPES_SUPPORTED)
List responseTypesSupported();
+ /**
+ * Grant types supported list.
+ *
+ * @return the list
+ */
@JsonProperty(OAuth2AuthorizationServerMetadataClaimNames.GRANT_TYPES_SUPPORTED)
List grantTypesSupported();
+ /**
+ * Revocation endpoint string.
+ *
+ * @return the string
+ */
@JsonProperty(OAuth2AuthorizationServerMetadataClaimNames.REVOCATION_ENDPOINT)
String revocationEndpoint();
+ /**
+ * Revocation endpoint auth methods supported list.
+ *
+ * @return the list
+ */
@JsonProperty(OAuth2AuthorizationServerMetadataClaimNames.REVOCATION_ENDPOINT_AUTH_METHODS_SUPPORTED)
List revocationEndpointAuthMethodsSupported();
+ /**
+ * Introspection endpoint string.
+ *
+ * @return the string
+ */
@JsonProperty(OAuth2AuthorizationServerMetadataClaimNames.INTROSPECTION_ENDPOINT)
String introspectionEndpoint();
+ /**
+ * Introspection endpoint auth methods supported list.
+ *
+ * @return the list
+ */
@JsonProperty(OAuth2AuthorizationServerMetadataClaimNames.INTROSPECTION_ENDPOINT_AUTH_METHODS_SUPPORTED)
List introspectionEndpointAuthMethodsSupported();
+ /**
+ * Code challenge methods supported list.
+ *
+ * @return the list
+ */
@JsonProperty(OAuth2AuthorizationServerMetadataClaimNames.CODE_CHALLENGE_METHODS_SUPPORTED)
List codeChallengeMethodsSupported();
}
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/oauth2/SpringDocOAuth2Token.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/oauth2/SpringDocOAuth2Token.java
index 4aedaf5ec..31667ef27 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/oauth2/SpringDocOAuth2Token.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/oauth2/SpringDocOAuth2Token.java
@@ -1,3 +1,29 @@
+/*
+ *
+ * *
+ * * *
+ * * * *
+ * * * * *
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.springdoc.core.configuration.oauth2;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
@@ -7,19 +33,44 @@
/**
* The type Spring doc o auth 2 token.
*
- * @see DefaultOAuth2AccessTokenResponseMapConverter
* @author yuta.saito
+ * @see DefaultOAuth2AccessTokenResponseMapConverter
*/
@Schema(name = "OAuth2Token")
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
public interface SpringDocOAuth2Token {
+ /**
+ * Gets access token.
+ *
+ * @return the access token
+ */
String getAccessToken();
+ /**
+ * Gets token type.
+ *
+ * @return the token type
+ */
String getTokenType();
+ /**
+ * Gets expires in.
+ *
+ * @return the expires in
+ */
long getExpiresIn();
+ /**
+ * Gets scope.
+ *
+ * @return the scope
+ */
String getScope();
+ /**
+ * Gets refresh token.
+ *
+ * @return the refresh token
+ */
String getRefreshToken();
}
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/oauth2/SpringDocOAuth2TokenIntrospection.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/oauth2/SpringDocOAuth2TokenIntrospection.java
index ae2cc9ee0..cc127ce55 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/oauth2/SpringDocOAuth2TokenIntrospection.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/oauth2/SpringDocOAuth2TokenIntrospection.java
@@ -1,3 +1,29 @@
+/*
+ *
+ * *
+ * * *
+ * * * *
+ * * * * *
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.springdoc.core.configuration.oauth2;
import java.util.List;
@@ -10,46 +36,106 @@
/**
* The type Spring doc o auth 2 token introspection.
*
- * @see OAuth2TokenIntrospectionHttpMessageConverter
- * @see OAuth2TokenIntrospection
* @author bnasslahsen
* @author yuta.saito
+ * @see OAuth2TokenIntrospectionHttpMessageConverter
+ * @see OAuth2TokenIntrospection
*/
@Schema(name = "OAuth2TokenIntrospection")
public interface SpringDocOAuth2TokenIntrospection {
+ /**
+ * Gets active.
+ *
+ * @return the active
+ */
@JsonProperty(OAuth2TokenIntrospectionClaimNames.ACTIVE)
boolean getActive();
+ /**
+ * Gets scope.
+ *
+ * @return the scope
+ */
@JsonProperty(OAuth2TokenIntrospectionClaimNames.SCOPE)
String getScope();
+ /**
+ * Gets client id.
+ *
+ * @return the client id
+ */
@JsonProperty(OAuth2TokenIntrospectionClaimNames.CLIENT_ID)
String getClientId();
+ /**
+ * Gets username.
+ *
+ * @return the username
+ */
@JsonProperty(OAuth2TokenIntrospectionClaimNames.USERNAME)
String getUsername();
+ /**
+ * Gets token type.
+ *
+ * @return the token type
+ */
@JsonProperty(OAuth2TokenIntrospectionClaimNames.TOKEN_TYPE)
String getTokenType();
+ /**
+ * Gets expires at.
+ *
+ * @return the expires at
+ */
@JsonProperty(OAuth2TokenIntrospectionClaimNames.EXP)
long getExpiresAt();
+ /**
+ * Gets issue at.
+ *
+ * @return the issue at
+ */
@JsonProperty(OAuth2TokenIntrospectionClaimNames.IAT)
long getIssueAt();
+ /**
+ * Gets not before.
+ *
+ * @return the not before
+ */
@JsonProperty(OAuth2TokenIntrospectionClaimNames.NBF)
long getNotBefore();
+ /**
+ * Gets subject.
+ *
+ * @return the subject
+ */
@JsonProperty(OAuth2TokenIntrospectionClaimNames.SUB)
String getSubject();
+ /**
+ * Gets audience.
+ *
+ * @return the audience
+ */
@JsonProperty(OAuth2TokenIntrospectionClaimNames.AUD)
List getAudience();
+ /**
+ * Gets issuer.
+ *
+ * @return the issuer
+ */
@JsonProperty(OAuth2TokenIntrospectionClaimNames.ISS)
String getIssuer();
+ /**
+ * Gets id.
+ *
+ * @return the id
+ */
@JsonProperty(OAuth2TokenIntrospectionClaimNames.JTI)
String getId();
}
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/oauth2/SpringDocOidcClientRegistrationRequest.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/oauth2/SpringDocOidcClientRegistrationRequest.java
index 984d7539a..1894545e8 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/oauth2/SpringDocOidcClientRegistrationRequest.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/oauth2/SpringDocOidcClientRegistrationRequest.java
@@ -1,3 +1,29 @@
+/*
+ *
+ * *
+ * * *
+ * * * *
+ * * * * *
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.springdoc.core.configuration.oauth2;
import java.time.Instant;
@@ -11,48 +37,113 @@
/**
* The type Spring doc OpenID Client Registration Request
*
+ * @author yuta.saito
* @see OidcClientRegistration
* @see OidcClientRegistrationHttpMessageConverter
- * @author yuta.saito
*/
@Schema(name = "ClientRegistrationRequest")
public interface SpringDocOidcClientRegistrationRequest {
+ /**
+ * Client id string.
+ *
+ * @return the string
+ */
@JsonProperty(OidcClientMetadataClaimNames.CLIENT_ID)
String clientId();
+ /**
+ * Client id issued at instant.
+ *
+ * @return the instant
+ */
@JsonProperty(OidcClientMetadataClaimNames.CLIENT_ID_ISSUED_AT)
Instant clientIdIssuedAt();
+ /**
+ * Client secret string.
+ *
+ * @return the string
+ */
@JsonProperty(OidcClientMetadataClaimNames.CLIENT_SECRET)
String clientSecret();
+ /**
+ * Client secret expires at instant.
+ *
+ * @return the instant
+ */
@JsonProperty(OidcClientMetadataClaimNames.CLIENT_SECRET_EXPIRES_AT)
Instant CLIENT_SECRET_EXPIRES_AT();
+ /**
+ * Client name string.
+ *
+ * @return the string
+ */
@JsonProperty(OidcClientMetadataClaimNames.CLIENT_NAME)
String clientName();
+ /**
+ * Redirect uris list.
+ *
+ * @return the list
+ */
@JsonProperty(OidcClientMetadataClaimNames.REDIRECT_URIS)
List redirectUris();
+ /**
+ * Token endpoint authentication method string.
+ *
+ * @return the string
+ */
@JsonProperty(OidcClientMetadataClaimNames.TOKEN_ENDPOINT_AUTH_METHOD)
String tokenEndpointAuthenticationMethod();
+ /**
+ * Token endpoint authentication signing algorithm string.
+ *
+ * @return the string
+ */
@JsonProperty(OidcClientMetadataClaimNames.TOKEN_ENDPOINT_AUTH_SIGNING_ALG)
String tokenEndpointAuthenticationSigningAlgorithm();
+ /**
+ * Grant types list.
+ *
+ * @return the list
+ */
@JsonProperty(OidcClientMetadataClaimNames.GRANT_TYPES)
List grantTypes();
+ /**
+ * Response type list.
+ *
+ * @return the list
+ */
@JsonProperty(OidcClientMetadataClaimNames.RESPONSE_TYPES)
List responseType();
+ /**
+ * Scopes string.
+ *
+ * @return the string
+ */
@JsonProperty(OidcClientMetadataClaimNames.SCOPE)
String scopes();
+ /**
+ * Jwk set url string.
+ *
+ * @return the string
+ */
@JsonProperty(OidcClientMetadataClaimNames.JWKS_URI)
String jwkSetUrl();
+ /**
+ * Id token signed response algorithm string.
+ *
+ * @return the string
+ */
@JsonProperty(OidcClientMetadataClaimNames.ID_TOKEN_SIGNED_RESPONSE_ALG)
String idTokenSignedResponseAlgorithm();
}
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/oauth2/SpringDocOidcClientRegistrationResponse.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/oauth2/SpringDocOidcClientRegistrationResponse.java
index f62c8d0c0..365f08a2c 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/oauth2/SpringDocOidcClientRegistrationResponse.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/oauth2/SpringDocOidcClientRegistrationResponse.java
@@ -1,3 +1,29 @@
+/*
+ *
+ * *
+ * * *
+ * * * *
+ * * * * *
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.springdoc.core.configuration.oauth2;
import java.util.List;
@@ -10,54 +36,129 @@
/**
* The type Spring doc OpenID Client Registration Request
*
+ * @author yuta.saito
* @see OidcClientRegistration
* @see OidcClientRegistrationHttpMessageConverter
- * @author yuta.saito
*/
@Schema(name = "ClientRegistrationResponse")
public interface SpringDocOidcClientRegistrationResponse {
+ /**
+ * Client id string.
+ *
+ * @return the string
+ */
@JsonProperty(OidcClientMetadataClaimNames.CLIENT_ID)
String clientId();
+ /**
+ * Client id issued at long.
+ *
+ * @return the long
+ */
@JsonProperty(OidcClientMetadataClaimNames.CLIENT_ID_ISSUED_AT)
long clientIdIssuedAt();
+ /**
+ * Client secret string.
+ *
+ * @return the string
+ */
@JsonProperty(OidcClientMetadataClaimNames.CLIENT_SECRET)
String clientSecret();
+ /**
+ * Client secret expires at long.
+ *
+ * @return the long
+ */
@JsonProperty(OidcClientMetadataClaimNames.CLIENT_SECRET_EXPIRES_AT)
long CLIENT_SECRET_EXPIRES_AT();
+ /**
+ * Client name string.
+ *
+ * @return the string
+ */
@JsonProperty(OidcClientMetadataClaimNames.CLIENT_NAME)
String clientName();
+ /**
+ * Redirect uris list.
+ *
+ * @return the list
+ */
@JsonProperty(OidcClientMetadataClaimNames.REDIRECT_URIS)
List redirectUris();
+ /**
+ * Token endpoint authentication method string.
+ *
+ * @return the string
+ */
@JsonProperty(OidcClientMetadataClaimNames.TOKEN_ENDPOINT_AUTH_METHOD)
String tokenEndpointAuthenticationMethod();
+ /**
+ * Token endpoint authentication signing algorithm string.
+ *
+ * @return the string
+ */
@JsonProperty(OidcClientMetadataClaimNames.TOKEN_ENDPOINT_AUTH_SIGNING_ALG)
String tokenEndpointAuthenticationSigningAlgorithm();
+ /**
+ * Grant types list.
+ *
+ * @return the list
+ */
@JsonProperty(OidcClientMetadataClaimNames.GRANT_TYPES)
List grantTypes();
+ /**
+ * Response type list.
+ *
+ * @return the list
+ */
@JsonProperty(OidcClientMetadataClaimNames.RESPONSE_TYPES)
List responseType();
+ /**
+ * Scopes string.
+ *
+ * @return the string
+ */
@JsonProperty(OidcClientMetadataClaimNames.SCOPE)
String scopes();
+ /**
+ * Jwk set url string.
+ *
+ * @return the string
+ */
@JsonProperty(OidcClientMetadataClaimNames.JWKS_URI)
String jwkSetUrl();
+ /**
+ * Id token signed response algorithm string.
+ *
+ * @return the string
+ */
@JsonProperty(OidcClientMetadataClaimNames.ID_TOKEN_SIGNED_RESPONSE_ALG)
String idTokenSignedResponseAlgorithm();
+ /**
+ * Registration access token string.
+ *
+ * @return the string
+ */
@JsonProperty(OidcClientMetadataClaimNames.REGISTRATION_ACCESS_TOKEN)
String registrationAccessToken();
+ /**
+ * Registration client url string.
+ *
+ * @return the string
+ */
@JsonProperty(OidcClientMetadataClaimNames.REGISTRATION_CLIENT_URI)
String registrationClientUrl();
}
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/oauth2/SpringDocOidcProviderConfiguration.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/oauth2/SpringDocOidcProviderConfiguration.java
index 15f7f99c4..55d9d7313 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/oauth2/SpringDocOidcProviderConfiguration.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/oauth2/SpringDocOidcProviderConfiguration.java
@@ -1,3 +1,29 @@
+/*
+ *
+ * *
+ * * *
+ * * * *
+ * * * * *
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.springdoc.core.configuration.oauth2;
import java.util.List;
@@ -11,56 +37,136 @@
/**
* The type Spring doc OpenID Provider Configuration
*
- * @see OidcProviderConfiguration
* @author yuta.saito
+ * @see OidcProviderConfiguration
*/
@Schema(name = "OidcProviderConfiguration")
public interface SpringDocOidcProviderConfiguration {
+ /**
+ * Issuer string.
+ *
+ * @return the string
+ */
@JsonProperty(OAuth2AuthorizationServerMetadataClaimNames.ISSUER)
String issuer();
+ /**
+ * Authorization endpoint string.
+ *
+ * @return the string
+ */
@JsonProperty(OAuth2AuthorizationServerMetadataClaimNames.AUTHORIZATION_ENDPOINT)
String authorizationEndpoint();
+ /**
+ * Token endpoint string.
+ *
+ * @return the string
+ */
@JsonProperty(OAuth2AuthorizationServerMetadataClaimNames.TOKEN_ENDPOINT)
String tokenEndpoint();
+ /**
+ * Token endpoint auth methods supported list.
+ *
+ * @return the list
+ */
@JsonProperty(OAuth2AuthorizationServerMetadataClaimNames.TOKEN_ENDPOINT_AUTH_METHODS_SUPPORTED)
List tokenEndpointAuthMethodsSupported();
+ /**
+ * Jwks uri string.
+ *
+ * @return the string
+ */
@JsonProperty(OAuth2AuthorizationServerMetadataClaimNames.JWKS_URI)
String jwksUri();
+ /**
+ * User info endpoint string.
+ *
+ * @return the string
+ */
@JsonProperty(OidcProviderMetadataClaimNames.USER_INFO_ENDPOINT)
String userInfoEndpoint();
+ /**
+ * Response types supported list.
+ *
+ * @return the list
+ */
@JsonProperty(OAuth2AuthorizationServerMetadataClaimNames.RESPONSE_TYPES_SUPPORTED)
List responseTypesSupported();
+ /**
+ * Grant types supported list.
+ *
+ * @return the list
+ */
@JsonProperty(OAuth2AuthorizationServerMetadataClaimNames.GRANT_TYPES_SUPPORTED)
List grantTypesSupported();
+ /**
+ * Revocation endpoint string.
+ *
+ * @return the string
+ */
@JsonProperty(OAuth2AuthorizationServerMetadataClaimNames.REVOCATION_ENDPOINT)
String revocationEndpoint();
+ /**
+ * Revocation endpoint auth methods supported list.
+ *
+ * @return the list
+ */
@JsonProperty(OAuth2AuthorizationServerMetadataClaimNames.REVOCATION_ENDPOINT_AUTH_METHODS_SUPPORTED)
List revocationEndpointAuthMethodsSupported();
+ /**
+ * Introspection endpoint string.
+ *
+ * @return the string
+ */
@JsonProperty(OAuth2AuthorizationServerMetadataClaimNames.INTROSPECTION_ENDPOINT)
String introspectionEndpoint();
+ /**
+ * Introspection endpoint auth methods supported list.
+ *
+ * @return the list
+ */
@JsonProperty(OAuth2AuthorizationServerMetadataClaimNames.INTROSPECTION_ENDPOINT_AUTH_METHODS_SUPPORTED)
List introspectionEndpointAuthMethodsSupported();
+ /**
+ * Subject types supported string.
+ *
+ * @return the string
+ */
@JsonProperty(OidcProviderMetadataClaimNames.SUBJECT_TYPES_SUPPORTED)
String subjectTypesSupported();
+ /**
+ * Id token signing alg values supported string.
+ *
+ * @return the string
+ */
@JsonProperty(OidcProviderMetadataClaimNames.ID_TOKEN_SIGNING_ALG_VALUES_SUPPORTED)
String idTokenSigningAlgValuesSupported();
+ /**
+ * Scope supported string.
+ *
+ * @return the string
+ */
@JsonProperty(OAuth2AuthorizationServerMetadataClaimNames.SCOPES_SUPPORTED)
String scopeSupported();
+ /**
+ * Code challenge methods supported list.
+ *
+ * @return the list
+ */
@JsonProperty(OAuth2AuthorizationServerMetadataClaimNames.CODE_CHALLENGE_METHODS_SUPPORTED)
List codeChallengeMethodsSupported();
}
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configurer/SpringdocActuatorBeanFactoryConfigurer.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configurer/SpringdocActuatorBeanFactoryConfigurer.java
index 0bfcdf5d4..1adedafcd 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configurer/SpringdocActuatorBeanFactoryConfigurer.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configurer/SpringdocActuatorBeanFactoryConfigurer.java
@@ -3,23 +3,25 @@
* *
* * *
* * * *
- * * * * * Copyright 2019-2022 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
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
* * * * *
- * * * * * https://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.springdoc.core.configurer;
@@ -27,7 +29,6 @@
import java.util.ArrayList;
import java.util.List;
-import org.springdoc.core.customizers.ActuatorOpenApiCustomizer;
import org.springdoc.core.customizers.ActuatorOperationCustomizer;
import org.springdoc.core.models.GroupedOpenApi;
import org.springdoc.core.properties.SpringDocConfigProperties;
@@ -47,6 +48,7 @@
/**
* The type Springdoc bean factory configurer.
+ *
* @author bnasslahsen
*/
public class SpringdocActuatorBeanFactoryConfigurer extends SpringdocBeanFactoryConfigurer {
@@ -59,7 +61,7 @@ public class SpringdocActuatorBeanFactoryConfigurer extends SpringdocBeanFactory
/**
* Instantiates a new Springdoc actuator bean factory configurer.
*
- * @param groupedOpenApis the grouped open apis
+ * @param groupedOpenApis the grouped open apis
*/
public SpringdocActuatorBeanFactoryConfigurer(List groupedOpenApis) {
this.groupedOpenApis = groupedOpenApis;
@@ -76,9 +78,7 @@ public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
WebEndpointProperties webEndpointProperties = result.get();
SpringDocConfigProperties springDocConfigProperties = springDocConfigPropertiesBindResult.get();
List newGroups = new ArrayList<>();
-
- ActuatorOpenApiCustomizer actuatorOpenApiCustomizer = new ActuatorOpenApiCustomizer(webEndpointProperties);
- beanFactory.registerSingleton("actuatorOpenApiCustomizer", actuatorOpenApiCustomizer);
+
ActuatorOperationCustomizer actuatorCustomizer = new ActuatorOperationCustomizer(springDocConfigProperties);
beanFactory.registerSingleton("actuatorCustomizer", actuatorCustomizer);
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configurer/SpringdocBeanFactoryConfigurer.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configurer/SpringdocBeanFactoryConfigurer.java
index a67ff7e25..816f407fb 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configurer/SpringdocBeanFactoryConfigurer.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configurer/SpringdocBeanFactoryConfigurer.java
@@ -3,23 +3,25 @@
* *
* * *
* * * *
- * * * * * Copyright 2019-2022 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
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
* * * * *
- * * * * * https://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.springdoc.core.configurer;
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/AdditionalModelsConverter.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/AdditionalModelsConverter.java
index c565255db..7c7a34f6d 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/AdditionalModelsConverter.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/AdditionalModelsConverter.java
@@ -3,23 +3,25 @@
* *
* * *
* * * *
- * * * * * Copyright 2019-2022 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
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
* * * * *
- * * * * * https://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.springdoc.core.converters;
@@ -39,8 +41,11 @@
import org.slf4j.LoggerFactory;
import org.springdoc.core.providers.ObjectMapperProvider;
+import static org.springdoc.core.utils.SpringDocUtils.handleSchemaTypes;
+
/**
* The type Additional models converter.
+ *
* @author bnasslahsen
*/
public class AdditionalModelsConverter implements ModelConverter {
@@ -143,8 +148,11 @@ public Schema resolve(AnnotatedType type, ModelConverterContext context, Iterato
Class> cls = javaType.getRawClass();
if (modelToSchemaMap.containsKey(cls))
try {
+ Schema schema = modelToSchemaMap.get(cls);
+ if(springDocObjectMapper.isOpenapi31())
+ handleSchemaTypes(schema);
return springDocObjectMapper.jsonMapper()
- .readValue(springDocObjectMapper.jsonMapper().writeValueAsString(modelToSchemaMap.get(cls)), new TypeReference() {});
+ .readValue(springDocObjectMapper.jsonMapper().writeValueAsString(schema), new TypeReference() {});
}
catch (JsonProcessingException e) {
LOGGER.warn("Json Processing Exception occurred: {}", e.getMessage());
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/CollectionModelContentConverter.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/CollectionModelContentConverter.java
index 0b8b6ae6e..08e8e6e52 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/CollectionModelContentConverter.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/CollectionModelContentConverter.java
@@ -3,23 +3,25 @@
* *
* * *
* * * *
- * * * * * Copyright 2019-2022 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
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
* * * * *
- * * * * * https://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.springdoc.core.converters;
@@ -46,8 +48,8 @@
* Override resolved schema as there is a custom serializer that converts the data to a map before serializing it.
*
* @author bnasslahsen
- * @see org.springframework.hateoas.mediatype.hal.Jackson2HalModule.HalResourcesSerializer
- * @see org.springframework.hateoas.mediatype.hal.Jackson2HalModule.HalResourcesSerializer#serialize(Collection, JsonGenerator, SerializerProvider) org.springframework.hateoas.mediatype.hal.Jackson2HalModule.HalResourcesSerializer#serialize(Collection, JsonGenerator, SerializerProvider)org.springframework.hateoas.mediatype.hal.Jackson2HalModule.HalResourcesSerializer#serialize(Collection, JsonGenerator, SerializerProvider)org.springframework.hateoas.mediatype.hal.Jackson2HalModule.HalResourcesSerializer#serialize(Collection, JsonGenerator, SerializerProvider)org.springframework.hateoas.mediatype.hal.Jackson2HalModule.HalResourcesSerializer#serialize(Collection, JsonGenerator, SerializerProvider)
+ * @see org.springframework.hateoas.mediatype.hal.Jackson2HalModule.HalResourcesSerializer
+ * @see org.springframework.hateoas.mediatype.hal.Jackson2HalModule.HalResourcesSerializer#serialize(Collection, JsonGenerator, SerializerProvider) org.springframework.hateoas.mediatype.hal.Jackson2HalModule.HalResourcesSerializer#serialize(Collection, JsonGenerator, SerializerProvider)org.springframework.hateoas.mediatype.hal.Jackson2HalModule.HalResourcesSerializer#serialize(Collection, JsonGenerator, SerializerProvider)org.springframework.hateoas.mediatype.hal.Jackson2HalModule.HalResourcesSerializer#serialize(Collection, JsonGenerator, SerializerProvider)org.springframework.hateoas.mediatype.hal.Jackson2HalModule.HalResourcesSerializer#serialize(Collection, JsonGenerator, SerializerProvider)org.springframework.hateoas.mediatype.hal.Jackson2HalModule.HalResourcesSerializer#serialize(Collection, JsonGenerator, SerializerProvider)
*/
public class CollectionModelContentConverter implements ModelConverter {
@@ -85,7 +87,7 @@ public Schema> resolve(AnnotatedType type, ModelConverterContext context, Iter
/**
* Gets entity type.
*
- * @param type the type
+ * @param type the type
* @return the entity type
*/
private Class> getEntityType(AnnotatedType type) {
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/ConverterUtils.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/ConverterUtils.java
index 98b165ee9..b49a02e82 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/ConverterUtils.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/ConverterUtils.java
@@ -3,23 +3,25 @@
* *
* * *
* * * *
- * * * * * Copyright 2019-2022 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
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
* * * * *
- * * * * * https://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.springdoc.core.converters;
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/FileSupportConverter.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/FileSupportConverter.java
index 9192f4471..547fd4c17 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/FileSupportConverter.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/FileSupportConverter.java
@@ -3,23 +3,25 @@
* *
* * *
* * * *
- * * * * * Copyright 2019-2022 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
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
* * * * *
- * * * * * https://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.springdoc.core.converters;
@@ -40,6 +42,7 @@
/**
* The type File support converter.
+ *
* @author bnasslahsen
*/
public class FileSupportConverter implements ModelConverter {
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/HateoasLinksConverter.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/HateoasLinksConverter.java
new file mode 100644
index 000000000..7fbfa420b
--- /dev/null
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/HateoasLinksConverter.java
@@ -0,0 +1,90 @@
+/*
+ *
+ * *
+ * * *
+ * * * *
+ * * * * *
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.springdoc.core.converters;
+
+
+import java.util.Iterator;
+
+import com.fasterxml.jackson.databind.JavaType;
+import io.swagger.v3.core.converter.ModelConverter;
+import io.swagger.v3.core.converter.ModelConverterContext;
+import io.swagger.v3.core.util.AnnotationsUtils;
+import io.swagger.v3.oas.models.Components;
+import io.swagger.v3.oas.models.media.ArraySchema;
+import io.swagger.v3.oas.models.media.JsonSchema;
+import io.swagger.v3.oas.models.media.Schema;
+import org.springdoc.core.providers.ObjectMapperProvider;
+
+import org.springframework.hateoas.RepresentationModel;
+
+/**
+ * The type Hateoas links converter.
+ *
+ * @author bnasslahsen
+ */
+public class HateoasLinksConverter implements ModelConverter {
+
+ /**
+ * The Spring doc object mapper.
+ */
+ private final ObjectMapperProvider springDocObjectMapper;
+
+ /**
+ * Instantiates a new Hateoas links converter.
+ *
+ * @param springDocObjectMapper the spring doc object mapper
+ */
+ public HateoasLinksConverter(ObjectMapperProvider springDocObjectMapper) {
+ this.springDocObjectMapper = springDocObjectMapper;
+ }
+
+ @Override
+ public Schema> resolve(
+ io.swagger.v3.core.converter.AnnotatedType type,
+ ModelConverterContext context,
+ Iterator chain
+ ) {
+ JavaType javaType = springDocObjectMapper.jsonMapper().constructType(type.getType());
+ if (javaType != null && RepresentationModel.class.isAssignableFrom(javaType.getRawClass())) {
+ Schema> schema = chain.next().resolve(type, context, chain);
+ String schemaName = schema.get$ref().substring(Components.COMPONENTS_SCHEMAS_REF.length());
+ Schema original = context.getDefinedModels().get(schemaName);
+ Object links = original.getProperties().get("_links");
+ if(links instanceof JsonSchema jsonSchema) {
+ jsonSchema.set$ref(AnnotationsUtils.COMPONENTS_REF + "Links");
+ jsonSchema.setType(null);
+ jsonSchema.setItems(null);
+ jsonSchema.setTypes(null);
+ } else if (links instanceof ArraySchema arraySchema){
+ arraySchema.set$ref(AnnotationsUtils.COMPONENTS_REF + "Links");
+ }
+ return schema;
+ }
+ return chain.hasNext() ? chain.next().resolve(type, context, chain) : null;
+ }
+
+}
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/JavaTypeToIgnoreConverter.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/JavaTypeToIgnoreConverter.java
index 093e2f68e..a8457b378 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/JavaTypeToIgnoreConverter.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/JavaTypeToIgnoreConverter.java
@@ -3,23 +3,25 @@
* *
* * *
* * * *
- * * * * * Copyright 2019-2022 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
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
* * * * *
- * * * * * https://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.springdoc.core.converters;
@@ -35,6 +37,7 @@
/**
* The type Request type to ignore converter.
+ *
* @author bnasslahsen
*/
public class JavaTypeToIgnoreConverter implements ModelConverter {
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/ModelConverterRegistrar.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/ModelConverterRegistrar.java
index d97926ce1..8a363c93b 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/ModelConverterRegistrar.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/ModelConverterRegistrar.java
@@ -3,28 +3,29 @@
* *
* * *
* * * *
- * * * * * Copyright 2019-2022 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
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
* * * * *
- * * * * * https://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.springdoc.core.converters;
-import java.lang.reflect.Field;
import java.util.List;
import java.util.Optional;
@@ -37,6 +38,7 @@
/**
* Wrapper for model converters to only register converters once
+ *
* @author bnasslahsen
*/
public class ModelConverterRegistrar {
@@ -75,8 +77,7 @@ public ModelConverterRegistrar(List modelConverters, SpringDocCo
@SuppressWarnings("unchecked")
private Optional getRegisteredConverterSameAs(ModelConverter modelConverter) {
try {
- Field convertersField = FieldUtils.getDeclaredField(ModelConverters.class, "converters", true);
- List modelConverters = (List) convertersField.get(modelConvertersInstance);
+ List modelConverters = (List) FieldUtils.readDeclaredField(modelConvertersInstance, "converters", true);
return modelConverters.stream()
.filter(registeredModelConverter -> isSameConverter(registeredModelConverter, modelConverter))
.findFirst();
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/OAS31ModelConverter.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/OAS31ModelConverter.java
new file mode 100644
index 000000000..17fbdbbb4
--- /dev/null
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/OAS31ModelConverter.java
@@ -0,0 +1,58 @@
+/*
+ *
+ * *
+ * * *
+ * * * *
+ * * * * *
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.springdoc.core.converters;
+
+import java.util.Iterator;
+
+import io.swagger.v3.core.converter.AnnotatedType;
+import io.swagger.v3.core.converter.ModelConverter;
+import io.swagger.v3.core.converter.ModelConverterContext;
+import io.swagger.v3.oas.models.media.Schema;
+
+import static org.springdoc.core.utils.SpringDocUtils.handleSchemaTypes;
+import static org.springdoc.core.utils.SpringDocUtils.isComposedSchema;
+
+/**
+ * The type OAS31 Model converter.
+ *
+ * @author bnasslahsen
+ */
+public class OAS31ModelConverter implements ModelConverter {
+
+ @Override
+ public Schema> resolve(AnnotatedType type, ModelConverterContext context, Iterator chain) {
+ if (chain.hasNext()) {
+ Schema> resolvedSchema = chain.next().resolve(type, context, chain);
+ if (resolvedSchema != null && !isComposedSchema(resolvedSchema)) {
+ handleSchemaTypes(resolvedSchema);
+ }
+ return resolvedSchema;
+ }
+ return null;
+ }
+
+}
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/PageOpenAPIConverter.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/PageOpenAPIConverter.java
new file mode 100644
index 000000000..34e7e7f3a
--- /dev/null
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/PageOpenAPIConverter.java
@@ -0,0 +1,125 @@
+/*
+ *
+ * *
+ * * *
+ * * * *
+ * * * * *
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.springdoc.core.converters;
+
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.Iterator;
+
+import com.fasterxml.jackson.databind.JavaType;
+import io.swagger.v3.core.converter.AnnotatedType;
+import io.swagger.v3.core.converter.ModelConverter;
+import io.swagger.v3.core.converter.ModelConverterContext;
+import io.swagger.v3.oas.models.media.Schema;
+import org.springdoc.core.providers.ObjectMapperProvider;
+
+import org.springframework.core.ResolvableType;
+import org.springframework.data.web.PagedModel;
+
+import static org.springdoc.core.utils.SpringDocUtils.getParentTypeName;
+
+/**
+ * The Spring Data Page type model converter.
+ *
+ * @author Claudio Nave
+ */
+public class PageOpenAPIConverter implements ModelConverter {
+
+ /**
+ * The constant PAGE_TO_REPLACE.
+ */
+ private static final String PAGE_TO_REPLACE = "org.springframework.data.domain.Page";
+
+ /**
+ * The constant PAGED_MODEL.
+ */
+ private static final AnnotatedType PAGED_MODEL = new AnnotatedType(PagedModel.class).resolveAsRef(true);
+
+ /**
+ * The Spring doc object mapper.
+ */
+ private final ObjectMapperProvider springDocObjectMapper;
+
+ /**
+ * Flag to replace Page with PagedModel or not.
+ */
+ private final boolean replacePageWithPagedModel;
+
+ /**
+ * Instantiates a new Page open api converter.
+ *
+ * @param replacePageWithPagedModel flag to replace Page with PagedModel or not
+ * @param springDocObjectMapper the spring doc object mapper
+ */
+ public PageOpenAPIConverter(boolean replacePageWithPagedModel, ObjectMapperProvider springDocObjectMapper) {
+ this.replacePageWithPagedModel = replacePageWithPagedModel;
+ this.springDocObjectMapper = springDocObjectMapper;
+ }
+
+ /**
+ * Resolve schema.
+ * @param type the type
+ * @param context the context
+ * @param chain the chain
+ * @return the schema
+ */
+ @Override
+ public Schema resolve(AnnotatedType type, ModelConverterContext context, Iterator chain) {
+ JavaType javaType = springDocObjectMapper.jsonMapper().constructType(type.getType());
+ if (javaType != null) {
+ Class> cls = javaType.getRawClass();
+ if (replacePageWithPagedModel && PAGE_TO_REPLACE.equals(cls.getCanonicalName())) {
+ if (!type.isSchemaProperty())
+ type = resolvePagedModelType(type);
+ else
+ type.name(getParentTypeName(type, cls));
+ }
+ }
+ return (chain.hasNext()) ? chain.next().resolve(type, context, chain) : null;
+ }
+
+ /**
+ * Resolve paged model type annotated type.
+ *
+ * @param type the type
+ * @return the annotated type
+ */
+ private AnnotatedType resolvePagedModelType(AnnotatedType type) {
+ Type pageType = type.getType();
+ if (pageType instanceof ParameterizedType) {
+ Type argumentType = ((ParameterizedType) type.getType()).getActualTypeArguments()[0];
+ Type pagedModelType = ResolvableType
+ .forClassWithGenerics(PagedModel.class, ResolvableType.forType(argumentType))
+ .getType();
+ return new AnnotatedType(pagedModelType).resolveAsRef(true);
+ }
+ else {
+ return PAGED_MODEL;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/PageableOpenAPIConverter.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/PageableOpenAPIConverter.java
index 8bf14d5ea..0bae9272a 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/PageableOpenAPIConverter.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/PageableOpenAPIConverter.java
@@ -3,23 +3,25 @@
* *
* * *
* * * *
- * * * * * Copyright 2019-2022 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
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
* * * * *
- * * * * * https://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.springdoc.core.converters;
@@ -31,12 +33,14 @@
import io.swagger.v3.core.converter.ModelConverter;
import io.swagger.v3.core.converter.ModelConverterContext;
import io.swagger.v3.oas.models.media.Schema;
-import org.apache.commons.lang3.StringUtils;
import org.springdoc.core.converters.models.Pageable;
import org.springdoc.core.providers.ObjectMapperProvider;
+import static org.springdoc.core.utils.SpringDocUtils.getParentTypeName;
+
/**
* The Pageable Type models converter.
+ *
* @author bnasslahsen
*/
public class PageableOpenAPIConverter implements ModelConverter {
@@ -87,7 +91,7 @@ public Schema resolve(AnnotatedType type, ModelConverterContext context, Iterato
if (!type.isSchemaProperty())
type = PAGEABLE;
else
- type.name(cls.getSimpleName() + StringUtils.capitalize(type.getParent().getType()));
+ type.name(getParentTypeName(type, cls));
}
}
return (chain.hasNext()) ? chain.next().resolve(type, context, chain) : null;
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/PolymorphicModelConverter.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/PolymorphicModelConverter.java
index 2f04a52c8..8cdbd65a6 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/PolymorphicModelConverter.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/PolymorphicModelConverter.java
@@ -3,19 +3,21 @@
* *
* * *
* * * *
- * * * * * Copyright 2019-2022 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
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
* * * * *
- * * * * * https://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.
* * * *
* * *
* *
@@ -24,23 +26,34 @@
package org.springdoc.core.converters;
+import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
+import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
+import java.util.Set;
+import com.fasterxml.jackson.annotation.JsonUnwrapped;
import com.fasterxml.jackson.databind.JavaType;
import io.swagger.v3.core.converter.AnnotatedType;
import io.swagger.v3.core.converter.ModelConverter;
import io.swagger.v3.core.converter.ModelConverterContext;
+import io.swagger.v3.core.jackson.TypeNameResolver;
import io.swagger.v3.core.util.AnnotationsUtils;
+import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.media.ComposedSchema;
import io.swagger.v3.oas.models.media.ObjectSchema;
import io.swagger.v3.oas.models.media.Schema;
+import org.apache.commons.lang3.ArrayUtils;
+import org.apache.commons.lang3.reflect.FieldUtils;
import org.springdoc.core.providers.ObjectMapperProvider;
/**
* The type Polymorphic model converter.
+ *
* @author bnasslahsen
*/
public class PolymorphicModelConverter implements ModelConverter {
@@ -50,6 +63,22 @@ public class PolymorphicModelConverter implements ModelConverter {
*/
private final ObjectMapperProvider springDocObjectMapper;
+ /**
+ * The constant PARENT_TYPES_TO_IGNORE.
+ */
+ private static final Set PARENT_TYPES_TO_IGNORE = Collections.synchronizedSet(new HashSet<>());
+
+ /**
+ * The constant PARENT_TYPES_TO_IGNORE.
+ */
+ private static final Set TYPES_TO_SKIP = Collections.synchronizedSet(new HashSet<>());
+
+ static {
+ PARENT_TYPES_TO_IGNORE.add("JsonSchema");
+ PARENT_TYPES_TO_IGNORE.add("Pageable");
+ PARENT_TYPES_TO_IGNORE.add("EntityModel");
+ }
+
/**
* Instantiates a new Polymorphic model converter.
*
@@ -59,12 +88,30 @@ public PolymorphicModelConverter(ObjectMapperProvider springDocObjectMapper) {
this.springDocObjectMapper = springDocObjectMapper;
}
- private static Schema> getResolvedSchema(JavaType javaType, Schema> resolvedSchema) {
+ /**
+ * Add parent type.
+ *
+ * @param parentTypes the parent types
+ */
+ public static void addParentType(String... parentTypes) {
+ PARENT_TYPES_TO_IGNORE.addAll(List.of(parentTypes));
+ }
+
+ /**
+ * Gets resolved schema.
+ *
+ * @param javaType the java type
+ * @param resolvedSchema the resolved schema
+ * @return the resolved schema
+ */
+ private Schema> getResolvedSchema(JavaType javaType, Schema> resolvedSchema) {
if (resolvedSchema instanceof ObjectSchema && resolvedSchema.getProperties() != null) {
- if (resolvedSchema.getProperties().containsKey(javaType.getRawClass().getName()))
+ if (resolvedSchema.getProperties().containsKey(javaType.getRawClass().getName())) {
resolvedSchema = resolvedSchema.getProperties().get(javaType.getRawClass().getName());
- else if (resolvedSchema.getProperties().containsKey(javaType.getRawClass().getSimpleName()))
+ }
+ else if (resolvedSchema.getProperties().containsKey(javaType.getRawClass().getSimpleName())) {
resolvedSchema = resolvedSchema.getProperties().get(javaType.getRawClass().getSimpleName());
+ }
}
return resolvedSchema;
}
@@ -73,11 +120,36 @@ else if (resolvedSchema.getProperties().containsKey(javaType.getRawClass().getSi
public Schema resolve(AnnotatedType type, ModelConverterContext context, Iterator chain) {
JavaType javaType = springDocObjectMapper.jsonMapper().constructType(type.getType());
if (javaType != null) {
+ for (Field field : FieldUtils.getAllFields(javaType.getRawClass())) {
+ if (field.isAnnotationPresent(JsonUnwrapped.class)) {
+ if (!TypeNameResolver.std.getUseFqn())
+ PARENT_TYPES_TO_IGNORE.add(javaType.getRawClass().getSimpleName());
+ else
+ PARENT_TYPES_TO_IGNORE.add(javaType.getRawClass().getName());
+ }
+ else if (field.isAnnotationPresent(io.swagger.v3.oas.annotations.media.Schema.class)) {
+ io.swagger.v3.oas.annotations.media.Schema declaredSchema = field.getDeclaredAnnotation(io.swagger.v3.oas.annotations.media.Schema.class);
+ if (ArrayUtils.isNotEmpty(declaredSchema.oneOf()) || ArrayUtils.isNotEmpty(declaredSchema.allOf())) {
+ TYPES_TO_SKIP.add(field.getType().getSimpleName());
+ }
+ }
+ }
if (chain.hasNext()) {
+ if (!type.isResolveAsRef() && type.getParent() != null
+ && PARENT_TYPES_TO_IGNORE.stream().noneMatch(ignore -> type.getParent().getName().startsWith(ignore)))
+ type.resolveAsRef(true);
Schema> resolvedSchema = chain.next().resolve(type, context, chain);
resolvedSchema = getResolvedSchema(javaType, resolvedSchema);
- if (resolvedSchema == null || resolvedSchema.get$ref() == null)
+ if (resolvedSchema == null || resolvedSchema.get$ref() == null) {
return resolvedSchema;
+ }
+ if (resolvedSchema.get$ref().contains(Components.COMPONENTS_SCHEMAS_REF)) {
+ String schemaName = resolvedSchema.get$ref().substring(Components.COMPONENTS_SCHEMAS_REF.length());
+ Schema existingSchema = context.getDefinedModels().get(schemaName);
+ if (existingSchema != null && (existingSchema.getOneOf() != null || existingSchema.getAllOf() != null)) {
+ return resolvedSchema;
+ }
+ }
return composePolymorphicSchema(type, resolvedSchema, context.getDefinedModels().values());
}
}
@@ -87,13 +159,32 @@ public Schema resolve(AnnotatedType type, ModelConverterContext context, Iterato
/**
* Compose polymorphic schema.
*
- * @param type the type
- * @param schema the schema
+ * @param type the type
+ * @param schema the schema
* @param schemas the schemas
* @return the schema
*/
private Schema composePolymorphicSchema(AnnotatedType type, Schema schema, Collection schemas) {
String ref = schema.get$ref();
+ List composedSchemas = findComposedSchemas(ref, schemas);
+ if (composedSchemas.isEmpty()) return schema;
+ ComposedSchema result = new ComposedSchema();
+ if (isConcreteClass(type)) result.addOneOfItem(schema);
+ JavaType javaType = springDocObjectMapper.jsonMapper().constructType(type.getType());
+ Class> clazz = javaType.getRawClass();
+ if (TYPES_TO_SKIP.stream().noneMatch(typeToSkip -> typeToSkip.equals(clazz.getSimpleName())))
+ composedSchemas.forEach(result::addOneOfItem);
+ return result;
+ }
+
+ /**
+ * Find composed schemas recursively.
+ *
+ * @param ref the reference of the schema
+ * @param schemas the collection of schemas to search in
+ * @return the list of composed schemas
+ */
+ private List findComposedSchemas(String ref, Collection schemas) {
List composedSchemas = schemas.stream()
.filter(ComposedSchema.class::isInstance)
.map(ComposedSchema.class::cast)
@@ -101,12 +192,15 @@ private Schema composePolymorphicSchema(AnnotatedType type, Schema schema, Colle
.filter(s -> s.getAllOf().stream().anyMatch(s2 -> ref.equals(s2.get$ref())))
.map(s -> new Schema().$ref(AnnotationsUtils.COMPONENTS_REF + s.getName()))
.toList();
- if (composedSchemas.isEmpty()) return schema;
- ComposedSchema result = new ComposedSchema();
- if (isConcreteClass(type)) result.addOneOfItem(schema);
- composedSchemas.forEach(result::addOneOfItem);
- return result;
+ List resultSchemas = new ArrayList<>(composedSchemas);
+
+ for (Schema childSchema : composedSchemas) {
+ String childSchemaRef = childSchema.get$ref();
+ resultSchemas.addAll(findComposedSchemas(childSchemaRef, schemas));
+ }
+
+ return resultSchemas;
}
/**
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/PropertyCustomizingConverter.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/PropertyCustomizingConverter.java
index f82afbb45..85fb1e30c 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/PropertyCustomizingConverter.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/PropertyCustomizingConverter.java
@@ -3,23 +3,25 @@
* *
* * *
* * * *
- * * * * * Copyright 2019-2022 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
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
* * * * *
- * * * * * https://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.springdoc.core.converters;
@@ -36,6 +38,7 @@
/**
* The type Property customizing converter.
+ *
* @author bnasslahsen
*/
public class PropertyCustomizingConverter implements ModelConverter {
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/RepresentationModelLinksOASMixin.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/RepresentationModelLinksOASMixin.java
deleted file mode 100644
index 6a5f3e7a7..000000000
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/RepresentationModelLinksOASMixin.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- *
- * *
- * * *
- * * * *
- * * * * * Copyright 2019-2022 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
- * * * * *
- * * * * * https://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.springdoc.core.converters;
-
-import io.swagger.v3.core.util.AnnotationsUtils;
-import io.swagger.v3.oas.annotations.media.Schema;
-
-import org.springframework.hateoas.Links;
-import org.springframework.hateoas.mediatype.hal.RepresentationModelMixin;
-
-/**
- * The type Representation model links oas mixin.
- * @author bnasslahsen
- */
-public abstract class RepresentationModelLinksOASMixin extends RepresentationModelMixin {
- @Override
- @Schema(ref = AnnotationsUtils.COMPONENTS_REF + "Links")
- public abstract Links getLinks();
-}
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/ResponseSupportConverter.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/ResponseSupportConverter.java
index 6ce3e79e5..118152a3c 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/ResponseSupportConverter.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/ResponseSupportConverter.java
@@ -3,23 +3,25 @@
* *
* * *
* * * *
- * * * * * Copyright 2019-2022 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
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
* * * * *
- * * * * * https://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.springdoc.core.converters;
@@ -35,12 +37,15 @@
import io.swagger.v3.oas.models.media.StringSchema;
import org.springdoc.core.providers.ObjectMapperProvider;
+import org.springframework.http.ResponseEntity;
+
import static org.springdoc.core.converters.ConverterUtils.isFluxTypeWrapper;
import static org.springdoc.core.converters.ConverterUtils.isResponseTypeToIgnore;
import static org.springdoc.core.converters.ConverterUtils.isResponseTypeWrapper;
/**
* The type Response support converter.
+ *
* @author bnasslahsen
*/
public class ResponseSupportConverter implements ModelConverter {
@@ -65,7 +70,7 @@ public Schema resolve(AnnotatedType type, ModelConverterContext context, Iterato
if (javaType != null) {
Class> cls = javaType.getRawClass();
if (isResponseTypeWrapper(cls) && !isFluxTypeWrapper(cls)) {
- JavaType innerType = javaType.getBindings().getBoundType(0);
+ JavaType innerType = findResponseEntity(javaType).containedType(0);
if (innerType == null)
return new StringSchema();
return context.resolve(new AnnotatedType(innerType)
@@ -79,4 +84,18 @@ else if (isResponseTypeToIgnore(cls))
return (chain.hasNext()) ? chain.next().resolve(type, context, chain) : null;
}
+ /**
+ * Find response entity java type.
+ *
+ * @param javaType the java type
+ * @return the java type
+ */
+ private JavaType findResponseEntity(JavaType javaType){
+ if(ResponseEntity.class.isAssignableFrom(javaType.getRawClass())){
+ while (ResponseEntity.class != javaType.getRawClass())
+ javaType = javaType.getSuperClass();
+ }
+ return javaType;
+ }
+
}
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/SchemaPropertyDeprecatingConverter.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/SchemaPropertyDeprecatingConverter.java
index 919484a4a..06340b00a 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/SchemaPropertyDeprecatingConverter.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/SchemaPropertyDeprecatingConverter.java
@@ -3,23 +3,25 @@
* *
* * *
* * * *
- * * * * * Copyright 2019-2022 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
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
* * * * *
- * * * * * https://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.springdoc.core.converters;
@@ -41,6 +43,7 @@
/**
* The type Schema property deprecating converter.
+ *
* @author bnasslahsen
*/
public class SchemaPropertyDeprecatingConverter implements ModelConverter {
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/SortOpenAPIConverter.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/SortOpenAPIConverter.java
index bc8fe5ce4..3b2b77929 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/SortOpenAPIConverter.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/SortOpenAPIConverter.java
@@ -1,27 +1,31 @@
-package org.springdoc.core.converters;
-
/*
*
* *
* * *
- * * * * Copyright 2019-2022 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
* * * *
- * * * * https://www.apache.org/licenses/LICENSE-2.0
+ * * * * *
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
+ * * * * *
* * * *
- * * * * 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.springdoc.core.converters;
+
import java.util.Iterator;
import com.fasterxml.jackson.databind.JavaType;
@@ -29,16 +33,21 @@
import io.swagger.v3.core.converter.ModelConverter;
import io.swagger.v3.core.converter.ModelConverterContext;
import io.swagger.v3.oas.models.media.Schema;
-import org.apache.commons.lang3.StringUtils;
import org.springdoc.core.converters.models.Sort;
import org.springdoc.core.providers.ObjectMapperProvider;
+import static org.springdoc.core.utils.SpringDocUtils.getParentTypeName;
+
/**
* The Spring Data Sort type model converter.
- * @author daniel-shuy
+ *
+ * @author daniel -shuy
*/
public class SortOpenAPIConverter implements ModelConverter {
+ /**
+ * The constant SORT_TO_REPLACE.
+ */
private static final String SORT_TO_REPLACE = "org.springframework.data.domain.Sort";
/**
@@ -77,7 +86,7 @@ public Schema resolve(AnnotatedType type, ModelConverterContext context, Iterato
if (!type.isSchemaProperty())
type = SORT;
else
- type.name(cls.getSimpleName() + StringUtils.capitalize(type.getParent().getType()));
+ type.name(getParentTypeName(type, cls));
}
}
return (chain.hasNext()) ? chain.next().resolve(type, context, chain) : null;
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/WebFluxSupportConverter.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/WebFluxSupportConverter.java
index 08137e942..62f04c19e 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/WebFluxSupportConverter.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/WebFluxSupportConverter.java
@@ -3,23 +3,25 @@
* *
* * *
* * * *
- * * * * * Copyright 2019-2022 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
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
* * * * *
- * * * * * https://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.springdoc.core.converters;
@@ -44,6 +46,7 @@
/**
* The type Web flux support converter.
+ *
* @author bnasslahsen
*/
public class WebFluxSupportConverter implements ModelConverter {
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/models/DefaultPageable.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/models/DefaultPageable.java
index b33db51e0..2d0afe986 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/models/DefaultPageable.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/models/DefaultPageable.java
@@ -3,23 +3,25 @@
* *
* * *
* * * *
- * * * * * Copyright 2019-2022 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
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
* * * * *
- * * * * * https://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.springdoc.core.converters.models;
@@ -30,6 +32,7 @@
/**
* The type Default pageable.
+ *
* @author bnasslahsen
*/
@ParameterObject
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/models/MonetaryAmount.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/models/MonetaryAmount.java
index 34cd2654c..a37c4c33c 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/models/MonetaryAmount.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/models/MonetaryAmount.java
@@ -3,23 +3,25 @@
* *
* * *
* * * *
- * * * * * Copyright 2019-2022 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
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
* * * * *
- * * * * * https://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.springdoc.core.converters.models;
@@ -31,6 +33,7 @@
/**
* The type Monetary amount.
+ *
* @author bnasslahsen
*/
@Schema
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/models/Pageable.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/models/Pageable.java
index b97360821..b469e88a3 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/models/Pageable.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/models/Pageable.java
@@ -3,23 +3,25 @@
* *
* * *
* * * *
- * * * * * Copyright 2019-2022 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
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
* * * * *
- * * * * * https://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.springdoc.core.converters.models;
@@ -34,6 +36,7 @@
/**
* The type Pageable.
+ *
* @author bnasslahsen
*/
public class Pageable {
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/models/PageableAsQueryParam.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/models/PageableAsQueryParam.java
index 7ab5f3a6a..6bad26ab1 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/models/PageableAsQueryParam.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/models/PageableAsQueryParam.java
@@ -3,23 +3,25 @@
* *
* * *
* * * *
- * * * * * Copyright 2019-2022 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
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
* * * * *
- * * * * * https://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.springdoc.core.converters.models;
@@ -36,6 +38,7 @@
/**
* The interface Pageable as query param.
+ *
* @author bnasslahsen
*/
@Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE })
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/models/Sort.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/models/Sort.java
index d698a9a2b..15055afc8 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/models/Sort.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/models/Sort.java
@@ -1,27 +1,31 @@
-package org.springdoc.core.converters.models;
-
/*
*
* *
* * *
- * * * * Copyright 2019-2022 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
+ * * * * *
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
+ * * * * *
* * * *
- * * * * https://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.springdoc.core.converters.models;
+
import java.util.List;
import java.util.Objects;
@@ -31,7 +35,8 @@
/**
* The Sort type.
- * @author daniel-shuy
+ *
+ * @author daniel -shuy
*/
public class Sort {
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/models/SortAsQueryParam.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/models/SortAsQueryParam.java
new file mode 100644
index 000000000..56e3b62bd
--- /dev/null
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/models/SortAsQueryParam.java
@@ -0,0 +1,52 @@
+/*
+ *
+ * *
+ * * *
+ * * * *
+ * * * * *
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.springdoc.core.converters.models;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.enums.ParameterIn;
+import io.swagger.v3.oas.annotations.media.ArraySchema;
+import io.swagger.v3.oas.annotations.media.Schema;
+
+/**
+ * The Sort class as query param.
+ *
+ * @author ondrejkrpec
+ */
+@Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE })
+@Retention(RetentionPolicy.RUNTIME)
+@Parameter(in = ParameterIn.QUERY
+ , description = "Sorting criteria in the format: property,(asc|desc). "
+ + "Default sort order is ascending. " + "Multiple sort criteria are supported."
+ , name = "sort"
+ , array = @ArraySchema(schema = @Schema(type = "string"))
+)
+public @interface SortAsQueryParam {}
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/models/SortObject.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/models/SortObject.java
index c1b851270..f59d862eb 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/models/SortObject.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/models/SortObject.java
@@ -3,23 +3,25 @@
* *
* * *
* * * *
- * * * * * Copyright 2019-2022 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
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
* * * * *
- * * * * * https://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.springdoc.core.converters.models;
@@ -29,6 +31,7 @@
/**
* The type Sort response.
+ *
* @author bnasslahsen
*/
@ArraySchema(arraySchema = @Schema(implementation = SortObject.class))
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/ActuatorOpenApiCustomizer.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/ActuatorOpenApiCustomizer.java
index 93c367b22..5810af1da 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/ActuatorOpenApiCustomizer.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/ActuatorOpenApiCustomizer.java
@@ -3,59 +3,52 @@
* *
* * *
* * * *
- * * * * * Copyright 2019-2022 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
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
* * * * *
- * * * * * https://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.springdoc.core.customizers;
import java.util.Comparator;
import java.util.HashSet;
-import java.util.List;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
import java.util.stream.Stream;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.PathItem;
import io.swagger.v3.oas.models.Paths;
-import io.swagger.v3.oas.models.media.StringSchema;
-import io.swagger.v3.oas.models.parameters.Parameter;
-import io.swagger.v3.oas.models.parameters.PathParameter;
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
-import org.springframework.util.CollectionUtils;
-
-import static org.springframework.util.AntPathMatcher.DEFAULT_PATH_SEPARATOR;
/**
- * The type Actuator open api customiser.
+ * The type Actuator open api customizer.
+ *
* @author bnasslahsen
+ * @since 2.7.0
+ * @deprecated as not anymore required, use your own {@link org.springdoc.core.customizers.GlobalOpenApiCustomizer} instead
*/
+@Deprecated(since = "2.7.0")
public class ActuatorOpenApiCustomizer implements GlobalOpenApiCustomizer {
- /**
- * The Path pathern.
- */
- private final Pattern pathPathern = Pattern.compile("\\{(.*?)}");
/**
* The Web endpoint properties.
@@ -71,6 +64,13 @@ public ActuatorOpenApiCustomizer(WebEndpointProperties webEndpointProperties) {
this.webEndpointProperties = webEndpointProperties;
}
+ /**
+ * Actuator path entry stream stream.
+ *
+ * @param openApi the open api
+ * @param relativeSubPath the relative sub path
+ * @return the stream
+ */
private Stream> actuatorPathEntryStream(OpenAPI openApi, String relativeSubPath) {
String pathPrefix = webEndpointProperties.getBasePath() + Optional.ofNullable(relativeSubPath).orElse("");
return Optional.ofNullable(openApi.getPaths())
@@ -80,30 +80,16 @@ private Stream> actuatorPathEntryStream(OpenAPI openApi,
.orElse(Stream.empty());
}
- private void handleActuatorPathParam(OpenAPI openApi) {
- actuatorPathEntryStream(openApi, DEFAULT_PATH_SEPARATOR).forEach(stringPathItemEntry -> {
- String path = stringPathItemEntry.getKey();
- Matcher matcher = pathPathern.matcher(path);
- while (matcher.find()) {
- String pathParam = matcher.group(1);
- PathItem pathItem = stringPathItemEntry.getValue();
- pathItem.readOperations().forEach(operation -> {
- List existingParameters = operation.getParameters();
- Optional existingParam = Optional.empty();
- if (!CollectionUtils.isEmpty(existingParameters))
- existingParam = existingParameters.stream().filter(p -> pathParam.equals(p.getName())).findAny();
- if (!existingParam.isPresent())
- operation.addParametersItem(new PathParameter().name(pathParam).schema(new StringSchema()));
- });
- }
- });
- }
-
+ /**
+ * Handle actuator operation id uniqueness.
+ *
+ * @param openApi the open api
+ */
private void handleActuatorOperationIdUniqueness(OpenAPI openApi) {
Set usedOperationIds = new HashSet<>();
actuatorPathEntryStream(openApi, null)
.sorted(Comparator.comparing(Entry::getKey))
- .forEachOrdered(stringPathItemEntry -> {
+ .forEachOrdered(stringPathItemEntry ->
stringPathItemEntry.getValue().readOperations().forEach(operation -> {
String initialOperationId = operation.getOperationId();
String uniqueOperationId = operation.getOperationId();
@@ -112,13 +98,12 @@ private void handleActuatorOperationIdUniqueness(OpenAPI openApi) {
uniqueOperationId = initialOperationId + "_" + ++counter;
}
operation.setOperationId(uniqueOperationId);
- });
- });
+ })
+ );
}
@Override
public void customise(OpenAPI openApi) {
- handleActuatorPathParam(openApi);
handleActuatorOperationIdUniqueness(openApi);
}
}
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/ActuatorOperationCustomizer.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/ActuatorOperationCustomizer.java
index 985513421..df37c2b43 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/ActuatorOperationCustomizer.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/ActuatorOperationCustomizer.java
@@ -3,54 +3,62 @@
* *
* * *
* * * *
- * * * * * Copyright 2019-2022 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
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
* * * * *
- * * * * * https://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.springdoc.core.customizers;
import java.lang.reflect.Field;
import java.lang.reflect.Parameter;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
import io.swagger.v3.core.util.AnnotationsUtils;
+import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.media.Content;
import io.swagger.v3.oas.models.media.MediaType;
import io.swagger.v3.oas.models.media.Schema;
import io.swagger.v3.oas.models.parameters.RequestBody;
+import io.swagger.v3.oas.models.responses.ApiResponse;
+import io.swagger.v3.oas.models.responses.ApiResponses;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springdoc.core.properties.SpringDocConfigProperties;
-import org.springframework.boot.actuate.endpoint.OperationType;
+import org.springframework.boot.actuate.endpoint.ApiVersion;
+import org.springframework.boot.actuate.endpoint.SecurityContext;
import org.springframework.boot.actuate.endpoint.annotation.AbstractDiscoveredOperation;
import org.springframework.boot.actuate.endpoint.annotation.Selector;
import org.springframework.boot.actuate.endpoint.invoke.OperationParameter;
import org.springframework.boot.actuate.endpoint.invoke.reflect.OperationMethod;
+import org.springframework.boot.actuate.endpoint.web.WebServerNamespace;
+import org.springframework.http.HttpStatus;
import org.springframework.web.method.HandlerMethod;
import static org.springdoc.core.providers.ActuatorProvider.getTag;
+import static org.springdoc.core.utils.SpringDocUtils.handleSchemaTypes;
/**
* The type Actuator operation customizer.
+ *
* @author bnasslahsen
*/
public class ActuatorOperationCustomizer implements GlobalOperationCustomizer {
@@ -70,11 +78,6 @@ public class ActuatorOperationCustomizer implements GlobalOperationCustomizer {
*/
private static final Logger LOGGER = LoggerFactory.getLogger(ActuatorOperationCustomizer.class);
- /**
- * The regex pattern for operationId lookup.
- */
- private static final Pattern pattern = Pattern.compile(".*'([^']*)'.*");
-
/**
* The Spring doc config properties.
*/
@@ -92,44 +95,180 @@ public ActuatorOperationCustomizer(SpringDocConfigProperties springDocConfigProp
@Override
public Operation customize(Operation operation, HandlerMethod handlerMethod) {
- if (operation.getTags() != null && operation.getTags().contains(getTag().getName())) {
- Field operationFiled = FieldUtils.getDeclaredField(handlerMethod.getBean().getClass(), OPERATION, true);
- Object actuatorOperation;
- if (operationFiled != null) {
- try {
- actuatorOperation = operationFiled.get(handlerMethod.getBean());
- Field actuatorOperationFiled = FieldUtils.getDeclaredField(actuatorOperation.getClass(), OPERATION, true);
- if (actuatorOperationFiled != null) {
- AbstractDiscoveredOperation discoveredOperation = (AbstractDiscoveredOperation) actuatorOperationFiled.get(actuatorOperation);
- OperationMethod operationMethod = discoveredOperation.getOperationMethod();
- if (OperationType.WRITE.equals(operationMethod.getOperationType())) {
- for (OperationParameter operationParameter : operationMethod.getParameters()) {
- Field parameterField = FieldUtils.getDeclaredField(operationParameter.getClass(), PARAMETER, true);
- Parameter parameter = (Parameter) parameterField.get(operationParameter);
- Schema> schema = AnnotationsUtils.resolveSchemaFromType(parameter.getType(), null, null, springDocConfigProperties.isOpenapi31());
- if (parameter.getAnnotation(Selector.class) == null) {
- operation.setRequestBody(new RequestBody()
- .content(new Content().addMediaType(org.springframework.http.MediaType.APPLICATION_JSON_VALUE, new MediaType().schema(schema))));
- }
- }
- }
- }
- }
- catch (IllegalAccessException e) {
- LOGGER.warn(e.getMessage());
- }
+ if (operationHasValidTag(operation)) {
+ Field operationField = FieldUtils.getDeclaredField(handlerMethod.getBean().getClass(), OPERATION,true);
+ if (operationField != null) {
+ processOperationField(handlerMethod, operation, operationField);
}
+ setOperationSummary(operation, handlerMethod);
+ }
+ return operation;
+ }
- String summary = handlerMethod.toString();
- Matcher matcher = pattern.matcher(summary);
- String operationId = operation.getOperationId();
- while (matcher.find()) {
- operationId = matcher.group(1);
+ /**
+ * Operation has valid tag boolean.
+ *
+ * @param operation the operation
+ * @return the boolean
+ */
+ private boolean operationHasValidTag(Operation operation) {
+ return operation.getTags() != null && operation.getTags().contains(getTag().getName());
+ }
+
+ /**
+ * Process operation field.
+ *
+ * @param handlerMethod the handler method
+ * @param operation the operation
+ * @param operationField the operation field
+ */
+ private void processOperationField(HandlerMethod handlerMethod, Operation operation, Field operationField) {
+ try {
+ Object actuatorOperation = operationField.get(handlerMethod.getBean());
+ Field actuatorOperationField = FieldUtils.getDeclaredField(actuatorOperation.getClass(), OPERATION, true);
+ if (actuatorOperationField != null) {
+ AbstractDiscoveredOperation discoveredOperation =
+ (AbstractDiscoveredOperation) actuatorOperationField.get(actuatorOperation);
+ handleOperationMethod(discoveredOperation.getOperationMethod(), operation);
+ }
+ }
+ catch (IllegalAccessException e) {
+ LOGGER.warn(e.getMessage());
+ }
+ }
+
+ /**
+ * Handle operation method.
+ *
+ * @param operationMethod the operation method
+ * @param operation the operation
+ */
+ private void handleOperationMethod(OperationMethod operationMethod, Operation operation) {
+ String operationId = operationMethod.getMethod().getName();
+ operation.setOperationId(operationId);
+
+ switch (operationMethod.getOperationType()) {
+ case READ:
+ addParameters(operationMethod, operation, ParameterIn.QUERY);
+ break;
+ case WRITE:
+ addWriteParameters(operationMethod, operation);
+ operation.setResponses(new ApiResponses()
+ .addApiResponse(String.valueOf(HttpStatus.NO_CONTENT.value()), new ApiResponse().description(HttpStatus.NO_CONTENT.getReasonPhrase()))
+ .addApiResponse(String.valueOf(HttpStatus.BAD_REQUEST.value()), new ApiResponse().description(HttpStatus.BAD_REQUEST.getReasonPhrase())));
+ break;
+ case DELETE:
+ operation.setResponses(new ApiResponses().addApiResponse(String.valueOf(HttpStatus.NO_CONTENT.value()), new ApiResponse().description(HttpStatus.NO_CONTENT.getReasonPhrase())));
+ addParameters(operationMethod, operation, ParameterIn.QUERY);
+ break;
+ default:
+ break;
+ }
+ }
+
+ /**
+ * Add parameters.
+ *
+ * @param operationMethod the operation method
+ * @param operation the operation
+ * @param parameterIn the parameter in
+ */
+ private void addParameters(OperationMethod operationMethod, Operation operation, ParameterIn parameterIn) {
+ for (OperationParameter operationParameter : operationMethod.getParameters()) {
+ Parameter parameter = getParameterFromField(operationParameter);
+ if(parameter == null) continue;
+ Schema> schema = resolveSchema(parameter);
+ if (parameter.getAnnotation(Selector.class) != null) {
+ operation.addParametersItem(new io.swagger.v3.oas.models.parameters.PathParameter()
+ .name(parameter.getName())
+ .schema(schema));
+ operation.getResponses().addApiResponse(String.valueOf(HttpStatus.NOT_FOUND.value()), new ApiResponse().description(HttpStatus.NOT_FOUND.getReasonPhrase()));
+ }
+ else if (isValidParameterType(parameter)) {
+ operation.addParametersItem(new io.swagger.v3.oas.models.parameters.Parameter()
+ .name(parameter.getName())
+ .in(parameterIn.toString())
+ .schema(schema));
+ }
+ }
+ }
+
+ /**
+ * Add write parameters.
+ *
+ * @param operationMethod the operation method
+ * @param operation the operation
+ */
+ private void addWriteParameters(OperationMethod operationMethod, Operation operation) {
+ for (OperationParameter operationParameter : operationMethod.getParameters()) {
+ Parameter parameter = getParameterFromField(operationParameter);
+ if(parameter == null) continue;
+ Schema> schema = resolveSchema(parameter);
+ if (parameter.getAnnotation(Selector.class) != null) {
+ operation.addParametersItem(new io.swagger.v3.oas.models.parameters.PathParameter()
+ .name(parameter.getName())
+ .schema(schema));
+ }
+ else {
+ operation.setRequestBody(new RequestBody()
+ .content(new Content()
+ .addMediaType(org.springframework.http.MediaType.APPLICATION_JSON_VALUE,
+ new MediaType().schema(schema))));
}
- if (operation.getSummary() == null && !summary.contains("$"))
- operation.setSummary(summary);
- operation.setOperationId(operationId);
}
- return operation;
}
+
+ /**
+ * Gets parameter from field.
+ *
+ * @param operationParameter the operation parameter
+ * @return the parameter from field
+ */
+ private Parameter getParameterFromField(OperationParameter operationParameter) {
+ try {
+ return (Parameter) FieldUtils.readDeclaredField(operationParameter, PARAMETER, true);
+ }
+ catch (IllegalAccessException e) {
+ LOGGER.warn(e.getMessage());
+ return null;
+ }
+ }
+
+ /**
+ * Resolve schema schema.
+ *
+ * @param parameter the parameter
+ * @return the schema
+ */
+ private Schema> resolveSchema(Parameter parameter) {
+ Schema schema = AnnotationsUtils.resolveSchemaFromType(parameter.getType(), null, null, springDocConfigProperties.isOpenapi31());
+ if(springDocConfigProperties.isOpenapi31()) handleSchemaTypes(schema);
+ return schema;
+ }
+
+ /**
+ * Is valid parameter type boolean.
+ *
+ * @param parameter the parameter
+ * @return the boolean
+ */
+ private boolean isValidParameterType(Parameter parameter) {
+ return !ApiVersion.class.isAssignableFrom(parameter.getType()) &&
+ !WebServerNamespace.class.isAssignableFrom(parameter.getType()) &&
+ !SecurityContext.class.isAssignableFrom(parameter.getType());
+ }
+
+ /**
+ * Sets operation summary.
+ *
+ * @param operation the operation
+ * @param handlerMethod the handler method
+ */
+ private void setOperationSummary(Operation operation, HandlerMethod handlerMethod) {
+ String summary = handlerMethod.toString();
+ if (operation.getSummary() == null && !summary.contains("$")) {
+ operation.setSummary(summary);
+ }
+ }
+
}
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/DataRestDelegatingMethodParameterCustomizer.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/DataRestDelegatingMethodParameterCustomizer.java
index 8918b2bc4..8a8ef92dc 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/DataRestDelegatingMethodParameterCustomizer.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/DataRestDelegatingMethodParameterCustomizer.java
@@ -2,28 +2,31 @@
*
* *
* * *
- * * * * Copyright 2019-2022 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
+ * * * * *
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
+ * * * * *
* * * *
- * * * * https://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.springdoc.core.customizers;
import java.lang.annotation.Annotation;
-import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
@@ -50,7 +53,6 @@
import org.apache.commons.lang3.reflect.FieldUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.springdoc.core.extractor.DelegatingMethodParameter;
import org.springdoc.core.providers.RepositoryRestConfigurationProvider;
import org.springdoc.core.providers.SpringDataWebPropertiesProvider;
@@ -86,7 +88,7 @@ public class DataRestDelegatingMethodParameterCustomizer implements DelegatingMe
/**
* Instantiates a new Data rest delegating method parameter customizer.
*
- * @param optionalSpringDataWebPropertiesProvider the optional spring data web properties provider
+ * @param optionalSpringDataWebPropertiesProvider the optional spring data web properties provider
* @param optionalRepositoryRestConfigurationProvider the optional repository rest configuration provider
*/
public DataRestDelegatingMethodParameterCustomizer(Optional optionalSpringDataWebPropertiesProvider, Optional optionalRepositoryRestConfigurationProvider) {
@@ -103,9 +105,8 @@ public void customize(MethodParameter originalParameter, MethodParameter methodP
(Pageable.class.isAssignableFrom(parameterType) || Sort.class.isAssignableFrom(parameterType))
&& (isSpringDataWebPropertiesPresent() || isRepositoryRestConfigurationPresent())
)) {
- Field field = FieldUtils.getDeclaredField(DelegatingMethodParameter.class, "additionalParameterAnnotations", true);
try {
- Annotation[] parameterAnnotations = (Annotation[]) field.get(methodParameter);
+ Annotation[] parameterAnnotations = (Annotation[]) FieldUtils.readDeclaredField(methodParameter, "additionalParameterAnnotations", true);
if (ArrayUtils.isNotEmpty(parameterAnnotations))
for (int i = 0; i < parameterAnnotations.length; i++) {
if (Parameter.class.equals(parameterAnnotations[i].annotationType())) {
@@ -126,15 +127,14 @@ public void customize(MethodParameter originalParameter, MethodParameter methodP
*
* @param methodParameter the method parameter
* @param pageableDefault the pageable default
+ * @param sortDefault the sort default
* @return the new parameter annotation for field
*/
private Optional getNewParameterAnnotationForField(MethodParameter methodParameter, PageableDefault pageableDefault, SortDefault sortDefault) {
String parameterName = methodParameter.getParameterName();
- Field field;
Parameter parameterNew;
try {
- field = methodParameter.getContainingClass().getDeclaredField(parameterName);
- Parameter parameter = field.getAnnotation(Parameter.class);
+ Parameter parameter = methodParameter.getContainingClass().getDeclaredField(parameterName).getAnnotation(Parameter.class);
parameterNew = new Parameter() {
@Override
public Class extends Annotation> annotationType() {
@@ -189,6 +189,10 @@ public boolean allowReserved() {
@Override
public Schema schema() {
return new Schema() {
+ @Override
+ public SchemaResolution schemaResolution() {
+ return parameterSchema.schemaResolution();
+ }
private Schema parameterSchema = parameter.schema();
@@ -938,6 +942,11 @@ public String[] examples() {
public String _const() {
return schema._const();
}
+
+ @Override
+ public SchemaResolution schemaResolution() {
+ return schema.schemaResolution();
+ }
};
}
@@ -1030,7 +1039,7 @@ public String ref() {
* Gets name.
*
* @param parameterName the parameter name
- * @param originalName the original name
+ * @param originalName the original name
* @return the name
*/
private String getName(String parameterName, String originalName) {
@@ -1062,8 +1071,7 @@ else if (isSpringDataWebPropertiesPresent())
else
name = originalName;
break;
- case "direction":
- case "caseSensitive":
+ case "direction", "caseSensitive":
name = originalName;
break;
default:
@@ -1076,7 +1084,7 @@ else if (isSpringDataWebPropertiesPresent())
/**
* Gets description.
*
- * @param parameterName the parameter name
+ * @param parameterName the parameter name
* @param originalDescription the original description
* @return the description
*/
@@ -1090,8 +1098,8 @@ private String getDescription(String parameterName, String originalDescription)
/**
* Gets default value.
*
- * @param parameterName the parameter name
- * @param pageableDefault the pageable default
+ * @param parameterName the parameter name
+ * @param pageableDefault the pageable default
* @param defaultSchemaVal the default schema val
* @return the default value
*/
@@ -1140,9 +1148,9 @@ else if (isSpringDataWebPropertiesPresent() && optionalSpringDataWebPropertiesPr
/**
* Gets default value.
*
- * @param parameterName the parameter name
- * @param pageableDefault the pageable default
- * @param sortDefault the sort default
+ * @param parameterName the parameter name
+ * @param pageableDefault the pageable default
+ * @param sortDefault the sort default
* @param defaultSchemaVal the default schema val
* @return the default value
*/
@@ -1167,7 +1175,7 @@ private String getArrayDefaultValue(String parameterName, PageableDefault pageab
* Gets default sort.
*
* @param pageableDefault the pageable default
- * @param sortDefault the sort default
+ * @param sortDefault the sort default
* @return the default sort
*/
private DefaultSort getDefaultSort(PageableDefault pageableDefault, SortDefault sortDefault) {
@@ -1222,23 +1230,52 @@ private boolean isRepositoryRestConfigurationPresent() {
return optionalRepositoryRestConfigurationProvider.isPresent() && optionalRepositoryRestConfigurationProvider.get().isRepositoryRestConfigurationPresent();
}
+ /**
+ * The type Default sort.
+ */
private static class DefaultSort {
+ /**
+ * The constant DIRECTION_GROUP.
+ */
private static final String DIRECTION_GROUP = Arrays.stream(Sort.Direction.values()).map(Enum::name).collect(Collectors.joining("|"));
+ /**
+ * The constant DIRECTED_REGEXP.
+ */
private static final String DIRECTED_REGEXP = "\\w+(\\.\\w+)*,\\s*(" + DIRECTION_GROUP + ')';
+ /**
+ * The constant DIRECTED_PATTERN.
+ */
private static final Pattern DIRECTED_PATTERN = Pattern.compile(DIRECTED_REGEXP, Pattern.CASE_INSENSITIVE);
+ /**
+ * The Direction.
+ */
private final Sort.Direction direction;
+ /**
+ * The Properties.
+ */
private final String[] properties;
+ /**
+ * Instantiates a new Default sort.
+ *
+ * @param direction the direction
+ * @param properties the properties
+ */
DefaultSort(Sort.Direction direction, String... properties) {
this.direction = direction;
this.properties = properties;
}
+ /**
+ * Gets effective properties.
+ *
+ * @return the effective properties
+ */
List getEffectiveProperties() {
return Arrays.stream(properties)
.map(p -> {
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/DataRestRouterOperationCustomizer.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/DataRestRouterOperationCustomizer.java
index b9f968a4d..a31015f4e 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/DataRestRouterOperationCustomizer.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/DataRestRouterOperationCustomizer.java
@@ -1,3 +1,29 @@
+/*
+ *
+ * *
+ * * *
+ * * * *
+ * * * * *
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.springdoc.core.customizers;
import org.springdoc.core.fn.RouterOperation;
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/DelegatingMethodParameterCustomizer.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/DelegatingMethodParameterCustomizer.java
index 74a3bac4d..d6475c4c4 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/DelegatingMethodParameterCustomizer.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/DelegatingMethodParameterCustomizer.java
@@ -3,23 +3,25 @@
* *
* * *
* * * *
- * * * * * Copyright 2019-2022 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
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
* * * * *
- * * * * * https://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.springdoc.core.customizers;
@@ -36,7 +38,7 @@ public interface DelegatingMethodParameterCustomizer {
* Customize.
*
* @param originalParameter the original parameter
- * @param methodParameter the method parameter
+ * @param methodParameter the method parameter
*/
void customize(MethodParameter originalParameter, MethodParameter methodParameter);
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/GlobalOpenApiCustomizer.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/GlobalOpenApiCustomizer.java
index 8b5130cdc..a2a2fc631 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/GlobalOpenApiCustomizer.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/GlobalOpenApiCustomizer.java
@@ -3,23 +3,25 @@
* *
* * *
* * * *
- * * * * * Copyright 2019-2022 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
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
* * * * *
- * * * * * https://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.springdoc.core.customizers;
@@ -29,7 +31,7 @@
* customize Open api on default OpenAPI description and groups.
*
* @author christophejan
- * @see OpenApiCustomizer customize default OpenAPI description but not groups
+ * @see OpenApiCustomizer default OpenAPI description but not groups
*/
public interface GlobalOpenApiCustomizer extends OpenApiCustomizer {
}
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/GlobalOperationCustomizer.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/GlobalOperationCustomizer.java
index 9dc560053..22dc998ec 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/GlobalOperationCustomizer.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/GlobalOperationCustomizer.java
@@ -3,23 +3,25 @@
* *
* * *
* * * *
- * * * * * Copyright 2019-2022 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
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
* * * * *
- * * * * * https://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.springdoc.core.customizers;
@@ -30,7 +32,7 @@
* description and groups
*
* @author christophejan
- * @see OperationCustomizer customize operations on default OpenAPI description but not groups
+ * @see OperationCustomizer operations on default OpenAPI description but not groups
*/
public interface GlobalOperationCustomizer extends OperationCustomizer {
}
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/JavadocPropertyCustomizer.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/JavadocPropertyCustomizer.java
index e81ea2225..db9cf5141 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/JavadocPropertyCustomizer.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/JavadocPropertyCustomizer.java
@@ -3,23 +3,25 @@
* *
* * *
* * * *
- * * * * * Copyright 2019-2023 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
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
* * * * *
- * * * * * https://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.springdoc.core.customizers;
@@ -44,6 +46,7 @@
import io.swagger.v3.core.converter.ModelConverterContext;
import io.swagger.v3.core.converter.ModelConverterContextImpl;
import io.swagger.v3.core.util.AnnotationsUtils;
+import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.media.Schema;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.reflect.FieldUtils;
@@ -64,6 +67,9 @@ public record JavadocPropertyCustomizer(JavadocProvider javadocProvider,
ObjectMapperProvider objectMapperProvider)
implements ModelConverter {
+ /**
+ * The constant LOGGER.
+ */
private static final Logger LOGGER = LoggerFactory.getLogger(DelegatingMethodParameter.class);
/**
@@ -95,7 +101,7 @@ public Schema resolve(AnnotatedType type, ModelConverterContext context, Iterato
setJavadocDescription(cls, fields, clsProperties, existingSchema, false);
}
else if (resolvedSchema != null && resolvedSchema.get$ref() != null && resolvedSchema.get$ref().contains(AnnotationsUtils.COMPONENTS_REF)) {
- String schemaName = resolvedSchema.get$ref().substring(21);
+ String schemaName = resolvedSchema.get$ref().substring(Components.COMPONENTS_SCHEMAS_REF.length());
Schema existingSchema = context.getDefinedModels().get(schemaName);
setJavadocDescription(cls, fields, clsProperties, existingSchema, false);
}
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/KotlinDeprecatedPropertyCustomizer.kt b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/KotlinDeprecatedPropertyCustomizer.kt
new file mode 100644
index 000000000..3e397242d
--- /dev/null
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/KotlinDeprecatedPropertyCustomizer.kt
@@ -0,0 +1,83 @@
+/*
+ *
+ * *
+ * * *
+ * * * *
+ * * * * *
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.springdoc.core.customizers
+
+import com.fasterxml.jackson.databind.JavaType
+import io.swagger.v3.core.converter.AnnotatedType
+import io.swagger.v3.core.converter.ModelConverter
+import io.swagger.v3.core.converter.ModelConverterContext
+import io.swagger.v3.oas.models.Components
+import io.swagger.v3.oas.models.media.Schema
+import org.springdoc.core.providers.ObjectMapperProvider
+import kotlin.reflect.full.findAnnotation
+import kotlin.reflect.full.hasAnnotation
+import kotlin.reflect.full.memberProperties
+
+/**
+ * Kotlin Deprecated PropertyCustomizer to handle Kotlin Deprecated annotations.
+ * @author bnasslahsen
+ */
+class KotlinDeprecatedPropertyCustomizer(
+ private val objectMapperProvider: ObjectMapperProvider
+) : ModelConverter {
+
+ override fun resolve(
+ type: AnnotatedType,
+ context: ModelConverterContext,
+ chain: Iterator
+ ): Schema<*>? {
+ if (!chain.hasNext()) return null
+ // Resolve the next model in the chain
+ val resolvedSchema = chain.next().resolve(type, context, chain)
+
+ val javaType: JavaType =
+ objectMapperProvider.jsonMapper().constructType(type.type)
+ val kotlinClass = javaType.rawClass.kotlin
+
+ // Check each property of the class
+ for (prop in kotlinClass.memberProperties) {
+ val deprecatedAnnotation = prop.findAnnotation()
+ prop.hasAnnotation()
+ if (deprecatedAnnotation != null) {
+ val fieldName = prop.name
+ if (resolvedSchema.`$ref` != null) {
+ val schema =
+ context.getDefinedModels()[resolvedSchema.`$ref`.substring(
+ Components.COMPONENTS_SCHEMAS_REF.length
+ )]
+ schema?.properties?.get(fieldName)?.deprecated = true
+ if (deprecatedAnnotation.message.isNotBlank()) {
+ schema?.properties?.get(fieldName)?.description =
+ schema?.properties?.get(fieldName)?.description?.takeIf { it.isNotBlank() }
+ ?: deprecatedAnnotation.message
+ }
+ }
+ }
+ }
+ return resolvedSchema
+ }
+}
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/OpenApiBuilderCustomizer.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/OpenApiBuilderCustomizer.java
index 25d8d467e..4631fbd0b 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/OpenApiBuilderCustomizer.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/OpenApiBuilderCustomizer.java
@@ -3,23 +3,25 @@
* *
* * *
* * * *
- * * * * * Copyright 2019-2022 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
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
* * * * *
- * * * * * https://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.springdoc.core.customizers;
@@ -28,6 +30,7 @@
/**
* The interface Open api builder customizer.
+ *
* @author bnasslahsen
*/
@FunctionalInterface
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/OpenApiCustomizer.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/OpenApiCustomizer.java
index 970203322..f54d294c4 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/OpenApiCustomizer.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/OpenApiCustomizer.java
@@ -3,23 +3,25 @@
* *
* * *
* * * *
- * * * * * Copyright 2019-2022 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
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
* * * * *
- * * * * * https://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.springdoc.core.customizers;
@@ -31,7 +33,7 @@
* Open api on default OpenAPI description but not on groups
*
* @author bnasslahsen
- * @see GlobalOpenApiCustomizer customize default OpenAPI description and groups
+ * @see GlobalOpenApiCustomizer default OpenAPI description and groups
*/
@FunctionalInterface
public interface OpenApiCustomizer {
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/OpenApiHateoasLinksCustomizer.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/OpenApiHateoasLinksCustomizer.java
index 4c1d80b0e..c3cae9d1e 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/OpenApiHateoasLinksCustomizer.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/OpenApiHateoasLinksCustomizer.java
@@ -3,23 +3,25 @@
* *
* * *
* * * *
- * * * * * Copyright 2019-2022 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
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
* * * * *
- * * * * * https://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.springdoc.core.customizers;
@@ -31,7 +33,7 @@
import io.swagger.v3.core.util.AnnotationsUtils;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.media.MapSchema;
-import io.swagger.v3.oas.models.media.ObjectSchema;
+import io.swagger.v3.oas.models.media.Schema;
import io.swagger.v3.oas.models.media.StringSchema;
import org.springdoc.core.properties.SpringDocConfigProperties;
@@ -39,6 +41,7 @@
/**
* The type Open api hateoas links customiser.
+ *
* @author bnasslahsen
*/
public class OpenApiHateoasLinksCustomizer extends SpecFilter implements GlobalOpenApiCustomizer {
@@ -65,7 +68,7 @@ public void customise(OpenAPI openApi) {
.schema("Link", resolvedLinkSchema.schema)
.schema("Links", new MapSchema()
.additionalProperties(new StringSchema())
- .additionalProperties(new ObjectSchema().$ref(AnnotationsUtils.COMPONENTS_REF + "Link")));
+ .additionalProperties(new Schema<>().$ref(AnnotationsUtils.COMPONENTS_REF + "Link")));
if (springDocConfigProperties.isRemoveBrokenReferenceDefinitions())
this.removeBrokenReferenceDefinitions(openApi);
}
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/OpenApiLocaleCustomizer.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/OpenApiLocaleCustomizer.java
index 568945325..af86fc0ea 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/OpenApiLocaleCustomizer.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/OpenApiLocaleCustomizer.java
@@ -3,23 +3,25 @@
* *
* * *
* * * *
- * * * * * Copyright 2019-2022 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
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
* * * * *
- * * * * * https://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.springdoc.core.customizers;
@@ -30,6 +32,7 @@
/**
* The interface Open api locale customizer.
+ *
* @author bnasslahsen
*/
@FunctionalInterface
@@ -39,7 +42,7 @@ public interface OpenApiLocaleCustomizer {
* Customise.
*
* @param openApi the open api
- * @param locale the locale
+ * @param locale the locale
*/
void customise(OpenAPI openApi, Locale locale);
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/OperationCustomizer.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/OperationCustomizer.java
index 015f4afc7..518802606 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/OperationCustomizer.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/OperationCustomizer.java
@@ -3,23 +3,25 @@
* *
* * *
* * * *
- * * * * * Copyright 2019-2022 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
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
* * * * *
- * * * * * https://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.springdoc.core.customizers;
@@ -34,7 +36,7 @@
* groups
*
* @author bnasslahsen
- * @see GlobalOperationCustomizer customize operations on default OpenAPI description and groups
+ * @see GlobalOperationCustomizer operations on default OpenAPI description and groups
*/
@FunctionalInterface
public interface OperationCustomizer {
@@ -42,7 +44,7 @@ public interface OperationCustomizer {
/**
* Customize operation.
*
- * @param operation input operation
+ * @param operation input operation
* @param handlerMethod original handler method
* @return customized operation
*/
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/OperationIdCustomizer.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/OperationIdCustomizer.java
new file mode 100644
index 000000000..dc718aa5e
--- /dev/null
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/OperationIdCustomizer.java
@@ -0,0 +1,92 @@
+/*
+ *
+ * *
+ * * *
+ * * * *
+ * * * * *
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.springdoc.core.customizers;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import io.swagger.v3.oas.models.OpenAPI;
+import io.swagger.v3.oas.models.Operation;
+import io.swagger.v3.oas.models.PathItem;
+
+/**
+ * The type Operation id customizer.
+ *
+ * @author bnasslahsen
+ */
+public class OperationIdCustomizer implements GlobalOpenApiCustomizer {
+
+ @Override
+ public void customise(OpenAPI openApi) {
+ // Map to store operationId counts
+ Map operationIdCount = new HashMap<>();
+
+ // Iterate through all the paths
+ for (Map.Entry pathEntry : openApi.getPaths().entrySet()) {
+ PathItem pathItem = pathEntry.getValue();
+
+ // Process all HTTP methods for the path (GET, POST, PUT, DELETE, etc.)
+ processOperation(pathItem.getGet(), operationIdCount);
+ processOperation(pathItem.getPost(), operationIdCount);
+ processOperation(pathItem.getPut(), operationIdCount);
+ processOperation(pathItem.getDelete(), operationIdCount);
+ processOperation(pathItem.getPatch(), operationIdCount);
+ processOperation(pathItem.getHead(), operationIdCount);
+ processOperation(pathItem.getOptions(), operationIdCount);
+ processOperation(pathItem.getTrace(), operationIdCount);
+ }
+ }
+
+ /**
+ * Process operation.
+ *
+ * @param operation the operation
+ * @param operationIdCount the operation id count
+ */
+// Helper method to process each operation and handle duplicate operationId
+ private void processOperation(Operation operation, Map operationIdCount) {
+ if (operation != null) {
+ String originalOperationId = operation.getOperationId();
+
+ // Check if operationId already exists
+ if ( originalOperationId!=null && operationIdCount.containsKey(originalOperationId)) {
+ // Get the count for the current operationId and increment
+ int count = operationIdCount.get(originalOperationId);
+ count++;
+ operationIdCount.put(originalOperationId, count);
+
+ // Create new unique operationId by appending _x
+ String newOperationId = originalOperationId + "_" + count;
+ operation.setOperationId(newOperationId);
+ }
+ else {
+ // First time this operationId is seen, initialize the count
+ operationIdCount.put(originalOperationId, 0);
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/ParameterCustomizer.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/ParameterCustomizer.java
index 7dbaa0d3c..084ae2cc6 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/ParameterCustomizer.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/ParameterCustomizer.java
@@ -3,23 +3,25 @@
* *
* * *
* * * *
- * * * * * Copyright 2019-2022 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
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
* * * * *
- * * * * * https://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.springdoc.core.customizers;
@@ -31,6 +33,7 @@
/**
* Implement and register a bean of type {@link ParameterCustomizer} to customize a parameter
* based on the parameter and handler method input
+ *
* @author bnasslahsen
*/
@FunctionalInterface
@@ -38,7 +41,7 @@ public interface ParameterCustomizer {
/**
* Customize parameter.
*
- * @param parameterModel to be customized
+ * @param parameterModel to be customized
* @param methodParameter original parameter from handler method
* @return customized parameter
*/
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/ParameterObjectNamingStrategyCustomizer.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/ParameterObjectNamingStrategyCustomizer.java
new file mode 100644
index 000000000..5a7875474
--- /dev/null
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/ParameterObjectNamingStrategyCustomizer.java
@@ -0,0 +1,70 @@
+/*
+ *
+ * *
+ * * *
+ * * * *
+ * * * * *
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.springdoc.core.customizers;
+
+import java.lang.reflect.Field;
+
+import com.fasterxml.jackson.databind.PropertyNamingStrategies;
+import com.fasterxml.jackson.databind.annotation.JsonNaming;
+import org.apache.commons.lang3.reflect.FieldUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.springframework.core.MethodParameter;
+import org.springframework.core.annotation.AnnotatedElementUtils;
+
+/**
+ * The type Parameter object naming strategy customizer.
+ *
+ * @author bnasslahsen
+ */
+public class ParameterObjectNamingStrategyCustomizer implements DelegatingMethodParameterCustomizer {
+
+ /**
+ * The constant LOGGER.
+ */
+ private static final Logger LOGGER = LoggerFactory.getLogger(ParameterObjectNamingStrategyCustomizer.class);
+
+ @Override
+ public void customize(MethodParameter originalParameter, MethodParameter methodParameter) {
+ if (AnnotatedElementUtils.isAnnotated(methodParameter.getContainingClass(), JsonNaming.class)) {
+ JsonNaming jsonNaming = methodParameter.getContainingClass().getAnnotation(JsonNaming.class);
+ if (jsonNaming.value().equals(PropertyNamingStrategies.UpperSnakeCaseStrategy.class)) {
+ try {
+ Field parameterNameField = FieldUtils.getDeclaredField(methodParameter.getClass(), "parameterName",
+ true);
+ parameterNameField.set(methodParameter,
+ PropertyNamingStrategies.UpperSnakeCaseStrategy.INSTANCE.translate(
+ methodParameter.getParameterName()));
+ }
+ catch (IllegalAccessException e) {
+ LOGGER.warn(e.getMessage());
+ }
+ }
+ }
+ }
+}
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/PropertyCustomizer.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/PropertyCustomizer.java
index 447958c3e..9f500c4d7 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/PropertyCustomizer.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/PropertyCustomizer.java
@@ -3,23 +3,25 @@
* *
* * *
* * * *
- * * * * * Copyright 2019-2022 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
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
* * * * *
- * * * * * https://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.springdoc.core.customizers;
@@ -30,6 +32,7 @@
/**
* Implement and register a bean of type {@link PropertyCustomizer} to customize a schema property
* based on annotated type
+ *
* @author bnasslahsen
*/
@FunctionalInterface
@@ -39,7 +42,7 @@ public interface PropertyCustomizer {
* Customize schema.
*
* @param property to be customized
- * @param type form the model class
+ * @param type form the model class
* @return customized property
*/
Schema customize(Schema property, AnnotatedType type);
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/QuerydslPredicateOperationCustomizer.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/QuerydslPredicateOperationCustomizer.java
index bbd45e5d3..dd6fc4e4d 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/QuerydslPredicateOperationCustomizer.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/QuerydslPredicateOperationCustomizer.java
@@ -3,23 +3,25 @@
* *
* * *
* * * *
- * * * * * Copyright 2019-2022 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
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
* * * * *
- * * * * * https://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.springdoc.core.customizers;
@@ -62,6 +64,7 @@
/**
* The type Querydsl predicate operation customizer.
+ *
* @author Gibah Joseph Email: gibahjoe@gmail.com Mar, 2020
*/
@SuppressWarnings("unchecked")
@@ -149,17 +152,14 @@ public Operation customize(Operation operation, HandlerMethod handlerMethod) {
/**
* Gets field value of boolean.
*
- * @param instance the instance
- * @param fieldName the field name
+ * @param instance the instance
+ * @param fieldName the field name
* @return the field value of boolean
*/
private boolean getFieldValueOfBoolean(QuerydslBindings instance, String fieldName) {
try {
- Field field = FieldUtils.getDeclaredField(instance.getClass(), fieldName, true);
- if (field != null)
- return (boolean) field.get(instance);
- }
- catch (IllegalAccessException e) {
+ return (boolean) FieldUtils.readDeclaredField(instance, fieldName, true);
+ } catch (IllegalAccessException e) {
LOGGER.warn(e.getMessage());
}
return false;
@@ -168,7 +168,7 @@ private boolean getFieldValueOfBoolean(QuerydslBindings instance, String fieldNa
/**
* Extract qdsl bindings querydsl bindings.
*
- * @param predicate the predicate
+ * @param predicate the predicate
* @return the querydsl bindings
*/
private QuerydslBindings extractQdslBindings(QuerydslPredicate predicate) {
@@ -187,9 +187,9 @@ private QuerydslBindings extractQdslBindings(QuerydslPredicate predicate) {
/**
* Gets field values.
*
- * @param instance the instance
- * @param fieldName the field name
- * @param alternativeFieldName the alternative field name
+ * @param instance the instance
+ * @param fieldName the field name
+ * @param alternativeFieldName the alternative field name
* @return the field values
*/
private Set getFieldValues(QuerydslBindings instance, String fieldName, String alternativeFieldName) {
@@ -209,14 +209,13 @@ private Set getFieldValues(QuerydslBindings instance, String fieldName,
/**
* Gets path spec.
*
- * @param instance the instance
- * @param fieldName the field name
+ * @param instance the instance
+ * @param fieldName the field name
* @return the path spec
*/
private Map getPathSpec(QuerydslBindings instance, String fieldName) {
try {
- Field field = FieldUtils.getDeclaredField(instance.getClass(), fieldName, true);
- return (Map) field.get(instance);
+ return (Map) FieldUtils.readDeclaredField(instance, fieldName, true);
}
catch (IllegalAccessException e) {
LOGGER.warn(e.getMessage());
@@ -227,7 +226,7 @@ private Map getPathSpec(QuerydslBindings instance, String fieldN
/**
* Gets path from path spec.
*
- * @param instance the instance
+ * @param instance the instance
* @return the path from path spec
*/
private Optional> getPathFromPathSpec(Object instance) {
@@ -235,8 +234,7 @@ private Optional> getPathFromPathSpec(Object instance) {
if (instance == null) {
return Optional.empty();
}
- Field field = FieldUtils.getDeclaredField(instance.getClass(), "path", true);
- return (Optional>) field.get(instance);
+ return (Optional>) FieldUtils.readDeclaredField(instance, "path", true);
}
catch (IllegalAccessException e) {
LOGGER.warn(e.getMessage());
@@ -246,9 +244,9 @@ private Optional> getPathFromPathSpec(Object instance) {
/***
* Tries to figure out the Type of the field. It first checks the Qdsl pathSpecMap before checking the root class. Defaults to String.class
- * @param fieldName The name of the field used as reference to get the type
- * @param pathSpecMap The Qdsl path specifications as defined in the resolved bindings
- * @param root The root type where the paths are gotten
+ * @param fieldName The name of the field used as reference to get the type
+ * @param pathSpecMap The Qdsl path specifications as defined in the resolved bindings
+ * @param root The root type where the paths are gotten
* @return The type of the field. Returns
*/
private Type getFieldType(String fieldName, Map pathSpecMap, Class> root) {
@@ -273,8 +271,8 @@ private Type getFieldType(String fieldName, Map pathSpecMap, Cla
/***
* Constructs the parameter
- * @param type The type of the parameter
- * @param name The name of the parameter
+ * @param type The type of the parameter
+ * @param name The name of the parameter
* @return The swagger parameter
*/
private Parameter buildParam(Type type, String name) {
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/RouterOperationCustomizer.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/RouterOperationCustomizer.java
index 2bf93dc60..42b98a7f5 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/RouterOperationCustomizer.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/RouterOperationCustomizer.java
@@ -1,3 +1,29 @@
+/*
+ *
+ * *
+ * * *
+ * * * *
+ * * * * *
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.springdoc.core.customizers;
import org.springdoc.core.fn.RouterOperation;
@@ -17,7 +43,7 @@ public interface RouterOperationCustomizer {
* Customize router operation.
*
* @param routerOperation input operation
- * @param handlerMethod original handler method
+ * @param handlerMethod original handler method
* @return customized router operation
*/
RouterOperation customize(RouterOperation routerOperation, HandlerMethod handlerMethod);
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/ServerBaseUrlCustomizer.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/ServerBaseUrlCustomizer.java
index b209ba72e..985a4ffba 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/ServerBaseUrlCustomizer.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/ServerBaseUrlCustomizer.java
@@ -3,29 +3,34 @@
* *
* * *
* * * *
- * * * * * Copyright 2019-2022 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
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
* * * * *
- * * * * * https://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.springdoc.core.customizers;
+import org.springframework.http.HttpRequest;
+
/**
* The interface Server Base URL customiser.
+ *
* @author skylar -stark
*/
@FunctionalInterface
@@ -35,7 +40,8 @@ public interface ServerBaseUrlCustomizer {
* Customise.
*
* @param serverBaseUrl the serverBaseUrl.
+ * @param request the request.
* @return the customised serverBaseUrl
*/
- String customize(String serverBaseUrl);
+ String customize(String serverBaseUrl, HttpRequest request);
}
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/SpecPropertiesCustomizer.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/SpecPropertiesCustomizer.java
index f87f36eca..98ed3883c 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/SpecPropertiesCustomizer.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/SpecPropertiesCustomizer.java
@@ -3,23 +3,25 @@
* *
* * *
* * * *
- * * * * * Copyright 2019-2022 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
+ * * * * * * Copyright 2019-2025 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
+ * * * * * *
+ * * * * * * https://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.
* * * * *
- * * * * * https://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.springdoc.core.customizers;
@@ -39,6 +41,11 @@
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
import io.swagger.v3.oas.models.media.Schema;
+import io.swagger.v3.oas.models.security.OAuthFlows;
+import io.swagger.v3.oas.models.security.SecurityRequirement;
+import io.swagger.v3.oas.models.security.SecurityScheme;
+import io.swagger.v3.oas.models.security.SecurityScheme.In;
+import io.swagger.v3.oas.models.security.SecurityScheme.Type;
import org.apache.commons.lang3.StringUtils;
import org.springdoc.core.properties.SpringDocConfigProperties;
@@ -132,6 +139,31 @@ private void customizeOpenApi(OpenAPI openApi, OpenAPI openApiProperties) {
Paths pathsProperties = openApiProperties.getPaths();
if (pathsProperties != null)
customizePaths(openApi, pathsProperties);
+
+ List securityRequirementsProperties = openApiProperties.getSecurity();
+ if (!CollectionUtils.isEmpty(securityRequirementsProperties)) {
+ customizeSecurity(openApi, securityRequirementsProperties);
+ }
+ }
+ }
+
+ /**
+ * Customize security.
+ *
+ * @param openApi the open api
+ * @param securityRequirementsProperties the security requirements
+ */
+ private void customizeSecurity(OpenAPI openApi, List securityRequirementsProperties) {
+ List securityRequirements = openApi.getSecurity();
+ if (CollectionUtils.isEmpty(securityRequirements)) {
+ openApi.setSecurity(securityRequirementsProperties);
+ }
+ else {
+ securityRequirementsProperties.forEach(securityRequirement -> {
+ if (!securityRequirements.contains(securityRequirement)) {
+ securityRequirements.add(securityRequirement);
+ }
+ });
}
}
@@ -202,6 +234,28 @@ private void customizeComponents(OpenAPI openApi, Components componentsPropertie
});
}
});
+
+
+ Map securitySchemeMap = components.getSecuritySchemes();
+ if (CollectionUtils.isEmpty(securitySchemeMap)) {
+ components.setSecuritySchemes(componentsProperties.getSecuritySchemes());
+ }
+ else {
+ securitySchemeMap.forEach((key, securityScheme) -> {
+ SecurityScheme securitySchemeToCustomize = components.getSecuritySchemes().get(key);
+ if (securitySchemeToCustomize != null) {
+ resolveString(securitySchemeToCustomize::description, securityScheme::getDescription);
+ resolveString(securitySchemeToCustomize::name, securityScheme::getName);
+ resolveType(securitySchemeToCustomize::type, securityScheme::getType);
+ resolveIn(securitySchemeToCustomize::in, securityScheme::getIn);
+ resolveString(securitySchemeToCustomize::scheme, securityScheme::getScheme);
+ resolveString(securitySchemeToCustomize::bearerFormat, securityScheme::getBearerFormat);
+ resolveString(securitySchemeToCustomize::openIdConnectUrl, securityScheme::getOpenIdConnectUrl);
+ resolveOAuthFlows(securitySchemeToCustomize::flows, securityScheme::getFlows);
+ resolveString(securitySchemeToCustomize::$ref, securityScheme::get$ref);
+ }
+ });
+ }
}
}
@@ -257,6 +311,46 @@ private void resolveString(Consumer setter, Supplier