diff --git a/CHANGELOG.md b/CHANGELOG.md index 41ba6e3c9..81c356a35 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,24 @@ 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.8.5] - 2025-02-16 + +### Added +- #2696 - Do not require JsonSubType annotation for sealed classes +- #2898 - add needed runtime reflection hints for native image +- #2891 - Refactor trimIndent Method + +### Changed +- Upgrade swagger-ui to v5.18.3 + +### Fixed +- #2902 - Schema replaced by String when using @ApiResponse with RepresentationModel (Hateoas links) +- #2876 - Restentpoints with same name get mix up +- #2895 - Only filter out actuator endpoints with double asterisks. +- #2894 - respect @JsonUnwrapped & @Schema on props not fields only +- #2881 - fix defaultValue when using @PageableDefault together with one-indexed-parameters +- #2888 - Provide a better consistency for parameters and responses order. + ## [2.8.4] - 2025-01-25 ### Added diff --git a/README.md b/README.md index 180f3d560..5b3618093 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,9 @@ This project is sponsored by + + +

# Table of Contents diff --git a/pom.xml b/pom.xml index 5f72a3e70..dcda74974 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 org.springdoc springdoc-openapi - 2.8.4 + 2.8.5 pom Spring openapi documentation Spring openapi documentation @@ -35,7 +35,7 @@ scm:git:git@github.com:springdoc/springdoc-openapi.git scm:git:git@github.com:springdoc/springdoc-openapi.git - v2.8.4 + v2.8.5 @@ -61,7 +61,7 @@ 2.5.3 1.6.8 2.2.28 - 5.18.2 + 5.18.3 1.13.1 0.9.1 0.15.0 diff --git a/springdoc-openapi-starter-common/pom.xml b/springdoc-openapi-starter-common/pom.xml index b3bdef137..93483b2ac 100644 --- a/springdoc-openapi-starter-common/pom.xml +++ b/springdoc-openapi-starter-common/pom.xml @@ -3,7 +3,7 @@ org.springdoc springdoc-openapi - 2.8.4 + 2.8.5 springdoc-openapi-starter-common 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 7c97a5e4c..948a0e667 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 @@ -661,8 +661,7 @@ protected void calculatePath(HandlerMethod handlerMethod, RouterOperation router } PathItem pathItemObject = buildPathItem(requestMethod, operation, operationPath, paths); - if (!StringUtils.contains(operationPath, "**")) - paths.addPathItem(operationPath, pathItemObject); + paths.addPathItem(operationPath, pathItemObject); } } 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 4c39763c9..58c7ad34d 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 @@ -126,6 +126,7 @@ import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.web.context.request.async.DeferredResult; +import static org.springdoc.core.utils.Constants.GLOBAL_OPEN_API_CUSTOMIZER; import static org.springdoc.core.utils.Constants.SPRINGDOC_DEPRECATING_CONVERTER_ENABLED; import static org.springdoc.core.utils.Constants.SPRINGDOC_ENABLED; import static org.springdoc.core.utils.Constants.SPRINGDOC_POLYMORPHIC_CONVERTER_ENABLED; @@ -423,7 +424,7 @@ SpringDocProviders springDocProviders(Optional actuatorProvide Optional repositoryRestResourceProvider, Optional routerFunctionProvider, Optional springWebProvider, ObjectMapperProvider objectMapperProvider) { - objectMapperProvider.jsonMapper().registerModule(new SpringDocRequiredModule()); + objectMapperProvider.jsonMapper().registerModules(new SpringDocRequiredModule(), new SpringDocSealedClassModule()); return new SpringDocProviders(actuatorProvider, springCloudFunctionProvider, springSecurityOAuth2Provider, repositoryRestResourceProvider, routerFunctionProvider, springWebProvider, objectMapperProvider); } @@ -654,7 +655,7 @@ ParameterObjectNamingStrategyCustomizer parameterObjectNamingStrategyCustomizer( * @return the global open api customizer */ @Bean - @ConditionalOnMissingBean + @ConditionalOnMissingBean(name = GLOBAL_OPEN_API_CUSTOMIZER) @Lazy(false) GlobalOpenApiCustomizer globalOpenApiCustomizer() { return new OperationIdCustomizer(); 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 5c35852ba..17fb5c28a 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 @@ -101,8 +101,8 @@ CollectionModelContentConverter collectionModelContentConverter(HateoasHalProvid * @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)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) + @Bean(Constants.LINKS_SCHEMA_CUSTOMIZER) + @ConditionalOnMissingBean(name = Constants.LINKS_SCHEMA_CUSTOMIZER) @Lazy(false) GlobalOpenApiCustomizer linksSchemaCustomizer(HateoasHalProvider halProvider, SpringDocConfigProperties springDocConfigProperties) { if (!halProvider.isHalEnabled()) { diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocSealedClassModule.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocSealedClassModule.java new file mode 100644 index 000000000..d0b27ad81 --- /dev/null +++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocSealedClassModule.java @@ -0,0 +1,68 @@ +/* + * + * * + * * * + * * * * Copyright 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.ArrayList; +import java.util.Arrays; +import java.util.List; + +import com.fasterxml.jackson.databind.introspect.Annotated; +import com.fasterxml.jackson.databind.jsontype.NamedType; +import com.fasterxml.jackson.databind.module.SimpleModule; +import io.swagger.v3.core.jackson.SwaggerAnnotationIntrospector; + +/** + * The type Spring doc sealed class module. + * + * @author sahil-ramagiri + */ +public class SpringDocSealedClassModule extends SimpleModule { + + @Override + public void setupModule(SetupContext context) { + context.insertAnnotationIntrospector(new RespectSealedClassAnnotationIntrospector()); + } + + /** + * The type sealed class annotation introspector. + */ + private static class RespectSealedClassAnnotationIntrospector extends SwaggerAnnotationIntrospector { + + @Override + public List findSubtypes(Annotated annotated) { + ArrayList subTypes = new ArrayList<>(); + + if (annotated.getAnnotated() instanceof Class clazz + && clazz.isSealed() + && !clazz.getPackage().getName().startsWith("java") + ) { + Class[] permittedSubClasses = clazz.getPermittedSubclasses(); + if (permittedSubClasses.length > 0) { + Arrays.stream(permittedSubClasses).map(NamedType::new).forEach(subTypes::add); + } + } + + return subTypes; + } + } +} \ No newline at end of file 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 37e457135..dad4e1b11 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 @@ -113,6 +113,7 @@ public class SpringDocHints implements RuntimeHintsRegistrar { io.swagger.v3.oas.models.media.Schema.class, io.swagger.v3.oas.models.media.Content.class, io.swagger.v3.oas.models.media.ArraySchema.class, + io.swagger.v3.oas.models.media.JsonSchema.class, io.swagger.v3.oas.models.responses.ApiResponse.class, io.swagger.v3.oas.models.responses.ApiResponses.class, io.swagger.v3.oas.models.ExternalDocumentation.class, @@ -122,6 +123,7 @@ public class SpringDocHints implements RuntimeHintsRegistrar { io.swagger.v3.oas.models.Operation.class, io.swagger.v3.oas.models.headers.Header.class, ModelConverter.class, + io.swagger.v3.core.converter.ModelConverterContextImpl.class, ModelConverters.class, SpecFilter.class, MediaType.class, @@ -166,6 +168,7 @@ public class SpringDocHints implements RuntimeHintsRegistrar { MediaTypeMixin.class, //oas 3.1 Schema31Mixin.class, + Schema31Mixin.TypeSerializer.class, Components31Mixin.class, OpenAPI31Mixin.class, Discriminator31Mixin.class, 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 index 7fbfa420b..bcde9140c 100644 --- 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 @@ -28,6 +28,7 @@ import java.util.Iterator; +import java.util.Optional; import com.fasterxml.jackson.databind.JavaType; import io.swagger.v3.core.converter.ModelConverter; @@ -43,7 +44,7 @@ /** * The type Hateoas links converter. - * + * * @author bnasslahsen */ public class HateoasLinksConverter implements ModelConverter { @@ -70,19 +71,30 @@ public Schema resolve( ) { 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"); + Schema schema = chain.next().resolve(type, context, chain); + if (schema != null) { + String schemaName = Optional.ofNullable(schema.get$ref()) + .filter(ref -> ref.startsWith(Components.COMPONENTS_SCHEMAS_REF)) + .map(ref -> ref.substring(Components.COMPONENTS_SCHEMAS_REF.length())) + .orElse(schema.getName()); + if(schemaName != null) { + Schema original = context.getDefinedModels().get(schemaName); + if (original == null || original.getProperties() == null) { + return schema; + } + 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 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/PolymorphicModelConverter.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/PolymorphicModelConverter.java index 8cdbd65a6..9a940d349 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 @@ -37,7 +37,9 @@ import java.util.Set; import com.fasterxml.jackson.annotation.JsonUnwrapped; +import com.fasterxml.jackson.databind.BeanDescription; import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverter; import io.swagger.v3.core.converter.ModelConverterContext; @@ -120,17 +122,28 @@ 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)) { + BeanDescription javaTypeIntrospection = springDocObjectMapper.jsonMapper().getDeserializationConfig().introspect(javaType); + for (BeanPropertyDefinition property : javaTypeIntrospection.findProperties()) { + boolean isUnwrapped = (property.getField() != null && property.getField().hasAnnotation(JsonUnwrapped.class)) || + (property.getGetter() != null && property.getGetter().hasAnnotation(JsonUnwrapped.class)); + + if (isUnwrapped) { 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()); + else { + io.swagger.v3.oas.annotations.media.Schema declaredSchema = null; + if (property.getField() != null) { + declaredSchema = property.getField().getAnnotation(io.swagger.v3.oas.annotations.media.Schema.class); + } else if (property.getGetter() != null) { + declaredSchema = property.getGetter().getAnnotation(io.swagger.v3.oas.annotations.media.Schema.class); + } + + if (declaredSchema != null && + (ArrayUtils.isNotEmpty(declaredSchema.oneOf()) || ArrayUtils.isNotEmpty(declaredSchema.allOf()))) { + TYPES_TO_SKIP.add(property.getPrimaryType().getRawClass().getSimpleName()); } } } 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 8a8ef92dc..1db18a182 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 @@ -64,6 +64,9 @@ /** * The type Data rest delegating method parameter customizer. + * + * @author bnasslahsen + * @author pheyken */ public class DataRestDelegatingMethodParameterCustomizer implements DelegatingMethodParameterCustomizer { @@ -1131,8 +1134,13 @@ else if (isSpringDataWebPropertiesPresent()) defaultValue = defaultSchemaVal; break; case "page": - if (pageableDefault != null) - defaultValue = String.valueOf(pageableDefault.page()); + if (pageableDefault != null) { + if (isSpringDataWebPropertiesPresent() && optionalSpringDataWebPropertiesProvider.get().getSpringDataWebProperties().getPageable().isOneIndexedParameters()) { + defaultValue = String.valueOf(pageableDefault.page() + 1); + } else { + defaultValue = String.valueOf(pageableDefault.page()); + } + } else if (isSpringDataWebPropertiesPresent() && optionalSpringDataWebPropertiesProvider.get().getSpringDataWebProperties().getPageable().isOneIndexedParameters()) defaultValue = "1"; else 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 dd6fc4e4d..7f86ea597 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 @@ -32,6 +32,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Optional; @@ -112,7 +113,7 @@ public Operation customize(Operation operation, HandlerMethod handlerMethod) { QuerydslBindings bindings = extractQdslBindings(predicate); - Set fieldsToAdd = Arrays.stream(predicate.root().getDeclaredFields()).filter(field -> !Modifier.isStatic(field.getModifiers())).map(Field::getName).collect(Collectors.toSet()); + Set fieldsToAdd = Arrays.stream(predicate.root().getDeclaredFields()).filter(field -> !Modifier.isStatic(field.getModifiers())).map(Field::getName).collect(Collectors.toCollection(LinkedHashSet::new)); Map pathSpecMap = getPathSpec(bindings, "pathSpecs"); //remove blacklisted fields diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/SpringDocCustomizers.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/SpringDocCustomizers.java index 577cf39ed..8acc651c7 100644 --- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/SpringDocCustomizers.java +++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/SpringDocCustomizers.java @@ -39,7 +39,7 @@ import org.springframework.context.ApplicationContextAware; import org.springframework.util.CollectionUtils; -import static org.springdoc.core.utils.Constants.LINKS_SCHEMA_CUSTOMISER; +import static org.springdoc.core.utils.Constants.LINKS_SCHEMA_CUSTOMIZER; /** * The type Spring doc customizers. @@ -223,7 +223,7 @@ public Optional> getGlobalOpenApiMethodFilters() public void afterPropertiesSet() { //add the default customizers Map existingOpenApiCustomizers = context.getBeansOfType(OpenApiCustomizer.class); - if (!CollectionUtils.isEmpty(existingOpenApiCustomizers) && existingOpenApiCustomizers.containsKey(LINKS_SCHEMA_CUSTOMISER)) - this.openApiCustomizers.ifPresent(openApiCustomizersList -> openApiCustomizersList.add(existingOpenApiCustomizers.get(LINKS_SCHEMA_CUSTOMISER))); + if (!CollectionUtils.isEmpty(existingOpenApiCustomizers) && existingOpenApiCustomizers.containsKey(LINKS_SCHEMA_CUSTOMIZER)) + this.openApiCustomizers.ifPresent(openApiCustomizersList -> openApiCustomizersList.add(existingOpenApiCustomizers.get(LINKS_SCHEMA_CUSTOMIZER))); } } diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/data/DataRestRouterOperationService.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/data/DataRestRouterOperationService.java index bd640ad95..41660655b 100644 --- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/data/DataRestRouterOperationService.java +++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/data/DataRestRouterOperationService.java @@ -28,6 +28,7 @@ import java.util.Arrays; import java.util.LinkedHashMap; +import java.util.LinkedHashSet; import java.util.List; import java.util.Locale; import java.util.Map; @@ -178,7 +179,7 @@ private void buildRouterOperationList(List routerOperationList, if (andCheck(resourceMetadata != null, !controllerType.equals(ControllerType.SEARCH))) { HttpMethods httpMethodsItem = resourceMetadata.getSupportedHttpMethods().getMethodsFor(ResourceType.ITEM); requestMethodsItem = requestMethods.stream().filter(requestMethod -> httpMethodsItem.contains(HttpMethod.valueOf(requestMethod.toString()))) - .collect(Collectors.toSet()); + .collect(Collectors.toCollection(LinkedHashSet::new)); buildRouterOperation(routerOperationList, resourceMetadata, dataRestRepository, openAPI, path, subPath, controllerType, methodResourceMapping, requestMappingInfo, handlerMethod, requestMethodsItem, ResourceType.ITEM); @@ -186,7 +187,7 @@ private void buildRouterOperationList(List routerOperationList, if (!ControllerType.PROPERTY.equals(controllerType)) { HttpMethods httpMethodsCollection = resourceMetadata.getSupportedHttpMethods().getMethodsFor(ResourceType.COLLECTION); requestMethodsCollection = requestMethods.stream().filter(requestMethod -> httpMethodsCollection.contains(HttpMethod.valueOf(requestMethod.toString()))) - .collect(Collectors.toSet()); + .collect(Collectors.toCollection(LinkedHashSet::new)); buildRouterOperation(routerOperationList, resourceMetadata, dataRestRepository, openAPI, path, subPath, controllerType, methodResourceMapping, requestMappingInfo, handlerMethod, requestMethodsCollection, ResourceType.COLLECTION); diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/extractor/MethodParameterPojoExtractor.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/extractor/MethodParameterPojoExtractor.java index 1d51a5b4e..643c2d9fd 100644 --- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/extractor/MethodParameterPojoExtractor.java +++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/extractor/MethodParameterPojoExtractor.java @@ -40,6 +40,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Objects; @@ -361,7 +362,7 @@ private static boolean isNullable(Annotation[] fieldAnnotations) { Collection annotationSimpleNames = Arrays.stream(fieldAnnotations) .map(Annotation::annotationType) .map(Class::getSimpleName) - .collect(Collectors.toSet()); + .collect(Collectors.toCollection(LinkedHashSet::new)); return !hasNotNullAnnotation(annotationSimpleNames); } } diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/properties/SwaggerUiConfigProperties.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/properties/SwaggerUiConfigProperties.java index b2e21e843..d4158bcc3 100644 --- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/properties/SwaggerUiConfigProperties.java +++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/properties/SwaggerUiConfigProperties.java @@ -27,6 +27,7 @@ package org.springdoc.core.properties; import java.io.IOException; +import java.util.LinkedHashSet; import java.util.Properties; import java.util.Set; import java.util.stream.Collectors; @@ -239,7 +240,7 @@ public void setSyntaxHighlight(SyntaxHighlight syntaxHighlight) { * @return the set */ public Set cloneUrls() { - return this.urls.stream().map(swaggerUrl -> new SwaggerUrl(swaggerUrl.getName(), swaggerUrl.getUrl(), swaggerUrl.getDisplayName())).collect(Collectors.toSet()); + return this.urls.stream().map(swaggerUrl -> new SwaggerUrl(swaggerUrl.getName(), swaggerUrl.getUrl(), swaggerUrl.getDisplayName())).collect(Collectors.toCollection(LinkedHashSet::new)); } /** diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/service/GenericResponseService.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/service/GenericResponseService.java index ea41fee6f..f26f4a90b 100644 --- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/service/GenericResponseService.java +++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/service/GenericResponseService.java @@ -36,6 +36,7 @@ import java.util.Collection; import java.util.HashSet; import java.util.LinkedHashMap; +import java.util.LinkedHashSet; import java.util.List; import java.util.Locale; import java.util.Map; @@ -489,12 +490,12 @@ public Set getApiResponses( Set apiResponsesDoc = AnnotatedElementUtils .findAllMergedAnnotations(method, io.swagger.v3.oas.annotations.responses.ApiResponses.class); Set responses = apiResponsesDoc.stream() - .flatMap(x -> Stream.of(x.value())).collect(Collectors.toSet()); + .flatMap(x -> Stream.of(x.value())).collect(Collectors.toCollection(LinkedHashSet::new)); Set apiResponsesDocDeclaringClass = AnnotatedElementUtils .findAllMergedAnnotations(declaringClass, io.swagger.v3.oas.annotations.responses.ApiResponses.class); responses.addAll( - apiResponsesDocDeclaringClass.stream().flatMap(x -> Stream.of(x.value())).collect(Collectors.toSet())); + apiResponsesDocDeclaringClass.stream().flatMap(x -> Stream.of(x.value())).collect(Collectors.toCollection(LinkedHashSet::new))); Set apiResponseDoc = AnnotatedElementUtils .findMergedRepeatableAnnotations(method, io.swagger.v3.oas.annotations.responses.ApiResponse.class); diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/service/OpenAPIService.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/service/OpenAPIService.java index 596e61395..1d382c7db 100644 --- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/service/OpenAPIService.java +++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/service/OpenAPIService.java @@ -33,6 +33,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; +import java.util.LinkedHashSet; import java.util.List; import java.util.Locale; import java.util.Map; @@ -336,7 +337,7 @@ public Operation buildTags(HandlerMethod handlerMethod, Operation operation, Ope if (!CollectionUtils.isEmpty(tagsStr)) tagsStr = tagsStr.stream() .map(str -> propertyResolverUtils.resolve(str, locale)) - .collect(Collectors.toSet()); + .collect(Collectors.toCollection(LinkedHashSet::new)); if (springdocTags.containsKey(handlerMethod)) { io.swagger.v3.oas.models.tags.Tag tag = springdocTags.get(handlerMethod); @@ -407,10 +408,10 @@ private void buildTagsFromMethod(Method method, Set tagsSet = AnnotatedElementUtils .findAllMergedAnnotations(method, Tags.class); Set methodTags = tagsSet.stream() - .flatMap(x -> Stream.of(x.value())).collect(Collectors.toSet()); + .flatMap(x -> Stream.of(x.value())).collect(Collectors.toCollection(LinkedHashSet::new)); methodTags.addAll(AnnotatedElementUtils.findAllMergedAnnotations(method, Tag.class)); if (!CollectionUtils.isEmpty(methodTags)) { - tagsStr.addAll(methodTags.stream().map(tag -> propertyResolverUtils.resolve(tag.name(), locale)).collect(Collectors.toSet())); + tagsStr.addAll(methodTags.stream().map(tag -> propertyResolverUtils.resolve(tag.name(), locale)).collect(Collectors.toCollection(LinkedHashSet::new))); List allTags = new ArrayList<>(methodTags); addTags(allTags, tags, locale); } @@ -450,10 +451,10 @@ public void buildTagsFromClass(Class beanType, Set tagsSet = AnnotatedElementUtils .findAllMergedAnnotations(beanType, Tags.class); Set classTags = tagsSet.stream() - .flatMap(x -> Stream.of(x.value())).collect(Collectors.toSet()); + .flatMap(x -> Stream.of(x.value())).collect(Collectors.toCollection(LinkedHashSet::new)); classTags.addAll(AnnotatedElementUtils.findAllMergedAnnotations(beanType, Tag.class)); if (!CollectionUtils.isEmpty(classTags)) { - tagsStr.addAll(classTags.stream().map(tag -> propertyResolverUtils.resolve(tag.name(), locale)).collect(Collectors.toSet())); + tagsStr.addAll(classTags.stream().map(tag -> propertyResolverUtils.resolve(tag.name(), locale)).collect(Collectors.toCollection(LinkedHashSet::new))); allTags.addAll(classTags); addTags(allTags, tags, locale); } diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/utils/Constants.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/utils/Constants.java index 20f9124ab..9453a832d 100644 --- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/utils/Constants.java +++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/utils/Constants.java @@ -407,7 +407,12 @@ public final class Constants { /** * The constant LINKS_SCHEMA_CUSTOMISER. */ - public static final String LINKS_SCHEMA_CUSTOMISER = "linksSchemaCustomizer"; + public static final String LINKS_SCHEMA_CUSTOMIZER = "linksSchemaCustomizer"; + + /** + * The constant GLOBAL_OPEN_API_CUSTOMIZER. + */ + public static final String GLOBAL_OPEN_API_CUSTOMIZER = "globalOpenApiCustomizer"; /** * The constant SPRINGDOC_SORT_CONVERTER_ENABLED. diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/utils/PropertyResolverUtils.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/utils/PropertyResolverUtils.java index 3178f1f6f..a98d7a5e3 100644 --- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/utils/PropertyResolverUtils.java +++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/utils/PropertyResolverUtils.java @@ -32,7 +32,8 @@ import java.util.Map; import io.swagger.v3.oas.models.SpecVersion; -import org.apache.commons.lang3.StringUtils; +import java.util.stream.Collectors; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springdoc.core.properties.SpringDocConfigProperties; @@ -114,23 +115,24 @@ public String resolve(String parameterProperty, Locale locale) { * Returns a string where all leading indentation has been removed from each line. * It detects the smallest common indentation of all the lines in the input string, * and removes it. + * If the input text is {@code null}, the method returns {@code null}. * - * @param text The original string with possible leading indentation. - * @return The string with leading indentation removed from each line. + * @param text The original string with possible leading indentation. + * @return The string with the smallest common leading indentation removed from each line, + * or {@code null} if the input text is {@code null}. */ public String trimIndent(String text) { + if (text == null) { + return null; + } + final String newLine = "\n"; + String[] lines = text.split("\\r?\\n"); + int minIndent = resolveMinIndent(lines); try { - if (text == null) { - return null; - } - final String newLine = "\n"; - String[] lines = text.split(newLine); - int minIndent = resolveMinIndent(lines); return Arrays.stream(lines) - .map(line -> line.substring(Math.min(line.length(), minIndent))) - .reduce((a, b) -> a + newLine + b) - .orElse(StringUtils.EMPTY); - } catch (Exception ex){ + .map(line -> line.substring(Math.min(line.length(), minIndent))) + .collect(Collectors.joining(newLine)); + } catch (Exception ex) { LOGGER.warn(ex.getMessage()); return text; } @@ -239,4 +241,4 @@ public Map resolveExtensions(Locale locale, Map else return extensions; } -} \ No newline at end of file +} diff --git a/springdoc-openapi-starter-common/src/test/java/org/springdoc/core/configuration/SpringDocHateoasConfigurationTest.java b/springdoc-openapi-starter-common/src/test/java/org/springdoc/core/configuration/SpringDocHateoasConfigurationTest.java index 91e3029bb..35bd6c2f3 100644 --- a/springdoc-openapi-starter-common/src/test/java/org/springdoc/core/configuration/SpringDocHateoasConfigurationTest.java +++ b/springdoc-openapi-starter-common/src/test/java/org/springdoc/core/configuration/SpringDocHateoasConfigurationTest.java @@ -12,7 +12,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; -import static org.springdoc.core.utils.Constants.LINKS_SCHEMA_CUSTOMISER; +import static org.springdoc.core.utils.Constants.LINKS_SCHEMA_CUSTOMIZER; class SpringDocHateoasConfigurationTest { @@ -33,8 +33,8 @@ void linksSchemaCustomizerShouldBeRegistered() { .run(context -> { assertThat(context).getBeanNames(GlobalOpenApiCustomizer.class) .hasSize(2) - .contains(LINKS_SCHEMA_CUSTOMISER); - assertThat(context.getBean(LINKS_SCHEMA_CUSTOMISER)).isExactlyInstanceOf(OpenApiHateoasLinksCustomizer.class); + .contains(LINKS_SCHEMA_CUSTOMIZER); + assertThat(context.getBean(LINKS_SCHEMA_CUSTOMIZER)).isExactlyInstanceOf(OpenApiHateoasLinksCustomizer.class); }); } @@ -56,7 +56,7 @@ void linksSchemaCustomizerShouldBeRegisteredWithMultipleGlobalOpenApiCustomizer( .run(context -> { assertThat(context).getBeanNames(GlobalOpenApiCustomizer.class) .hasSize(2) - .containsExactlyInAnyOrder(LINKS_SCHEMA_CUSTOMISER, "globalOpenApiCustomizer"); + .containsExactlyInAnyOrder(LINKS_SCHEMA_CUSTOMIZER, "globalOpenApiCustomizer"); }); } @@ -74,12 +74,12 @@ void linksSchemaCustomizerShouldNotBeRegisteredIfBeanWithSameNameAlreadyExists() SpringDocConfigProperties.class, SpringDocHateoasConfiguration.class )) - .withBean(LINKS_SCHEMA_CUSTOMISER, GlobalOpenApiCustomizer.class, () -> mock(GlobalOpenApiCustomizer.class)) + .withBean(LINKS_SCHEMA_CUSTOMIZER, GlobalOpenApiCustomizer.class, () -> mock(GlobalOpenApiCustomizer.class)) .run(context -> { assertThat(context).getBeanNames(GlobalOpenApiCustomizer.class) - .hasSize(1) - .containsExactly(LINKS_SCHEMA_CUSTOMISER); - assertThat(context.getBean(LINKS_SCHEMA_CUSTOMISER)).isNotExactlyInstanceOf(OpenApiHateoasLinksCustomizer.class); + .hasSize(2) + .contains(LINKS_SCHEMA_CUSTOMIZER); + assertThat(context.getBean(LINKS_SCHEMA_CUSTOMIZER)).isNotExactlyInstanceOf(OpenApiHateoasLinksCustomizer.class); }); } } \ No newline at end of file diff --git a/springdoc-openapi-starter-webflux-api/pom.xml b/springdoc-openapi-starter-webflux-api/pom.xml index 4f18fd6b7..51ce89e9a 100644 --- a/springdoc-openapi-starter-webflux-api/pom.xml +++ b/springdoc-openapi-starter-webflux-api/pom.xml @@ -3,7 +3,7 @@ org.springdoc springdoc-openapi - 2.8.4 + 2.8.5 springdoc-openapi-starter-webflux-api diff --git a/springdoc-openapi-starter-webflux-api/src/main/java/org/springdoc/webflux/core/providers/SpringWebFluxProvider.java b/springdoc-openapi-starter-webflux-api/src/main/java/org/springdoc/webflux/core/providers/SpringWebFluxProvider.java index 2c2bd5bd1..2c5e92cd9 100644 --- a/springdoc-openapi-starter-webflux-api/src/main/java/org/springdoc/webflux/core/providers/SpringWebFluxProvider.java +++ b/springdoc-openapi-starter-webflux-api/src/main/java/org/springdoc/webflux/core/providers/SpringWebFluxProvider.java @@ -27,6 +27,7 @@ import java.util.Collection; import java.util.LinkedHashMap; +import java.util.LinkedHashSet; import java.util.Map; import java.util.Map.Entry; import java.util.Set; @@ -84,7 +85,7 @@ public Set getActivePatterns(Object requestMapping) { RequestMappingInfo requestMappingInfo = (RequestMappingInfo) requestMapping; PatternsRequestCondition patternsRequestCondition = requestMappingInfo.getPatternsCondition(); return patternsRequestCondition.getPatterns().stream() - .map(PathPattern::getPatternString).collect(Collectors.toSet()); + .map(PathPattern::getPatternString).collect(Collectors.toCollection(LinkedHashSet::new)); } diff --git a/springdoc-openapi-starter-webflux-ui/pom.xml b/springdoc-openapi-starter-webflux-ui/pom.xml index ac8dd0c40..76c31fc67 100644 --- a/springdoc-openapi-starter-webflux-ui/pom.xml +++ b/springdoc-openapi-starter-webflux-ui/pom.xml @@ -3,7 +3,7 @@ org.springdoc springdoc-openapi - 2.8.4 + 2.8.5 springdoc-openapi-starter-webflux-ui diff --git a/springdoc-openapi-starter-webmvc-api/pom.xml b/springdoc-openapi-starter-webmvc-api/pom.xml index 503d44926..8c868d9b2 100644 --- a/springdoc-openapi-starter-webmvc-api/pom.xml +++ b/springdoc-openapi-starter-webmvc-api/pom.xml @@ -3,7 +3,7 @@ org.springdoc springdoc-openapi - 2.8.4 + 2.8.5 springdoc-openapi-starter-webmvc-api diff --git a/springdoc-openapi-starter-webmvc-api/src/main/java/org/springdoc/webmvc/api/OpenApiResource.java b/springdoc-openapi-starter-webmvc-api/src/main/java/org/springdoc/webmvc/api/OpenApiResource.java index a1fcf1e16..c4557a5be 100644 --- a/springdoc-openapi-starter-webmvc-api/src/main/java/org/springdoc/webmvc/api/OpenApiResource.java +++ b/springdoc-openapi-starter-webmvc-api/src/main/java/org/springdoc/webmvc/api/OpenApiResource.java @@ -167,6 +167,11 @@ protected void getPaths(Map restControllers, Locale locale, Open Optional actuatorProviderOptional = springDocProviders.getActuatorProvider(); if (actuatorProviderOptional.isPresent() && springDocConfigProperties.isShowActuator()) { Map actuatorMap = actuatorProviderOptional.get().getMethods(); + List globMatchActuators = actuatorMap.keySet().stream() + .filter(requestMappingInfo -> requestMappingInfo.getPatternValues().stream() + .anyMatch(patternValues -> patternValues.contains("**"))) + .toList(); + globMatchActuators.forEach(actuatorMap::remove); this.openAPIService.addTag(new HashSet<>(actuatorMap.values()), getTag()); map.putAll(actuatorMap); } diff --git a/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app233/SpringDocApp233Test.java b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app233/SpringDocApp233Test.java index 4480482d1..582cc60ca 100644 --- a/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app233/SpringDocApp233Test.java +++ b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app233/SpringDocApp233Test.java @@ -27,6 +27,7 @@ package test.org.springdoc.api.v30.app233; import java.util.Collection; +import java.util.LinkedHashSet; import java.util.List; import java.util.Optional; import java.util.Set; @@ -167,7 +168,7 @@ private void verifySwaggerFieldRequirementsMatchJavaValidation(Collection field.getObjectName() + "." + field.getField()) - .collect(Collectors.toSet()); + .collect(Collectors.toCollection(LinkedHashSet::new)); assertThat(errorFields).containsExactlyElementsOf(expectedErrorFields); diff --git a/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app239/RootModel.java b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app239/RootModel.java new file mode 100644 index 000000000..cf2bd6039 --- /dev/null +++ b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app239/RootModel.java @@ -0,0 +1,27 @@ +package test.org.springdoc.api.v30.app239; + +import com.fasterxml.jackson.annotation.JsonUnwrapped; + +public class RootModel { + + private Integer rootProperty; + + private UnwrappedModel unwrappedModel; + + public Integer getRootProperty() { + return rootProperty; + } + + public void setRootProperty(Integer rootProperty) { + this.rootProperty = rootProperty; + } + + @JsonUnwrapped + public UnwrappedModel getUnwrappedModel() { + return unwrappedModel; + } + + public void setUnwrappedModel(UnwrappedModel unwrappedModel) { + this.unwrappedModel = unwrappedModel; + } +} diff --git a/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app239/SpringDocApp239Test.java b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app239/SpringDocApp239Test.java new file mode 100644 index 000000000..122f279a5 --- /dev/null +++ b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app239/SpringDocApp239Test.java @@ -0,0 +1,34 @@ +/* + * + * * + * * * + * * * * + * * * * * Copyright 2019-2024 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 test.org.springdoc.api.v30.app239; + +import org.springframework.boot.autoconfigure.SpringBootApplication; +import test.org.springdoc.api.v30.AbstractSpringDocV30Test; + +public class SpringDocApp239Test extends AbstractSpringDocV30Test { + + @SpringBootApplication + static class SpringDocTestApp {} +} diff --git a/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app239/TestController.java b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app239/TestController.java new file mode 100644 index 000000000..a3f084691 --- /dev/null +++ b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app239/TestController.java @@ -0,0 +1,15 @@ +package test.org.springdoc.api.v30.app239; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/api") +public class TestController { + + @GetMapping + public RootModel getRootModel() { + return new RootModel(); + } +} diff --git a/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app239/UnwrappedModel.java b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app239/UnwrappedModel.java new file mode 100644 index 000000000..9ac5c2a48 --- /dev/null +++ b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app239/UnwrappedModel.java @@ -0,0 +1,14 @@ +package test.org.springdoc.api.v30.app239; + +public class UnwrappedModel { + + private Integer unwrappedProperty; + + public Integer getUnwrappedProperty() { + return unwrappedProperty; + } + + public void setUnwrappedProperty(Integer unwrappedProperty) { + this.unwrappedProperty = unwrappedProperty; + } +} diff --git a/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app240/AbstractParent.java b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app240/AbstractParent.java new file mode 100644 index 000000000..63634eea2 --- /dev/null +++ b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app240/AbstractParent.java @@ -0,0 +1,66 @@ +/* + * + * * + * * * + * * * * + * * * * * Copyright 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 test.org.springdoc.api.v30.app240; + + +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import com.fasterxml.jackson.annotation.JsonTypeInfo.Id; + +@JsonTypeInfo(use = Id.NAME, property = "type") +public abstract sealed class AbstractParent { + private int id; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } +} + +final class ChildOfAbstract1 extends AbstractParent { + private String abstrachChild1Param; + + public String getAbstrachChild1Param() { + return abstrachChild1Param; + } + + public void setAbstrachChild1Param(String abstrachChild1Param) { + this.abstrachChild1Param = abstrachChild1Param; + } +} + +final class ChildOfAbstract2 extends AbstractParent { + private String abstractChild2Param; + + public String getAbstractChild2Param() { + return abstractChild2Param; + } + + public void setAbstractChild2Param(String abstractChild2Param) { + this.abstractChild2Param = abstractChild2Param; + } +} diff --git a/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app240/ConcreteParent.java b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app240/ConcreteParent.java new file mode 100644 index 000000000..b0064dc13 --- /dev/null +++ b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app240/ConcreteParent.java @@ -0,0 +1,66 @@ +/* + * + * * + * * * + * * * * + * * * * * Copyright 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 test.org.springdoc.api.v30.app240; + + +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import com.fasterxml.jackson.annotation.JsonTypeInfo.Id; + +@JsonTypeInfo(use = Id.NAME, property = "type") +public sealed class ConcreteParent { + private int id; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } +} + +final class ChildOfConcrete1 extends ConcreteParent { + private String concreteChild1Param; + + public String getConcreteChild1Param() { + return concreteChild1Param; + } + + public void setConcreteChild1Param(String concreteChild1Param) { + this.concreteChild1Param = concreteChild1Param; + } +} + +final class ChildOfConcrete2 extends ConcreteParent { + private String concreteChild2Param; + + public String getConcreteChild2Param() { + return concreteChild2Param; + } + + public void setConcreteChild2Param(String concreteChild2Param) { + this.concreteChild2Param = concreteChild2Param; + } +} diff --git a/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app240/Controller.java b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app240/Controller.java new file mode 100644 index 000000000..eb1ef7dd2 --- /dev/null +++ b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app240/Controller.java @@ -0,0 +1,68 @@ +/* + * + * * + * * * + * * * * + * * * * * Copyright 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 test.org.springdoc.api.v30.app240; + +import java.util.List; + +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("class-hierarchy") +public class Controller { + @PostMapping("abstract-parent") + public Response abstractParent(@RequestBody AbstractParent payload) { + return null; + } + + @PostMapping("concrete-parent") + public Response concreteParent(@RequestBody ConcreteParent payload) { + return null; + } +} + +class Response { + AbstractParent abstractParent; + + List concreteParents; + + public AbstractParent getAbstractParent() { + return abstractParent; + } + + public void setAbstractParent(AbstractParent abstractParent) { + this.abstractParent = abstractParent; + } + + public List getConcreteParents() { + return concreteParents; + } + + public void setConcreteParents(List concreteParents) { + this.concreteParents = concreteParents; + } +} diff --git a/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app240/SpringDocApp240Test.java b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app240/SpringDocApp240Test.java new file mode 100644 index 000000000..ff01415fb --- /dev/null +++ b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app240/SpringDocApp240Test.java @@ -0,0 +1,35 @@ +/* + * + * * + * * * + * * * * + * * * * * Copyright 2019-2024 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 test.org.springdoc.api.v30.app240; + +import test.org.springdoc.api.v30.AbstractSpringDocV30Test; + +import org.springframework.boot.autoconfigure.SpringBootApplication; + +public class SpringDocApp240Test extends AbstractSpringDocV30Test { + + @SpringBootApplication + static class SpringDocTestApp {} +} \ No newline at end of file diff --git a/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app241/HelloController.java b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app241/HelloController.java new file mode 100644 index 000000000..213093d74 --- /dev/null +++ b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app241/HelloController.java @@ -0,0 +1,77 @@ +/* + * + * * + * * * + * * * * + * * * * * + * * * * * * 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 test.org.springdoc.api.v30.app241; + + +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import io.swagger.v3.oas.annotations.media.Schema; + +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class HelloController { + + @PostMapping("/parent") + public void parentEndpoint(@RequestBody Superclass parent) { + + } + +} + +@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "@type") +sealed class Superclass permits IntermediateClass { + + public Superclass() {} +} + +@Schema(name = IntermediateClass.SCHEMA_NAME) +@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "@type") +sealed class IntermediateClass extends Superclass permits FirstChildClass, SecondChildClass { + + public static final String SCHEMA_NAME = "IntermediateClass"; +} + +@Schema(name = FirstChildClass.SCHEMA_NAME) +final class FirstChildClass extends IntermediateClass { + + public static final String SCHEMA_NAME = "Image"; +} + +@Schema(name = SecondChildClass.SCHEMA_NAME) +@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "@type") +sealed class SecondChildClass extends IntermediateClass { + + public static final String SCHEMA_NAME = "Mail"; +} + +@Schema(name = ThirdChildClass.SCHEMA_NAME) +final class ThirdChildClass extends SecondChildClass { + + public static final String SCHEMA_NAME = "Home"; +} diff --git a/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app241/SpringDocApp241Test.java b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app241/SpringDocApp241Test.java new file mode 100644 index 000000000..6798b5535 --- /dev/null +++ b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app241/SpringDocApp241Test.java @@ -0,0 +1,35 @@ +/* + * + * * + * * * + * * * * + * * * * * Copyright 2019-2024 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 test.org.springdoc.api.v30.app241; + +import test.org.springdoc.api.v30.AbstractSpringDocV30Test; + +import org.springframework.boot.autoconfigure.SpringBootApplication; + +public class SpringDocApp241Test extends AbstractSpringDocV30Test { + + @SpringBootApplication + static class SpringDocTestApp {} +} \ No newline at end of file diff --git a/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v31/app224/RootModel.java b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v31/app224/RootModel.java index 0df928bc6..8e4c9ce6a 100644 --- a/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v31/app224/RootModel.java +++ b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v31/app224/RootModel.java @@ -6,7 +6,6 @@ public class RootModel { private Integer rootProperty; - @JsonUnwrapped private UnwrappedModel unwrappedModel; public Integer getRootProperty() { @@ -17,6 +16,7 @@ public void setRootProperty(Integer rootProperty) { this.rootProperty = rootProperty; } + @JsonUnwrapped public UnwrappedModel getUnwrappedModel() { return unwrappedModel; } diff --git a/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v31/app233/SpringDocApp233Test.java b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v31/app233/SpringDocApp233Test.java index 1636f52a4..21ca8c25e 100644 --- a/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v31/app233/SpringDocApp233Test.java +++ b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v31/app233/SpringDocApp233Test.java @@ -27,6 +27,7 @@ package test.org.springdoc.api.v31.app233; import java.util.Collection; +import java.util.LinkedHashSet; import java.util.List; import java.util.Optional; import java.util.Set; @@ -167,7 +168,7 @@ private void verifySwaggerFieldRequirementsMatchJavaValidation(Collection field.getObjectName() + "." + field.getField()) - .collect(Collectors.toSet()); + .collect(Collectors.toCollection(LinkedHashSet::new)); assertThat(errorFields).containsExactlyElementsOf(expectedErrorFields); diff --git a/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v31/app239/RootModel.java b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v31/app239/RootModel.java new file mode 100644 index 000000000..ea8b4261f --- /dev/null +++ b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v31/app239/RootModel.java @@ -0,0 +1,27 @@ +package test.org.springdoc.api.v31.app239; + +import com.fasterxml.jackson.annotation.JsonUnwrapped; + +public class RootModel { + + private Integer rootProperty; + + @JsonUnwrapped + private UnwrappedModel unwrappedModel; + + public Integer getRootProperty() { + return rootProperty; + } + + public void setRootProperty(Integer rootProperty) { + this.rootProperty = rootProperty; + } + + public UnwrappedModel getUnwrappedModel() { + return unwrappedModel; + } + + public void setUnwrappedModel(UnwrappedModel unwrappedModel) { + this.unwrappedModel = unwrappedModel; + } +} diff --git a/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v31/app239/SpringDocApp239Test.java b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v31/app239/SpringDocApp239Test.java new file mode 100644 index 000000000..efa593ebc --- /dev/null +++ b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v31/app239/SpringDocApp239Test.java @@ -0,0 +1,34 @@ +/* + * + * * + * * * + * * * * + * * * * * Copyright 2019-2024 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 test.org.springdoc.api.v31.app239; + +import org.springframework.boot.autoconfigure.SpringBootApplication; +import test.org.springdoc.api.v31.AbstractSpringDocTest; + +public class SpringDocApp239Test extends AbstractSpringDocTest { + + @SpringBootApplication + static class SpringDocTestApp {} +} diff --git a/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v31/app239/TestController.java b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v31/app239/TestController.java new file mode 100644 index 000000000..623fbaefa --- /dev/null +++ b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v31/app239/TestController.java @@ -0,0 +1,15 @@ +package test.org.springdoc.api.v31.app239; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/api") +public class TestController { + + @GetMapping + public RootModel getRootModel() { + return new RootModel(); + } +} diff --git a/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v31/app239/UnwrappedModel.java b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v31/app239/UnwrappedModel.java new file mode 100644 index 000000000..ab4776f64 --- /dev/null +++ b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v31/app239/UnwrappedModel.java @@ -0,0 +1,14 @@ +package test.org.springdoc.api.v31.app239; + +public class UnwrappedModel { + + private Integer unwrappedProperty; + + public Integer getUnwrappedProperty() { + return unwrappedProperty; + } + + public void setUnwrappedProperty(Integer unwrappedProperty) { + this.unwrappedProperty = unwrappedProperty; + } +} diff --git a/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v31/app240/SpringDocApp240Test.java b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v31/app240/SpringDocApp240Test.java new file mode 100644 index 000000000..39e9ac2c4 --- /dev/null +++ b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v31/app240/SpringDocApp240Test.java @@ -0,0 +1,39 @@ +/* + * + * * + * * * + * * * * + * * * * * + * * * * * * 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 test.org.springdoc.api.v31.app240; + +import test.org.springdoc.api.v31.AbstractSpringDocTest; + +import org.springframework.boot.autoconfigure.SpringBootApplication; + +public class SpringDocApp240Test extends AbstractSpringDocTest { + + @SpringBootApplication + static class SpringDocTestApp { + + } +} diff --git a/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v31/app240/WildcardController.java b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v31/app240/WildcardController.java new file mode 100644 index 000000000..34c01dfb8 --- /dev/null +++ b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v31/app240/WildcardController.java @@ -0,0 +1,42 @@ +/* + * + * * + * * * + * * * * + * * * * * + * * * * * * 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 test.org.springdoc.api.v31.app240; + +import io.swagger.v3.oas.annotations.Operation; +import jakarta.servlet.http.HttpServletRequest; + +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class WildcardController { + @PostMapping("/**") + @Operation(summary = "My Wildcard Operation") + public String getItem(HttpServletRequest request) { + return request.getPathInfo(); + } +} diff --git a/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v31/app241/DemoRestController.java b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v31/app241/DemoRestController.java new file mode 100644 index 000000000..edbc59b8f --- /dev/null +++ b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v31/app241/DemoRestController.java @@ -0,0 +1,74 @@ +/* + * + * * + * * * + * * * * + * * * * * + * * * * * * 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 test.org.springdoc.api.v31.app241; + +import java.util.HashSet; +import java.util.Optional; +import java.util.Set; + +import io.swagger.v3.oas.annotations.Parameter; + +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/demo") +public class DemoRestController { + + @GetMapping(produces = MediaType.APPLICATION_JSON_VALUE) + public Set getDemo( + @Parameter(required = false, description = "Very important description.") + @RequestParam(name = "darstellung", required = false) final Optional darstellung) { + return new HashSet<>(); + } + + @PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity setDemo(@RequestBody final String str) { + return ResponseEntity.noContent().build(); + } + + @GetMapping(value = "/{vvpId}", produces = MediaType.APPLICATION_JSON_VALUE) + public String getDemo(@PathVariable("vvpId") final Long vvpId) { + return "Test"; + } + + @PatchMapping("/{vvpId}") + public ResponseEntity patchDemo(@PathVariable("vvpId") final Long idVerfahren, + @RequestBody() final String jsonPatch, + final Optional statusKinderAendern) { + return ResponseEntity.noContent().build(); + } + +} diff --git a/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v31/app241/OpenApiConfig.java b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v31/app241/OpenApiConfig.java new file mode 100644 index 000000000..9cc00301d --- /dev/null +++ b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v31/app241/OpenApiConfig.java @@ -0,0 +1,59 @@ +/* + * + * * + * * * + * * * * + * * * * * + * * * * * * 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 test.org.springdoc.api.v31.app241; + +import org.springdoc.core.customizers.OpenApiCustomizer; +import org.springdoc.core.customizers.ServerBaseUrlCustomizer; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpRequest; + +@Configuration +public class OpenApiConfig { + + @Bean + public OpenApiCustomizer openApiCustomiser() { + return openApi -> { + + }; + } + + @Bean + ServerBaseUrlCustomizer serverBaseUrlCustomizer() { + return new ServerBaseUrlCustomizer() { + + @Override + public String customize(final String serverBaseUrl, + final HttpRequest request) { + // TODO Auto-generated method stub + return null; + } + + }; + } +} \ No newline at end of file diff --git a/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v31/app241/SpringDocApp241Test.java b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v31/app241/SpringDocApp241Test.java new file mode 100644 index 000000000..d4027b764 --- /dev/null +++ b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v31/app241/SpringDocApp241Test.java @@ -0,0 +1,39 @@ +/* + * + * * + * * * + * * * * + * * * * * + * * * * * * 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 test.org.springdoc.api.v31.app241; + +import test.org.springdoc.api.v31.AbstractSpringDocTest; + +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.test.context.TestPropertySource; + +@TestPropertySource(properties = "springdoc.api-docs.resolve-schema-properties=true" ) +public class SpringDocApp241Test extends AbstractSpringDocTest { + + @SpringBootApplication + static class SpringDocTestApp {} +} \ No newline at end of file diff --git a/springdoc-openapi-starter-webmvc-api/src/test/resources/results/3.0.1/app126.json b/springdoc-openapi-starter-webmvc-api/src/test/resources/results/3.0.1/app126.json index 3bea48404..397f519eb 100644 --- a/springdoc-openapi-starter-webmvc-api/src/test/resources/results/3.0.1/app126.json +++ b/springdoc-openapi-starter-webmvc-api/src/test/resources/results/3.0.1/app126.json @@ -20,12 +20,6 @@ "description": "Get all currencies", "operationId": "getAllCurrencies", "responses": { - "401": { - "$ref": "#/components/responses/http401NoToken" - }, - "403": { - "$ref": "#/components/responses/http403" - }, "200": { "description": "All currencies returned", "content": { @@ -38,6 +32,12 @@ } } } + }, + "401": { + "$ref": "#/components/responses/http401BadToken" + }, + "403": { + "$ref": "#/components/responses/http403" } } } diff --git a/springdoc-openapi-starter-webmvc-api/src/test/resources/results/3.0.1/app239.json b/springdoc-openapi-starter-webmvc-api/src/test/resources/results/3.0.1/app239.json new file mode 100644 index 000000000..d83020e50 --- /dev/null +++ b/springdoc-openapi-starter-webmvc-api/src/test/resources/results/3.0.1/app239.json @@ -0,0 +1,52 @@ +{ + "openapi": "3.0.1", + "info": { + "title": "OpenAPI definition", + "version": "v0" + }, + "servers": [ + { + "url": "http://localhost", + "description": "Generated server url" + } + ], + "paths": { + "/api": { + "get": { + "tags": [ + "test-controller" + ], + "operationId": "getRootModel", + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/RootModel" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "RootModel": { + "type": "object", + "properties": { + "rootProperty": { + "type": "integer", + "format": "int32" + }, + "unwrappedProperty": { + "type": "integer", + "format": "int32" + } + } + } + } + } +} diff --git a/springdoc-openapi-starter-webmvc-api/src/test/resources/results/3.0.1/app240.json b/springdoc-openapi-starter-webmvc-api/src/test/resources/results/3.0.1/app240.json new file mode 100644 index 000000000..1f5dfa891 --- /dev/null +++ b/springdoc-openapi-starter-webmvc-api/src/test/resources/results/3.0.1/app240.json @@ -0,0 +1,227 @@ +{ + "openapi": "3.0.1", + "info": { + "title": "OpenAPI definition", + "version": "v0" + }, + "servers": [ + { + "url": "http://localhost", + "description": "Generated server url" + } + ], + "paths": { + "/class-hierarchy/concrete-parent": { + "post": { + "tags": [ + "controller" + ], + "operationId": "concreteParent", + "requestBody": { + "content": { + "application/json": { + "schema": { + "oneOf": [ + { + "$ref": "#/components/schemas/ConcreteParent" + }, + { + "$ref": "#/components/schemas/ChildOfConcrete1" + }, + { + "$ref": "#/components/schemas/ChildOfConcrete2" + } + ] + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/Response" + } + } + } + } + } + } + }, + "/class-hierarchy/abstract-parent": { + "post": { + "tags": [ + "controller" + ], + "operationId": "abstractParent", + "requestBody": { + "content": { + "application/json": { + "schema": { + "oneOf": [ + { + "$ref": "#/components/schemas/ChildOfAbstract1" + }, + { + "$ref": "#/components/schemas/ChildOfAbstract2" + } + ] + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/Response" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "ChildOfConcrete1": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/ConcreteParent" + }, + { + "type": "object", + "properties": { + "concreteChild1Param": { + "type": "string" + } + } + } + ] + }, + "ChildOfConcrete2": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/ConcreteParent" + }, + { + "type": "object", + "properties": { + "concreteChild2Param": { + "type": "string" + } + } + } + ] + }, + "ConcreteParent": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "type": { + "type": "string" + } + }, + "discriminator": { + "propertyName": "type" + } + }, + "AbstractParent": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "type": { + "type": "string" + } + }, + "discriminator": { + "propertyName": "type" + } + }, + "ChildOfAbstract1": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/AbstractParent" + }, + { + "type": "object", + "properties": { + "abstrachChild1Param": { + "type": "string" + } + } + } + ] + }, + "ChildOfAbstract2": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/AbstractParent" + }, + { + "type": "object", + "properties": { + "abstractChild2Param": { + "type": "string" + } + } + } + ] + }, + "Response": { + "type": "object", + "properties": { + "abstractParent": { + "oneOf": [ + { + "$ref": "#/components/schemas/ChildOfAbstract1" + }, + { + "$ref": "#/components/schemas/ChildOfAbstract2" + } + ] + }, + "concreteParents": { + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/ConcreteParent" + }, + { + "$ref": "#/components/schemas/ChildOfConcrete1" + }, + { + "$ref": "#/components/schemas/ChildOfConcrete2" + } + ] + } + } + } + } + } + } +} \ No newline at end of file diff --git a/springdoc-openapi-starter-webmvc-api/src/test/resources/results/3.0.1/app241.json b/springdoc-openapi-starter-webmvc-api/src/test/resources/results/3.0.1/app241.json new file mode 100644 index 000000000..b5dc7bdc7 --- /dev/null +++ b/springdoc-openapi-starter-webmvc-api/src/test/resources/results/3.0.1/app241.json @@ -0,0 +1,132 @@ +{ + "openapi": "3.0.1", + "info": { + "title": "OpenAPI definition", + "version": "v0" + }, + "servers": [ + { + "url": "http://localhost", + "description": "Generated server url" + } + ], + "paths": { + "/parent": { + "post": { + "tags": [ + "hello-controller" + ], + "operationId": "parentEndpoint", + "requestBody": { + "content": { + "application/json": { + "schema": { + "oneOf": [ + { + "$ref": "#/components/schemas/Superclass" + }, + { + "$ref": "#/components/schemas/IntermediateClass" + }, + { + "$ref": "#/components/schemas/Image" + }, + { + "$ref": "#/components/schemas/Mail" + }, + { + "$ref": "#/components/schemas/Home" + } + ] + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "OK" + } + } + } + } + }, + "components": { + "schemas": { + "Home": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/Mail" + } + ] + }, + "Image": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/IntermediateClass" + } + ] + }, + "IntermediateClass": { + "required": [ + "@type" + ], + "type": "object", + "discriminator": { + "propertyName": "@type" + }, + "allOf": [ + { + "$ref": "#/components/schemas/Superclass" + }, + { + "type": "object", + "properties": { + "@type": { + "type": "string" + } + } + } + ] + }, + "Mail": { + "required": [ + "@type" + ], + "type": "object", + "discriminator": { + "propertyName": "@type" + }, + "allOf": [ + { + "$ref": "#/components/schemas/IntermediateClass" + }, + { + "type": "object", + "properties": { + "@type": { + "type": "string" + } + } + } + ] + }, + "Superclass": { + "required": [ + "@type" + ], + "type": "object", + "properties": { + "@type": { + "type": "string" + } + }, + "discriminator": { + "propertyName": "@type" + } + } + } + } +} \ No newline at end of file diff --git a/springdoc-openapi-starter-webmvc-api/src/test/resources/results/3.1.0/app126.json b/springdoc-openapi-starter-webmvc-api/src/test/resources/results/3.1.0/app126.json index a20e02a5f..be22bf20b 100644 --- a/springdoc-openapi-starter-webmvc-api/src/test/resources/results/3.1.0/app126.json +++ b/springdoc-openapi-starter-webmvc-api/src/test/resources/results/3.1.0/app126.json @@ -20,12 +20,6 @@ "description": "Get all currencies", "operationId": "getAllCurrencies", "responses": { - "401": { - "$ref": "#/components/responses/http401NoToken" - }, - "403": { - "$ref": "#/components/responses/http403" - }, "200": { "description": "All currencies returned", "content": { @@ -38,6 +32,12 @@ } } } + }, + "401": { + "$ref": "#/components/responses/http401BadToken" + }, + "403": { + "$ref": "#/components/responses/http403" } } } @@ -62,15 +62,15 @@ "type": "object" } }, - "status": { - "type": "integer", - "format": "int32" - }, "title": { "type": "string" }, "detail": { "type": "string" + }, + "status": { + "type": "integer", + "format": "int32" } } } diff --git a/springdoc-openapi-starter-webmvc-api/src/test/resources/results/3.1.0/app239.json b/springdoc-openapi-starter-webmvc-api/src/test/resources/results/3.1.0/app239.json new file mode 100644 index 000000000..0ef50ddff --- /dev/null +++ b/springdoc-openapi-starter-webmvc-api/src/test/resources/results/3.1.0/app239.json @@ -0,0 +1,52 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "OpenAPI definition", + "version": "v0" + }, + "servers": [ + { + "url": "http://localhost", + "description": "Generated server url" + } + ], + "paths": { + "/api": { + "get": { + "tags": [ + "test-controller" + ], + "operationId": "getRootModel", + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/RootModel" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "RootModel": { + "type": "object", + "properties": { + "rootProperty": { + "type": "integer", + "format": "int32" + }, + "unwrappedProperty": { + "type": "integer", + "format": "int32" + } + } + } + } + } +} diff --git a/springdoc-openapi-starter-webmvc-api/src/test/resources/results/3.1.0/app240.json b/springdoc-openapi-starter-webmvc-api/src/test/resources/results/3.1.0/app240.json new file mode 100644 index 000000000..751bee35c --- /dev/null +++ b/springdoc-openapi-starter-webmvc-api/src/test/resources/results/3.1.0/app240.json @@ -0,0 +1,37 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "OpenAPI definition", + "version": "v0" + }, + "servers": [ + { + "url": "http://localhost", + "description": "Generated server url" + } + ], + "paths": { + "/**": { + "post": { + "tags": [ + "wildcard-controller" + ], + "summary": "My Wildcard Operation", + "operationId": "getItem", + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "type": "string" + } + } + } + } + } + } + } + }, + "components": {} +} \ No newline at end of file diff --git a/springdoc-openapi-starter-webmvc-api/src/test/resources/results/3.1.0/app241.json b/springdoc-openapi-starter-webmvc-api/src/test/resources/results/3.1.0/app241.json new file mode 100644 index 000000000..0a9af7bf9 --- /dev/null +++ b/springdoc-openapi-starter-webmvc-api/src/test/resources/results/3.1.0/app241.json @@ -0,0 +1,151 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "OpenAPI definition", + "version": "v0" + }, + "paths": { + "/demo": { + "get": { + "tags": [ + "demo-rest-controller" + ], + "operationId": "getDemo", + "parameters": [ + { + "name": "darstellung", + "in": "query", + "description": "Very important description.", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + } + } + } + } + } + }, + "post": { + "tags": [ + "demo-rest-controller" + ], + "operationId": "setDemo", + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "type": "object" + } + } + } + } + } + } + }, + "/demo/{vvpId}": { + "get": { + "tags": [ + "demo-rest-controller" + ], + "operationId": "getDemo_1", + "parameters": [ + { + "name": "vvpId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + } + }, + "patch": { + "tags": [ + "demo-rest-controller" + ], + "operationId": "patchDemo", + "parameters": [ + { + "name": "vvpId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "statusKinderAendern", + "in": "query", + "required": false, + "schema": { + "type": "boolean" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "type": "object" + } + } + } + } + } + } + } + }, + "components": {} +} diff --git a/springdoc-openapi-starter-webmvc-ui/pom.xml b/springdoc-openapi-starter-webmvc-ui/pom.xml index f16b12bfa..a02c5f0e4 100644 --- a/springdoc-openapi-starter-webmvc-ui/pom.xml +++ b/springdoc-openapi-starter-webmvc-ui/pom.xml @@ -3,7 +3,7 @@ org.springdoc springdoc-openapi - 2.8.4 + 2.8.5 springdoc-openapi-starter-webmvc-ui diff --git a/springdoc-openapi-tests/pom.xml b/springdoc-openapi-tests/pom.xml index 5ffc3b88e..9c8e6964b 100644 --- a/springdoc-openapi-tests/pom.xml +++ b/springdoc-openapi-tests/pom.xml @@ -2,7 +2,7 @@ springdoc-openapi org.springdoc - 2.8.4 + 2.8.5 pom 4.0.0 diff --git a/springdoc-openapi-tests/springdoc-openapi-actuator-webflux-tests/pom.xml b/springdoc-openapi-tests/springdoc-openapi-actuator-webflux-tests/pom.xml index 2634306e0..aec25732c 100644 --- a/springdoc-openapi-tests/springdoc-openapi-actuator-webflux-tests/pom.xml +++ b/springdoc-openapi-tests/springdoc-openapi-actuator-webflux-tests/pom.xml @@ -2,7 +2,7 @@ springdoc-openapi-tests org.springdoc - 2.8.4 + 2.8.5 4.0.0 diff --git a/springdoc-openapi-tests/springdoc-openapi-actuator-webmvc-tests/pom.xml b/springdoc-openapi-tests/springdoc-openapi-actuator-webmvc-tests/pom.xml index 8d35755c7..c7eaa8f48 100644 --- a/springdoc-openapi-tests/springdoc-openapi-actuator-webmvc-tests/pom.xml +++ b/springdoc-openapi-tests/springdoc-openapi-actuator-webmvc-tests/pom.xml @@ -2,7 +2,7 @@ springdoc-openapi-tests org.springdoc - 2.8.4 + 2.8.5 4.0.0 diff --git a/springdoc-openapi-tests/springdoc-openapi-data-rest-tests/pom.xml b/springdoc-openapi-tests/springdoc-openapi-data-rest-tests/pom.xml index 58dbf51bd..689cce0c5 100644 --- a/springdoc-openapi-tests/springdoc-openapi-data-rest-tests/pom.xml +++ b/springdoc-openapi-tests/springdoc-openapi-data-rest-tests/pom.xml @@ -2,7 +2,7 @@ springdoc-openapi-tests org.springdoc - 2.8.4 + 2.8.5 4.0.0 springdoc-openapi-data-rest-tests diff --git a/springdoc-openapi-tests/springdoc-openapi-data-rest-tests/src/test/java/test/org/springdoc/api/v31/app14/HelloController.java b/springdoc-openapi-tests/springdoc-openapi-data-rest-tests/src/test/java/test/org/springdoc/api/v31/app14/HelloController.java index 743ad62f6..282a794d0 100644 --- a/springdoc-openapi-tests/springdoc-openapi-data-rest-tests/src/test/java/test/org/springdoc/api/v31/app14/HelloController.java +++ b/springdoc-openapi-tests/springdoc-openapi-data-rest-tests/src/test/java/test/org/springdoc/api/v31/app14/HelloController.java @@ -21,7 +21,7 @@ * * * * * * * * * - * + * */ package test.org.springdoc.api.v31.app14; @@ -31,6 +31,8 @@ import org.springdoc.core.annotations.ParameterObject; import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.data.web.PageableDefault; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @@ -43,4 +45,11 @@ public ResponseEntity> getAllPets(@ParameterObject Pageable page return null; } + @GetMapping("/test1") + public String getPatientList1(@PageableDefault(size = 100, sort = { "someField", "someoTHER" }, + direction = Sort.Direction.DESC) + @ParameterObject Pageable pageable) { + return "bla"; + } + } diff --git a/springdoc-openapi-tests/springdoc-openapi-data-rest-tests/src/test/resources/results/3.0.1/app24.json b/springdoc-openapi-tests/springdoc-openapi-data-rest-tests/src/test/resources/results/3.0.1/app24.json index 33090dcc5..30ceb9d64 100644 --- a/springdoc-openapi-tests/springdoc-openapi-data-rest-tests/src/test/resources/results/3.0.1/app24.json +++ b/springdoc-openapi-tests/springdoc-openapi-data-rest-tests/src/test/resources/results/3.0.1/app24.json @@ -27,14 +27,14 @@ } }, { - "name": "name", + "name": "email", "in": "query", "schema": { "type": "string" } }, { - "name": "email", + "name": "name", "in": "query", "schema": { "type": "string" @@ -90,6 +90,12 @@ "type": "integer", "format": "int64" }, + "first": { + "type": "boolean" + }, + "last": { + "type": "boolean" + }, "size": { "type": "integer", "format": "int32" @@ -107,15 +113,9 @@ "sort": { "$ref": "#/components/schemas/SortObject" }, - "last": { - "type": "boolean" - }, "pageable": { "$ref": "#/components/schemas/PageableObject" }, - "first": { - "type": "boolean" - }, "numberOfElements": { "type": "integer", "format": "int32" @@ -135,6 +135,12 @@ "sort": { "$ref": "#/components/schemas/SortObject" }, + "unpaged": { + "type": "boolean" + }, + "paged": { + "type": "boolean" + }, "pageNumber": { "type": "integer", "format": "int32" @@ -142,12 +148,6 @@ "pageSize": { "type": "integer", "format": "int32" - }, - "paged": { - "type": "boolean" - }, - "unpaged": { - "type": "boolean" } } }, @@ -157,10 +157,10 @@ "empty": { "type": "boolean" }, - "sorted": { + "unsorted": { "type": "boolean" }, - "unsorted": { + "sorted": { "type": "boolean" } } diff --git a/springdoc-openapi-tests/springdoc-openapi-data-rest-tests/src/test/resources/results/3.0.1/app30.json b/springdoc-openapi-tests/springdoc-openapi-data-rest-tests/src/test/resources/results/3.0.1/app30.json index 2cf234399..a1c4cc176 100644 --- a/springdoc-openapi-tests/springdoc-openapi-data-rest-tests/src/test/resources/results/3.0.1/app30.json +++ b/springdoc-openapi-tests/springdoc-openapi-data-rest-tests/src/test/resources/results/3.0.1/app30.json @@ -19,14 +19,14 @@ "operationId": "testQueryDslAndSpringDoc", "parameters": [ { - "name": "name", + "name": "email", "in": "query", "schema": { "type": "string" } }, { - "name": "email", + "name": "name", "in": "query", "schema": { "type": "string" @@ -70,4 +70,4 @@ } } } -} \ No newline at end of file +} diff --git a/springdoc-openapi-tests/springdoc-openapi-data-rest-tests/src/test/resources/results/3.0.1/app5.json b/springdoc-openapi-tests/springdoc-openapi-data-rest-tests/src/test/resources/results/3.0.1/app5.json index 899554e82..932647c22 100644 --- a/springdoc-openapi-tests/springdoc-openapi-data-rest-tests/src/test/resources/results/3.0.1/app5.json +++ b/springdoc-openapi-tests/springdoc-openapi-data-rest-tests/src/test/resources/results/3.0.1/app5.json @@ -34,10 +34,11 @@ } }, { - "name": "code", + "name": "id", "in": "query", "schema": { - "type": "string" + "type": "integer", + "format": "int64" } }, { @@ -48,36 +49,35 @@ } }, { - "name": "postCode", + "name": "shortName", "in": "query", "schema": { "type": "string" } }, { - "name": "id", + "name": "status", "in": "query", "schema": { - "type": "integer", - "format": "int64" + "type": "string", + "enum": [ + "ACTIVE", + "INACTIVE" + ] } }, { - "name": "shortName", + "name": "code", "in": "query", "schema": { "type": "string" } }, { - "name": "status", + "name": "postCode", "in": "query", "schema": { - "type": "string", - "enum": [ - "ACTIVE", - "INACTIVE" - ] + "type": "string" } } ], diff --git a/springdoc-openapi-tests/springdoc-openapi-data-rest-tests/src/test/resources/results/3.1.0/app14.json b/springdoc-openapi-tests/springdoc-openapi-data-rest-tests/src/test/resources/results/3.1.0/app14.json index a2e119230..471b990a2 100644 --- a/springdoc-openapi-tests/springdoc-openapi-data-rest-tests/src/test/resources/results/3.1.0/app14.json +++ b/springdoc-openapi-tests/springdoc-openapi-data-rest-tests/src/test/resources/results/3.1.0/app14.json @@ -11,6 +11,66 @@ } ], "paths": { + "/test1": { + "get": { + "tags": [ + "hello-controller" + ], + "operationId": "getPatientList1", + "parameters": [ + { + "name": "prefix_pages", + "in": "query", + "description": "One-based page index (1..N)", + "required": false, + "schema": { + "type": "integer", + "default": 1, + "minimum": 0 + } + }, + { + "name": "prefix_sizes", + "in": "query", + "description": "The size of the page to be returned", + "required": false, + "schema": { + "type": "integer", + "default": 100, + "minimum": 1 + } + }, + { + "name": "sorts", + "in": "query", + "description": "Sorting criteria in the format: property,(asc|desc). Default sort order is ascending. Multiple sort criteria are supported.", + "required": false, + "schema": { + "type": "array", + "default": [ + "someField,DESC", + "someoTHER,DESC" + ], + "items": { + "type": "string" + } + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "type": "string" + } + } + } + } + } + } + }, "/search": { "get": { "tags": [ diff --git a/springdoc-openapi-tests/springdoc-openapi-data-rest-tests/src/test/resources/results/3.1.0/app24.json b/springdoc-openapi-tests/springdoc-openapi-data-rest-tests/src/test/resources/results/3.1.0/app24.json index 76b3a324f..1a901539e 100644 --- a/springdoc-openapi-tests/springdoc-openapi-data-rest-tests/src/test/resources/results/3.1.0/app24.json +++ b/springdoc-openapi-tests/springdoc-openapi-data-rest-tests/src/test/resources/results/3.1.0/app24.json @@ -27,14 +27,14 @@ } }, { - "name": "name", + "name": "email", "in": "query", "schema": { "type": "string" } }, { - "name": "email", + "name": "name", "in": "query", "schema": { "type": "string" @@ -62,14 +62,14 @@ "type": "object", "properties": { "page": { - "minimum": 0, "type": "integer", - "format": "int32" + "format": "int32", + "minimum": 0 }, "size": { - "minimum": 1, "type": "integer", - "format": "int32" + "format": "int32", + "minimum": 1 }, "sort": { "type": "array", @@ -90,6 +90,12 @@ "type": "integer", "format": "int64" }, + "first": { + "type": "boolean" + }, + "last": { + "type": "boolean" + }, "size": { "type": "integer", "format": "int32" @@ -107,15 +113,9 @@ "sort": { "$ref": "#/components/schemas/SortObject" }, - "last": { - "type": "boolean" - }, "pageable": { "$ref": "#/components/schemas/PageableObject" }, - "first": { - "type": "boolean" - }, "numberOfElements": { "type": "integer", "format": "int32" @@ -135,6 +135,12 @@ "sort": { "$ref": "#/components/schemas/SortObject" }, + "unpaged": { + "type": "boolean" + }, + "paged": { + "type": "boolean" + }, "pageNumber": { "type": "integer", "format": "int32" @@ -142,12 +148,6 @@ "pageSize": { "type": "integer", "format": "int32" - }, - "paged": { - "type": "boolean" - }, - "unpaged": { - "type": "boolean" } } }, @@ -157,10 +157,10 @@ "empty": { "type": "boolean" }, - "sorted": { + "unsorted": { "type": "boolean" }, - "unsorted": { + "sorted": { "type": "boolean" } } diff --git a/springdoc-openapi-tests/springdoc-openapi-data-rest-tests/src/test/resources/results/3.1.0/app30.json b/springdoc-openapi-tests/springdoc-openapi-data-rest-tests/src/test/resources/results/3.1.0/app30.json index bbb90bbe9..62757da1a 100644 --- a/springdoc-openapi-tests/springdoc-openapi-data-rest-tests/src/test/resources/results/3.1.0/app30.json +++ b/springdoc-openapi-tests/springdoc-openapi-data-rest-tests/src/test/resources/results/3.1.0/app30.json @@ -19,14 +19,14 @@ "operationId": "testQueryDslAndSpringDoc", "parameters": [ { - "name": "name", + "name": "email", "in": "query", "schema": { "type": "string" } }, { - "name": "email", + "name": "name", "in": "query", "schema": { "type": "string" @@ -70,4 +70,4 @@ } } } -} \ No newline at end of file +} diff --git a/springdoc-openapi-tests/springdoc-openapi-data-rest-tests/src/test/resources/results/3.1.0/app5.json b/springdoc-openapi-tests/springdoc-openapi-data-rest-tests/src/test/resources/results/3.1.0/app5.json index e46116a9f..fe52268d8 100644 --- a/springdoc-openapi-tests/springdoc-openapi-data-rest-tests/src/test/resources/results/3.1.0/app5.json +++ b/springdoc-openapi-tests/springdoc-openapi-data-rest-tests/src/test/resources/results/3.1.0/app5.json @@ -34,10 +34,11 @@ } }, { - "name": "code", + "name": "id", "in": "query", "schema": { - "type": "string" + "type": "integer", + "format": "int64" } }, { @@ -48,36 +49,35 @@ } }, { - "name": "postCode", + "name": "shortName", "in": "query", "schema": { "type": "string" } }, { - "name": "id", + "name": "status", "in": "query", "schema": { - "type": "integer", - "format": "int64" + "type": "string", + "enum": [ + "ACTIVE", + "INACTIVE" + ] } }, { - "name": "shortName", + "name": "code", "in": "query", "schema": { "type": "string" } }, { - "name": "status", + "name": "postCode", "in": "query", "schema": { - "type": "string", - "enum": [ - "ACTIVE", - "INACTIVE" - ] + "type": "string" } } ], diff --git a/springdoc-openapi-tests/springdoc-openapi-function-webflux-tests/pom.xml b/springdoc-openapi-tests/springdoc-openapi-function-webflux-tests/pom.xml index ae7b361d1..6c0f31049 100644 --- a/springdoc-openapi-tests/springdoc-openapi-function-webflux-tests/pom.xml +++ b/springdoc-openapi-tests/springdoc-openapi-function-webflux-tests/pom.xml @@ -2,7 +2,7 @@ springdoc-openapi-tests org.springdoc - 2.8.4 + 2.8.5 4.0.0 diff --git a/springdoc-openapi-tests/springdoc-openapi-function-webmvc-tests/pom.xml b/springdoc-openapi-tests/springdoc-openapi-function-webmvc-tests/pom.xml index f956be798..a6d1f9e82 100644 --- a/springdoc-openapi-tests/springdoc-openapi-function-webmvc-tests/pom.xml +++ b/springdoc-openapi-tests/springdoc-openapi-function-webmvc-tests/pom.xml @@ -2,7 +2,7 @@ springdoc-openapi-tests org.springdoc - 2.8.4 + 2.8.5 4.0.0 diff --git a/springdoc-openapi-tests/springdoc-openapi-groovy-tests/pom.xml b/springdoc-openapi-tests/springdoc-openapi-groovy-tests/pom.xml index 5597b2d91..cc71b2f05 100644 --- a/springdoc-openapi-tests/springdoc-openapi-groovy-tests/pom.xml +++ b/springdoc-openapi-tests/springdoc-openapi-groovy-tests/pom.xml @@ -3,7 +3,7 @@ org.springdoc springdoc-openapi-tests - 2.8.4 + 2.8.5 springdoc-openapi-groovy-tests diff --git a/springdoc-openapi-tests/springdoc-openapi-hateoas-tests/pom.xml b/springdoc-openapi-tests/springdoc-openapi-hateoas-tests/pom.xml index 5b6002f6c..b8c863bd4 100644 --- a/springdoc-openapi-tests/springdoc-openapi-hateoas-tests/pom.xml +++ b/springdoc-openapi-tests/springdoc-openapi-hateoas-tests/pom.xml @@ -2,7 +2,7 @@ springdoc-openapi-tests org.springdoc - 2.8.4 + 2.8.5 4.0.0 springdoc-openapi-hateoas-tests diff --git a/springdoc-openapi-tests/springdoc-openapi-hateoas-tests/src/test/java/test/org/springdoc/api/v31/app11/SpringDocApp11Test.java b/springdoc-openapi-tests/springdoc-openapi-hateoas-tests/src/test/java/test/org/springdoc/api/v31/app11/SpringDocApp11Test.java new file mode 100644 index 000000000..3e619a272 --- /dev/null +++ b/springdoc-openapi-tests/springdoc-openapi-hateoas-tests/src/test/java/test/org/springdoc/api/v31/app11/SpringDocApp11Test.java @@ -0,0 +1,39 @@ +/* + * + * * + * * * + * * * * + * * * * * + * * * * * * 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 test.org.springdoc.api.v31.app11; + +import test.org.springdoc.api.v31.AbstractSpringDocTest; + +import org.springframework.boot.autoconfigure.SpringBootApplication; + +public class SpringDocApp11Test extends AbstractSpringDocTest { + + @SpringBootApplication + static class SpringDocTestApp { + } + +} \ No newline at end of file diff --git a/springdoc-openapi-tests/springdoc-openapi-hateoas-tests/src/test/java/test/org/springdoc/api/v31/app11/configuration/WebMvcConfiguration.java b/springdoc-openapi-tests/springdoc-openapi-hateoas-tests/src/test/java/test/org/springdoc/api/v31/app11/configuration/WebMvcConfiguration.java new file mode 100644 index 000000000..032eeeac7 --- /dev/null +++ b/springdoc-openapi-tests/springdoc-openapi-hateoas-tests/src/test/java/test/org/springdoc/api/v31/app11/configuration/WebMvcConfiguration.java @@ -0,0 +1,25 @@ +package test.org.springdoc.api.v31.app11.configuration; + +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.ObjectMapper; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.MediaType; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; + +@Configuration +public class WebMvcConfiguration { + + @Bean + MappingJackson2HttpMessageConverter getMappingJacksonHttpMessageConverter() { + MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); + converter.setSupportedMediaTypes(List.of(MediaType.APPLICATION_JSON)); + converter.setObjectMapper(new ObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_NULL) + ); + + return converter; + } +} diff --git a/springdoc-openapi-tests/springdoc-openapi-hateoas-tests/src/test/java/test/org/springdoc/api/v31/app11/controllers/BasicController.java b/springdoc-openapi-tests/springdoc-openapi-hateoas-tests/src/test/java/test/org/springdoc/api/v31/app11/controllers/BasicController.java new file mode 100644 index 000000000..7f6586f05 --- /dev/null +++ b/springdoc-openapi-tests/springdoc-openapi-hateoas-tests/src/test/java/test/org/springdoc/api/v31/app11/controllers/BasicController.java @@ -0,0 +1,41 @@ +package test.org.springdoc.api.v31.app11.controllers; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import test.org.springdoc.api.v31.app11.model.Cat; + +import org.springframework.hateoas.MediaTypes; +import org.springframework.hateoas.RepresentationModel; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping(path = "/") +public class BasicController { + + @GetMapping("/cat") + @ResponseStatus(HttpStatus.OK) + @Operation(summary = "get", description = "Provides an animal.") + public String get(Cat cat) { + return cat != null ? cat.getName() : ""; + } + + @GetMapping("/test") + @ResponseStatus(HttpStatus.OK) + @Operation(summary = "get", description = "Provides a response.") + @ApiResponse(content = @Content(mediaType = MediaTypes.HAL_JSON_VALUE, + schema = @io.swagger.v3.oas.annotations.media.Schema(implementation = Response.class)), + responseCode = "200") + public Response get() { + return new Response("value"); + } + + // dummy + public static class Response extends RepresentationModel { + public Response(String v) {} + } +} diff --git a/springdoc-openapi-tests/springdoc-openapi-hateoas-tests/src/test/java/test/org/springdoc/api/v31/app11/controllers/CustomOpenApiWebMvcResource.java b/springdoc-openapi-tests/springdoc-openapi-hateoas-tests/src/test/java/test/org/springdoc/api/v31/app11/controllers/CustomOpenApiWebMvcResource.java new file mode 100644 index 000000000..f88930430 --- /dev/null +++ b/springdoc-openapi-tests/springdoc-openapi-hateoas-tests/src/test/java/test/org/springdoc/api/v31/app11/controllers/CustomOpenApiWebMvcResource.java @@ -0,0 +1,27 @@ +package test.org.springdoc.api.v31.app11.controllers; + +import org.springdoc.core.customizers.SpringDocCustomizers; +import org.springdoc.core.properties.SpringDocConfigProperties; +import org.springdoc.core.providers.SpringDocProviders; +import org.springdoc.core.service.AbstractRequestService; +import org.springdoc.core.service.GenericResponseService; +import org.springdoc.core.service.OpenAPIService; +import org.springdoc.core.service.OperationService; +import org.springdoc.webmvc.api.OpenApiWebMvcResource; + +import org.springframework.beans.factory.ObjectFactory; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class CustomOpenApiWebMvcResource extends OpenApiWebMvcResource { + + public CustomOpenApiWebMvcResource(ObjectFactory openAPIBuilderObjectFactory, + AbstractRequestService requestBuilder, + GenericResponseService responseBuilder, + OperationService operationParser, + SpringDocConfigProperties springDocConfigProperties, + SpringDocProviders springDocProviders, + SpringDocCustomizers springDocCustomizers) { + super(openAPIBuilderObjectFactory, requestBuilder, responseBuilder, operationParser, springDocConfigProperties, springDocProviders, springDocCustomizers); + } +} \ No newline at end of file diff --git a/springdoc-openapi-tests/springdoc-openapi-hateoas-tests/src/test/java/test/org/springdoc/api/v31/app11/model/Cat.java b/springdoc-openapi-tests/springdoc-openapi-hateoas-tests/src/test/java/test/org/springdoc/api/v31/app11/model/Cat.java new file mode 100644 index 000000000..95595b01a --- /dev/null +++ b/springdoc-openapi-tests/springdoc-openapi-hateoas-tests/src/test/java/test/org/springdoc/api/v31/app11/model/Cat.java @@ -0,0 +1,24 @@ +package test.org.springdoc.api.v31.app11.model; + +import com.fasterxml.jackson.annotation.JsonUnwrapped; +import io.swagger.v3.oas.annotations.media.Schema; + +@Schema(description = "Represents a Cat class.") +public class Cat { + + @JsonUnwrapped + @Schema(description = "The name.", nullable = true) + private String name; + + public Cat(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/springdoc-openapi-tests/springdoc-openapi-hateoas-tests/src/test/resources/results/3.1.0/app11.json b/springdoc-openapi-tests/springdoc-openapi-hateoas-tests/src/test/resources/results/3.1.0/app11.json new file mode 100644 index 000000000..a40b8cb0b --- /dev/null +++ b/springdoc-openapi-tests/springdoc-openapi-hateoas-tests/src/test/resources/results/3.1.0/app11.json @@ -0,0 +1,126 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "OpenAPI definition", + "version": "v0" + }, + "servers": [ + { + "url": "http://localhost", + "description": "Generated server url" + } + ], + "paths": { + "/test": { + "get": { + "tags": [ + "basic-controller" + ], + "summary": "get", + "description": "Provides a response.", + "operationId": "get", + "responses": { + "200": { + "description": "OK", + "content": { + "application/hal+json": { + "schema": { + "$ref": "#/components/schemas/Response" + } + } + } + } + } + } + }, + "/cat": { + "get": { + "tags": [ + "basic-controller" + ], + "summary": "get", + "description": "Provides an animal.", + "operationId": "get_1", + "parameters": [ + { + "name": "cat", + "in": "query", + "required": true, + "schema": { + "$ref": "#/components/schemas/Cat" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "type": "string" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "Response": { + "type": "object", + "properties": { + "_links": { + "$ref": "#/components/schemas/Links" + } + } + }, + "Cat": { + "type": "object", + "description": "Represents a Cat class.", + "properties": { + "name": { + "type": "string", + "description": "The name." + } + } + }, + "Link": { + "type": "object", + "properties": { + "href": { + "type": "string" + }, + "hreflang": { + "type": "string" + }, + "title": { + "type": "string" + }, + "type": { + "type": "string" + }, + "deprecation": { + "type": "string" + }, + "profile": { + "type": "string" + }, + "name": { + "type": "string" + }, + "templated": { + "type": "boolean" + } + } + }, + "Links": { + "type": "object", + "additionalProperties": { + "$ref": "#/components/schemas/Link" + } + } + } + } +} diff --git a/springdoc-openapi-tests/springdoc-openapi-javadoc-tests/pom.xml b/springdoc-openapi-tests/springdoc-openapi-javadoc-tests/pom.xml index a89128c99..127082932 100644 --- a/springdoc-openapi-tests/springdoc-openapi-javadoc-tests/pom.xml +++ b/springdoc-openapi-tests/springdoc-openapi-javadoc-tests/pom.xml @@ -2,7 +2,7 @@ org.springdoc springdoc-openapi-tests - 2.8.4 + 2.8.5 4.0.0 diff --git a/springdoc-openapi-tests/springdoc-openapi-javadoc-tests/src/test/resources/results/3.0.1/app126.json b/springdoc-openapi-tests/springdoc-openapi-javadoc-tests/src/test/resources/results/3.0.1/app126.json index 47ce6c5a7..ff6b88de5 100644 --- a/springdoc-openapi-tests/springdoc-openapi-javadoc-tests/src/test/resources/results/3.0.1/app126.json +++ b/springdoc-openapi-tests/springdoc-openapi-javadoc-tests/src/test/resources/results/3.0.1/app126.json @@ -26,12 +26,6 @@ "description": "Get all currencies", "operationId": "getAllCurrencies", "responses": { - "401": { - "$ref": "#/components/responses/http401NoToken" - }, - "403": { - "$ref": "#/components/responses/http403" - }, "200": { "description": "All currencies returned", "content": { @@ -44,6 +38,12 @@ } } } + }, + "401": { + "$ref": "#/components/responses/http401BadToken" + }, + "403": { + "$ref": "#/components/responses/http403" } } } @@ -71,6 +71,11 @@ }, "description": "Optional, additional attributes of the problem. Implementations can choose to ignore this in favor of concrete,\n typed fields." }, + "status": { + "type": "integer", + "description": "The HTTP status code generated by the origin server for this\n occurrence of the problem.", + "format": "int32" + }, "title": { "type": "string", "description": "A short, human-readable summary of the problem type. It SHOULD NOT\n change from occurrence to occurrence of the problem, except for\n purposes of localisation." @@ -78,11 +83,6 @@ "detail": { "type": "string", "description": "A human readable explanation specific to this occurrence of the problem." - }, - "status": { - "type": "integer", - "description": "The HTTP status code generated by the origin server for this\n occurrence of the problem.", - "format": "int32" } }, "description": "The interface Problem." diff --git a/springdoc-openapi-tests/springdoc-openapi-javadoc-tests/src/test/resources/results/3.1.0/app126.json b/springdoc-openapi-tests/springdoc-openapi-javadoc-tests/src/test/resources/results/3.1.0/app126.json index 074f383aa..57be66520 100644 --- a/springdoc-openapi-tests/springdoc-openapi-javadoc-tests/src/test/resources/results/3.1.0/app126.json +++ b/springdoc-openapi-tests/springdoc-openapi-javadoc-tests/src/test/resources/results/3.1.0/app126.json @@ -26,12 +26,6 @@ "description": "Get all currencies", "operationId": "getAllCurrencies", "responses": { - "401": { - "$ref": "#/components/responses/http401NoToken" - }, - "403": { - "$ref": "#/components/responses/http403" - }, "200": { "description": "All currencies returned", "content": { @@ -44,6 +38,12 @@ } } } + }, + "401": { + "$ref": "#/components/responses/http401BadToken" + }, + "403": { + "$ref": "#/components/responses/http403" } } } @@ -53,16 +53,17 @@ "schemas": { "Problem": { "type": "object", + "description": "The interface Problem.", "properties": { "instance": { "type": "string", - "description": "An absolute URI that identifies the specific occurrence of the problem.\n It may or may not yield further information if dereferenced.", - "format": "uri" + "format": "uri", + "description": "An absolute URI that identifies the specific occurrence of the problem.\n It may or may not yield further information if dereferenced." }, "type": { "type": "string", - "description": "An absolute URI that identifies the problem type. When dereferenced,\n it SHOULD provide human-readable documentation for the problem type\n (e.g., using HTML). When this member is not present, its value is\n assumed to be \"about:blank\".", - "format": "uri" + "format": "uri", + "description": "An absolute URI that identifies the problem type. When dereferenced,\n it SHOULD provide human-readable documentation for the problem type\n (e.g., using HTML). When this member is not present, its value is\n assumed to be \"about:blank\"." }, "parameters": { "type": "object", @@ -71,6 +72,11 @@ }, "description": "Optional, additional attributes of the problem. Implementations can choose to ignore this in favor of concrete,\n typed fields." }, + "status": { + "type": "integer", + "format": "int32", + "description": "The HTTP status code generated by the origin server for this\n occurrence of the problem." + }, "title": { "type": "string", "description": "A short, human-readable summary of the problem type. It SHOULD NOT\n change from occurrence to occurrence of the problem, except for\n purposes of localisation." @@ -78,14 +84,8 @@ "detail": { "type": "string", "description": "A human readable explanation specific to this occurrence of the problem." - }, - "status": { - "type": "integer", - "description": "The HTTP status code generated by the origin server for this\n occurrence of the problem.", - "format": "int32" } - }, - "description": "The interface Problem." + } } }, "responses": { diff --git a/springdoc-openapi-tests/springdoc-openapi-kotlin-webflux-tests/pom.xml b/springdoc-openapi-tests/springdoc-openapi-kotlin-webflux-tests/pom.xml index 3b25490e3..a6b7c7394 100644 --- a/springdoc-openapi-tests/springdoc-openapi-kotlin-webflux-tests/pom.xml +++ b/springdoc-openapi-tests/springdoc-openapi-kotlin-webflux-tests/pom.xml @@ -2,7 +2,7 @@ springdoc-openapi-tests org.springdoc - 2.8.4 + 2.8.5 4.0.0 springdoc-openapi-kotlin-webflux-tests diff --git a/springdoc-openapi-tests/springdoc-openapi-kotlin-webmvc-tests/pom.xml b/springdoc-openapi-tests/springdoc-openapi-kotlin-webmvc-tests/pom.xml index 621449351..6083259e1 100644 --- a/springdoc-openapi-tests/springdoc-openapi-kotlin-webmvc-tests/pom.xml +++ b/springdoc-openapi-tests/springdoc-openapi-kotlin-webmvc-tests/pom.xml @@ -2,7 +2,7 @@ springdoc-openapi-tests org.springdoc - 2.8.4 + 2.8.5 4.0.0 springdoc-openapi-kotlin-webmvc-tests diff --git a/springdoc-openapi-tests/springdoc-openapi-security-tests/pom.xml b/springdoc-openapi-tests/springdoc-openapi-security-tests/pom.xml index 20a2f52a0..30183265d 100644 --- a/springdoc-openapi-tests/springdoc-openapi-security-tests/pom.xml +++ b/springdoc-openapi-tests/springdoc-openapi-security-tests/pom.xml @@ -3,7 +3,7 @@ org.springdoc springdoc-openapi-tests - 2.8.4 + 2.8.5 springdoc-openapi-security-tests