From 3ae776357005f117cab32253d13b6ba5e2a32fce Mon Sep 17 00:00:00 2001 From: Sahil Kumar <45749746+sahil-ramagiri@users.noreply.github.com> Date: Fri, 17 Jan 2025 22:39:37 +0000 Subject: [PATCH 01/19] Do not require JsonSubType annotation for sealed classes. --- .../configuration/SpringDocConfiguration.java | 2 +- .../SpringDocSealedClassModule.java | 64 +++++ .../api/v30/app238/AbstractParent.java | 66 +++++ .../api/v30/app238/ConcreteParent.java | 66 +++++ .../springdoc/api/v30/app238/Controller.java | 68 ++++++ .../api/v30/app238/SpringDocApp238Test.java | 36 +++ .../api/v30/app239/HelloController.java | 51 ++++ .../api/v30/app239/SpringDocApp239Test.java | 35 +++ .../test/resources/results/3.0.1/app238.json | 227 ++++++++++++++++++ .../test/resources/results/3.0.1/app239.json | 132 ++++++++++ 10 files changed, 746 insertions(+), 1 deletion(-) create mode 100644 springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocSealedClassModule.java create mode 100644 springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app238/AbstractParent.java create mode 100644 springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app238/ConcreteParent.java create mode 100644 springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app238/Controller.java create mode 100644 springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app238/SpringDocApp238Test.java create mode 100644 springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app239/HelloController.java create mode 100644 springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app239/SpringDocApp239Test.java create mode 100644 springdoc-openapi-starter-webmvc-api/src/test/resources/results/3.0.1/app238.json create mode 100644 springdoc-openapi-starter-webmvc-api/src/test/resources/results/3.0.1/app239.json 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..7e6bc4889 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 @@ -423,7 +423,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); } 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..37b7a7290 --- /dev/null +++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocSealedClassModule.java @@ -0,0 +1,64 @@ +/* + * + * * + * * * + * * * * 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 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; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * 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()) { + 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-webmvc-api/src/test/java/test/org/springdoc/api/v30/app238/AbstractParent.java b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app238/AbstractParent.java new file mode 100644 index 000000000..5ef6af397 --- /dev/null +++ b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app238/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.app238; + + +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/app238/ConcreteParent.java b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app238/ConcreteParent.java new file mode 100644 index 000000000..de49b5ab3 --- /dev/null +++ b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app238/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.app238; + + +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/app238/Controller.java b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app238/Controller.java new file mode 100644 index 000000000..7fa6c0302 --- /dev/null +++ b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app238/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.app238; + +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/app238/SpringDocApp238Test.java b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app238/SpringDocApp238Test.java new file mode 100644 index 000000000..396c2c68b --- /dev/null +++ b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app238/SpringDocApp238Test.java @@ -0,0 +1,36 @@ +/* + * + * * + * * * + * * * * + * * * * * 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.app238; + +import test.org.springdoc.api.v30.AbstractSpringDocV30Test; + +import org.springframework.boot.autoconfigure.SpringBootApplication; + + +public class SpringDocApp238Test extends AbstractSpringDocV30Test { + + @SpringBootApplication + static class SpringDocTestApp {} +} diff --git a/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app239/HelloController.java b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app239/HelloController.java new file mode 100644 index 000000000..8f74c1227 --- /dev/null +++ b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app239/HelloController.java @@ -0,0 +1,51 @@ +package test.org.springdoc.api.v30.app239; + + +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"; +} \ No newline at end of file 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..d80d2caa0 --- /dev/null +++ b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app239/SpringDocApp239Test.java @@ -0,0 +1,35 @@ +/* + * + * * + * * * + * * * * + * * * * * 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.app239; + +import test.org.springdoc.api.v30.AbstractSpringDocV30Test; + +import org.springframework.boot.autoconfigure.SpringBootApplication; + +public class SpringDocApp239Test extends AbstractSpringDocV30Test { + + @SpringBootApplication + static class SpringDocTestApp {} +} diff --git a/springdoc-openapi-starter-webmvc-api/src/test/resources/results/3.0.1/app238.json b/springdoc-openapi-starter-webmvc-api/src/test/resources/results/3.0.1/app238.json new file mode 100644 index 000000000..1f5dfa891 --- /dev/null +++ b/springdoc-openapi-starter-webmvc-api/src/test/resources/results/3.0.1/app238.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/app239.json b/springdoc-openapi-starter-webmvc-api/src/test/resources/results/3.0.1/app239.json new file mode 100644 index 000000000..de2244501 --- /dev/null +++ b/springdoc-openapi-starter-webmvc-api/src/test/resources/results/3.0.1/app239.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" + } + } + } + } +} From 7af67d7b8529f8f6a14d32cc7052c811cd794d4f Mon Sep 17 00:00:00 2001 From: jenkins Date: Sun, 26 Jan 2025 17:58:03 +0000 Subject: [PATCH 02/19] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- springdoc-openapi-starter-common/pom.xml | 2 +- springdoc-openapi-starter-webflux-api/pom.xml | 2 +- springdoc-openapi-starter-webflux-ui/pom.xml | 2 +- springdoc-openapi-starter-webmvc-api/pom.xml | 2 +- springdoc-openapi-starter-webmvc-ui/pom.xml | 2 +- springdoc-openapi-tests/pom.xml | 2 +- .../springdoc-openapi-actuator-webflux-tests/pom.xml | 2 +- .../springdoc-openapi-actuator-webmvc-tests/pom.xml | 2 +- .../springdoc-openapi-data-rest-tests/pom.xml | 2 +- .../springdoc-openapi-function-webflux-tests/pom.xml | 2 +- .../springdoc-openapi-function-webmvc-tests/pom.xml | 2 +- .../springdoc-openapi-groovy-tests/pom.xml | 2 +- .../springdoc-openapi-hateoas-tests/pom.xml | 2 +- .../springdoc-openapi-javadoc-tests/pom.xml | 2 +- .../springdoc-openapi-kotlin-webflux-tests/pom.xml | 2 +- .../springdoc-openapi-kotlin-webmvc-tests/pom.xml | 2 +- .../springdoc-openapi-security-tests/pom.xml | 2 +- 18 files changed, 19 insertions(+), 19 deletions(-) diff --git a/pom.xml b/pom.xml index 5f72a3e70..1858f60f0 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 org.springdoc springdoc-openapi - 2.8.4 + 2.8.5-SNAPSHOT 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 + HEAD diff --git a/springdoc-openapi-starter-common/pom.xml b/springdoc-openapi-starter-common/pom.xml index b3bdef137..d1e0147af 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-SNAPSHOT springdoc-openapi-starter-common diff --git a/springdoc-openapi-starter-webflux-api/pom.xml b/springdoc-openapi-starter-webflux-api/pom.xml index 4f18fd6b7..597105442 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-SNAPSHOT springdoc-openapi-starter-webflux-api diff --git a/springdoc-openapi-starter-webflux-ui/pom.xml b/springdoc-openapi-starter-webflux-ui/pom.xml index ac8dd0c40..30bec3793 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-SNAPSHOT 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..9af76eee2 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-SNAPSHOT springdoc-openapi-starter-webmvc-api diff --git a/springdoc-openapi-starter-webmvc-ui/pom.xml b/springdoc-openapi-starter-webmvc-ui/pom.xml index f16b12bfa..ddc50f627 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-SNAPSHOT springdoc-openapi-starter-webmvc-ui diff --git a/springdoc-openapi-tests/pom.xml b/springdoc-openapi-tests/pom.xml index 5ffc3b88e..0625c0801 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-SNAPSHOT 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..a8c4d1846 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-SNAPSHOT 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..cc666c836 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-SNAPSHOT 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..b44366a3d 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-SNAPSHOT 4.0.0 springdoc-openapi-data-rest-tests 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..b4f77c4af 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-SNAPSHOT 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..ecd4ad9e1 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-SNAPSHOT 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..49bbfe98d 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-SNAPSHOT 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..7dd6dfef0 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-SNAPSHOT 4.0.0 springdoc-openapi-hateoas-tests diff --git a/springdoc-openapi-tests/springdoc-openapi-javadoc-tests/pom.xml b/springdoc-openapi-tests/springdoc-openapi-javadoc-tests/pom.xml index a89128c99..40fe4a564 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-SNAPSHOT 4.0.0 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..96c136a14 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-SNAPSHOT 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..608b5f83f 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-SNAPSHOT 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..bcde807d2 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-SNAPSHOT springdoc-openapi-security-tests From 38b78d6ee7a110850127bff56e9fe1c81ee2c286 Mon Sep 17 00:00:00 2001 From: Petar Heyken Date: Fri, 31 Jan 2025 11:00:34 +0100 Subject: [PATCH 03/19] add test with expected result --- .../api/v31/app14/HelloController.java | 11 +++- .../test/resources/results/3.1.0/app14.json | 60 +++++++++++++++++++ 2 files changed, 70 insertions(+), 1 deletion(-) 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.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": [ From 281c896f725542ab2b73d80a45d8e667e9245325 Mon Sep 17 00:00:00 2001 From: Petar Heyken Date: Fri, 31 Jan 2025 11:22:27 +0100 Subject: [PATCH 04/19] fix defaultValue when using @PageableDefault together with one-indexed-parameters --- .../DataRestDelegatingMethodParameterCustomizer.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) 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 From 665d72356b6ed57c10e627e883d74c736127b8a9 Mon Sep 17 00:00:00 2001 From: ryan-dia Date: Thu, 6 Feb 2025 22:59:34 +0900 Subject: [PATCH 05/19] Refactor trimIndent method: streamline indentation removal and handle exceptions gracefully --- .../core/utils/PropertyResolverUtils.java | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) 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..6eff3e174 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; @@ -119,18 +120,17 @@ public String resolve(String parameterProperty, Locale locale) { * @return The string with leading indentation removed from each line. */ 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 +239,4 @@ public Map resolveExtensions(Locale locale, Map else return extensions; } -} \ No newline at end of file +} From f72a7fb2496454102bea366b9c1855764dc26790 Mon Sep 17 00:00:00 2001 From: ryan-dia Date: Thu, 6 Feb 2025 23:40:45 +0900 Subject: [PATCH 06/19] Improve documentation for trimIndent: add details on null input and return values --- .../org/springdoc/core/utils/PropertyResolverUtils.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) 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 6eff3e174..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 @@ -115,9 +115,11 @@ 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) { From a9f338c2740cb32f9372d2e3f3ca6f97f6492549 Mon Sep 17 00:00:00 2001 From: "Badr.NassLahsen" Date: Thu, 6 Feb 2025 23:55:01 +0100 Subject: [PATCH 07/19] Sponsorship issue. Fixes #2892 --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 180f3d560..117c32a85 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,9 @@ This project is sponsored by + + +

# Table of Contents From 296beedff22a0dcfcfc6df08bed48f72a2d1121d Mon Sep 17 00:00:00 2001 From: "Badr.NassLahsen" Date: Sat, 8 Feb 2025 13:41:40 +0100 Subject: [PATCH 08/19] Provide a better consistency for parameters and responses. Fixes #2888 --- .../QuerydslPredicateOperationCustomizer.java | 3 +- .../data/DataRestRouterOperationService.java | 5 ++- .../MethodParameterPojoExtractor.java | 3 +- .../properties/SwaggerUiConfigProperties.java | 3 +- .../core/service/GenericResponseService.java | 5 ++- .../core/service/OpenAPIService.java | 11 ++--- .../core/providers/SpringWebFluxProvider.java | 3 +- .../api/v30/app233/SpringDocApp233Test.java | 3 +- .../api/v31/app233/SpringDocApp233Test.java | 3 +- .../test/resources/results/3.0.1/app126.json | 12 +++--- .../test/resources/results/3.1.0/app126.json | 20 +++++----- .../test/resources/results/3.0.1/app24.json | 32 +++++++-------- .../test/resources/results/3.0.1/app30.json | 6 +-- .../test/resources/results/3.0.1/app5.json | 26 ++++++------ .../test/resources/results/3.1.0/app24.json | 40 +++++++++---------- .../test/resources/results/3.1.0/app30.json | 6 +-- .../test/resources/results/3.1.0/app5.json | 26 ++++++------ .../test/resources/results/3.0.1/app126.json | 22 +++++----- .../test/resources/results/3.1.0/app126.json | 34 ++++++++-------- 19 files changed, 136 insertions(+), 127 deletions(-) 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/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-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-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/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/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.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-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/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-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": { From 28c66e13da5ece50d2c154910ac3c36d7f3bcd3f Mon Sep 17 00:00:00 2001 From: "Badr.NassLahsen" Date: Sat, 8 Feb 2025 13:42:46 +0100 Subject: [PATCH 09/19] upgrade swagger-ui to v5.18.3 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 1858f60f0..0928cf38e 100644 --- a/pom.xml +++ b/pom.xml @@ -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 From 7060d3a11dff7dcfff4af3f74e62aa8f95c6fccf Mon Sep 17 00:00:00 2001 From: Illia Ovchynnikov Date: Sat, 8 Feb 2025 17:41:47 +0100 Subject: [PATCH 10/19] fix: respect @JsonUnwrapped & @Schema on props not fields only --- .../converters/PolymorphicModelConverter.java | 25 ++++++--- .../springdoc/api/v30/app239/RootModel.java | 27 ++++++++++ .../api/v30/app239/SpringDocApp239Test.java | 34 ++++++++++++ .../api/v30/app239/TestController.java | 15 ++++++ .../api/v30/app239/UnwrappedModel.java | 14 +++++ .../springdoc/api/v31/app224/RootModel.java | 2 +- .../springdoc/api/v31/app239/RootModel.java | 27 ++++++++++ .../api/v31/app239/SpringDocApp239Test.java | 34 ++++++++++++ .../api/v31/app239/TestController.java | 15 ++++++ .../api/v31/app239/UnwrappedModel.java | 14 +++++ .../test/resources/results/3.0.1/app239.json | 52 +++++++++++++++++++ .../test/resources/results/3.1.0/app239.json | 52 +++++++++++++++++++ 12 files changed, 304 insertions(+), 7 deletions(-) create mode 100644 springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app239/RootModel.java create mode 100644 springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app239/SpringDocApp239Test.java create mode 100644 springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app239/TestController.java create mode 100644 springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app239/UnwrappedModel.java create mode 100644 springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v31/app239/RootModel.java create mode 100644 springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v31/app239/SpringDocApp239Test.java create mode 100644 springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v31/app239/TestController.java create mode 100644 springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v31/app239/UnwrappedModel.java create mode 100644 springdoc-openapi-starter-webmvc-api/src/test/resources/results/3.0.1/app239.json create mode 100644 springdoc-openapi-starter-webmvc-api/src/test/resources/results/3.1.0/app239.json 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-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/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/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/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.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" + } + } + } + } + } +} From 7d4820eea14190e39f49e9dc3d1ba5413a17d273 Mon Sep 17 00:00:00 2001 From: Michael Clarke Date: Sat, 8 Feb 2025 20:31:07 +0000 Subject: [PATCH 11/19] Only filter out actuator endpoints with double asterisks. Fixes #2895 All endpoints that contain a double-asterisks in the path are currently being excluded from the output Swagger definition, rather than just excluding match-all actuator endpoints. The endpoint matching is therefore being altered to pre-filter the actuator endpoints to remove any that contain a double-asterisks in the path, and remove the subsequent filtering of double asterisks in the combined endpoints list so that non-actuator endpoints aren't dropped by the actuator filtering. --- .../api/AbstractOpenApiResource.java | 3 +- .../springdoc/webmvc/api/OpenApiResource.java | 5 +++ .../api/v31/app240/SpringDocApp240Test.java | 31 ++++++++++++++++ .../api/v31/app240/WildcardController.java | 34 +++++++++++++++++ .../test/resources/results/3.1.0/app240.json | 37 +++++++++++++++++++ 5 files changed, 108 insertions(+), 2 deletions(-) create mode 100644 springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v31/app240/SpringDocApp240Test.java create mode 100644 springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v31/app240/WildcardController.java create mode 100644 springdoc-openapi-starter-webmvc-api/src/test/resources/results/3.1.0/app240.json 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-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/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..672be887b --- /dev/null +++ b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v31/app240/SpringDocApp240Test.java @@ -0,0 +1,31 @@ +/* + * + * * 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..98df2ccbb --- /dev/null +++ b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v31/app240/WildcardController.java @@ -0,0 +1,34 @@ +/* + * + * * 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/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..5a7391872 --- /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 From a9a2a2c2f01debb3851c489141ea33b11300eb3b Mon Sep 17 00:00:00 2001 From: lorenzbaier <64407215+lorenzbaier@users.noreply.github.com> Date: Tue, 11 Feb 2025 08:25:14 +0100 Subject: [PATCH 12/19] add needed runtime reflection hints for native image --- .../org/springdoc/core/configuration/hints/SpringDocHints.java | 3 +++ 1 file changed, 3 insertions(+) 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, From cce8e8b14ae3a7209334fa00619e905ba3111345 Mon Sep 17 00:00:00 2001 From: "Badr.NassLahsen" Date: Tue, 11 Feb 2025 21:57:40 +0100 Subject: [PATCH 13/19] img size update --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 117c32a85..5b3618093 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ This project is sponsored by - +

From 0775180535a0b7f1fcd6b1f7c18100689ed1c1a0 Mon Sep 17 00:00:00 2001 From: "Badr.NassLahsen" Date: Sat, 15 Feb 2025 20:51:34 +0100 Subject: [PATCH 14/19] Restentpoints with same name get mix up. Fixes #2876 --- .../configuration/SpringDocConfiguration.java | 3 +- .../SpringDocHateoasConfiguration.java | 4 +- .../customizers/SpringDocCustomizers.java | 6 +- .../org/springdoc/core/utils/Constants.java | 7 +- .../SpringDocHateoasConfigurationTest.java | 16 +- .../api/v31/app240/DemoRestController.java | 48 ++++++ .../api/v31/app240/OpenApiConfig.java | 33 ++++ .../api/v31/app240/SpringDocApp240Test.java | 39 +++++ .../test/resources/results/3.1.0/app240.json | 151 ++++++++++++++++++ 9 files changed, 292 insertions(+), 15 deletions(-) create mode 100644 springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v31/app240/DemoRestController.java create mode 100644 springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v31/app240/OpenApiConfig.java create mode 100644 springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v31/app240/SpringDocApp240Test.java create mode 100644 springdoc-openapi-starter-webmvc-api/src/test/resources/results/3.1.0/app240.json 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..ca30d9355 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; @@ -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/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/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/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-webmvc-api/src/test/java/test/org/springdoc/api/v31/app240/DemoRestController.java b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v31/app240/DemoRestController.java new file mode 100644 index 000000000..0a223c4e7 --- /dev/null +++ b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v31/app240/DemoRestController.java @@ -0,0 +1,48 @@ +package test.org.springdoc.api.v31.app240; + +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/app240/OpenApiConfig.java b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v31/app240/OpenApiConfig.java new file mode 100644 index 000000000..66bce186a --- /dev/null +++ b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v31/app240/OpenApiConfig.java @@ -0,0 +1,33 @@ +package test.org.springdoc.api.v31.app240; + +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/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..34b0c2a37 --- /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; +import org.springframework.test.context.TestPropertySource; + +@TestPropertySource(properties = "springdoc.api-docs.resolve-schema-properties=true" ) +public class SpringDocApp240Test extends AbstractSpringDocTest { + + @SpringBootApplication + static class SpringDocTestApp {} +} 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..0a9af7bf9 --- /dev/null +++ b/springdoc-openapi-starter-webmvc-api/src/test/resources/results/3.1.0/app240.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": {} +} From cdfaf63895773dd389027f8c5ad152abb326405f Mon Sep 17 00:00:00 2001 From: "Badr.NassLahsen" Date: Sat, 15 Feb 2025 21:01:08 +0100 Subject: [PATCH 15/19] Restentpoints with same name get mix up. Fixes #2876 --- .../api/v31/app240/SpringDocApp240Test.java | 39 +++++++++++++++++ .../api/v31/app240/WildcardController.java | 42 +++++++++++++++++++ .../test/resources/results/3.1.0/app240.json | 37 ++++++++++++++++ .../test/resources/results/3.1.0/app241.json | 39 ----------------- 4 files changed, 118 insertions(+), 39 deletions(-) create mode 100644 springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v31/app240/SpringDocApp240Test.java create mode 100644 springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v31/app240/WildcardController.java create mode 100644 springdoc-openapi-starter-webmvc-api/src/test/resources/results/3.1.0/app240.json 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/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 index 0ccd3b537..0a9af7bf9 100644 --- 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 @@ -1,5 +1,4 @@ { -<<<<<<< HEAD "openapi": "3.1.0", "info": { "title": "OpenAPI definition", @@ -150,41 +149,3 @@ }, "components": {} } -======= - "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": {} -} ->>>>>>> origin/main From a329910010b6186b894debdefed3c55bbd638377 Mon Sep 17 00:00:00 2001 From: "Badr.NassLahsen" Date: Sun, 16 Feb 2025 13:47:45 +0100 Subject: [PATCH 16/19] Schema replaced by String when using @ApiResponse with RepresentationModel (Hateoas links). Fixes #2902 --- .../converters/HateoasLinksConverter.java | 38 ++++-- .../api/v31/app11/SpringDocApp11Test.java | 39 ++++++ .../configuration/WebMvcConfiguration.java | 25 ++++ .../app11/controllers/BasicController.java | 41 ++++++ .../CustomOpenApiWebMvcResource.java | 27 ++++ .../springdoc/api/v31/app11/model/Cat.java | 24 ++++ .../test/resources/results/3.1.0/app11.json | 126 ++++++++++++++++++ 7 files changed, 307 insertions(+), 13 deletions(-) create mode 100644 springdoc-openapi-tests/springdoc-openapi-hateoas-tests/src/test/java/test/org/springdoc/api/v31/app11/SpringDocApp11Test.java create mode 100644 springdoc-openapi-tests/springdoc-openapi-hateoas-tests/src/test/java/test/org/springdoc/api/v31/app11/configuration/WebMvcConfiguration.java create mode 100644 springdoc-openapi-tests/springdoc-openapi-hateoas-tests/src/test/java/test/org/springdoc/api/v31/app11/controllers/BasicController.java create mode 100644 springdoc-openapi-tests/springdoc-openapi-hateoas-tests/src/test/java/test/org/springdoc/api/v31/app11/controllers/CustomOpenApiWebMvcResource.java create mode 100644 springdoc-openapi-tests/springdoc-openapi-hateoas-tests/src/test/java/test/org/springdoc/api/v31/app11/model/Cat.java create mode 100644 springdoc-openapi-tests/springdoc-openapi-hateoas-tests/src/test/resources/results/3.1.0/app11.json 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-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" + } + } + } + } +} From f4e632b5c51c4a700db02179ec44c9b5b39e022e Mon Sep 17 00:00:00 2001 From: "Badr.NassLahsen" Date: Sun, 16 Feb 2025 14:29:51 +0100 Subject: [PATCH 17/19] Do not require JsonSubType annotation for sealed classes #2696 --- .../configuration/SpringDocSealedClassModule.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) 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 index 37b7a7290..d0b27ad81 100644 --- 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 @@ -22,13 +22,14 @@ 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; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; /** * The type Spring doc sealed class module. @@ -51,7 +52,10 @@ private static class RespectSealedClassAnnotationIntrospector extends SwaggerAnn public List findSubtypes(Annotated annotated) { ArrayList subTypes = new ArrayList<>(); - if (annotated.getAnnotated() instanceof Class clazz && clazz.isSealed()) { + 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); From 21869843f3c761e4bfe11468f18ff601a6548bfd Mon Sep 17 00:00:00 2001 From: "Badr.NassLahsen" Date: Sun, 16 Feb 2025 14:49:47 +0100 Subject: [PATCH 18/19] CHANGELOG.md update for 2.8.5 --- CHANGELOG.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) 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 From 9006225a449c9532a1dd6ef8a4fd428b0c6f95e8 Mon Sep 17 00:00:00 2001 From: jenkins Date: Sun, 16 Feb 2025 14:06:19 +0000 Subject: [PATCH 19/19] [maven-release-plugin] prepare release v2.8.5 --- pom.xml | 4 ++-- springdoc-openapi-starter-common/pom.xml | 2 +- springdoc-openapi-starter-webflux-api/pom.xml | 2 +- springdoc-openapi-starter-webflux-ui/pom.xml | 2 +- springdoc-openapi-starter-webmvc-api/pom.xml | 2 +- springdoc-openapi-starter-webmvc-ui/pom.xml | 2 +- springdoc-openapi-tests/pom.xml | 2 +- .../springdoc-openapi-actuator-webflux-tests/pom.xml | 2 +- .../springdoc-openapi-actuator-webmvc-tests/pom.xml | 2 +- .../springdoc-openapi-data-rest-tests/pom.xml | 2 +- .../springdoc-openapi-function-webflux-tests/pom.xml | 2 +- .../springdoc-openapi-function-webmvc-tests/pom.xml | 2 +- .../springdoc-openapi-groovy-tests/pom.xml | 2 +- .../springdoc-openapi-hateoas-tests/pom.xml | 2 +- .../springdoc-openapi-javadoc-tests/pom.xml | 2 +- .../springdoc-openapi-kotlin-webflux-tests/pom.xml | 2 +- .../springdoc-openapi-kotlin-webmvc-tests/pom.xml | 2 +- .../springdoc-openapi-security-tests/pom.xml | 2 +- 18 files changed, 19 insertions(+), 19 deletions(-) diff --git a/pom.xml b/pom.xml index 0928cf38e..dcda74974 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 org.springdoc springdoc-openapi - 2.8.5-SNAPSHOT + 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 - HEAD + v2.8.5 diff --git a/springdoc-openapi-starter-common/pom.xml b/springdoc-openapi-starter-common/pom.xml index d1e0147af..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.5-SNAPSHOT + 2.8.5 springdoc-openapi-starter-common diff --git a/springdoc-openapi-starter-webflux-api/pom.xml b/springdoc-openapi-starter-webflux-api/pom.xml index 597105442..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.5-SNAPSHOT + 2.8.5 springdoc-openapi-starter-webflux-api diff --git a/springdoc-openapi-starter-webflux-ui/pom.xml b/springdoc-openapi-starter-webflux-ui/pom.xml index 30bec3793..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.5-SNAPSHOT + 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 9af76eee2..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.5-SNAPSHOT + 2.8.5 springdoc-openapi-starter-webmvc-api diff --git a/springdoc-openapi-starter-webmvc-ui/pom.xml b/springdoc-openapi-starter-webmvc-ui/pom.xml index ddc50f627..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.5-SNAPSHOT + 2.8.5 springdoc-openapi-starter-webmvc-ui diff --git a/springdoc-openapi-tests/pom.xml b/springdoc-openapi-tests/pom.xml index 0625c0801..9c8e6964b 100644 --- a/springdoc-openapi-tests/pom.xml +++ b/springdoc-openapi-tests/pom.xml @@ -2,7 +2,7 @@ springdoc-openapi org.springdoc - 2.8.5-SNAPSHOT + 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 a8c4d1846..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.5-SNAPSHOT + 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 cc666c836..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.5-SNAPSHOT + 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 b44366a3d..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.5-SNAPSHOT + 2.8.5 4.0.0 springdoc-openapi-data-rest-tests 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 b4f77c4af..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.5-SNAPSHOT + 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 ecd4ad9e1..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.5-SNAPSHOT + 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 49bbfe98d..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.5-SNAPSHOT + 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 7dd6dfef0..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.5-SNAPSHOT + 2.8.5 4.0.0 springdoc-openapi-hateoas-tests diff --git a/springdoc-openapi-tests/springdoc-openapi-javadoc-tests/pom.xml b/springdoc-openapi-tests/springdoc-openapi-javadoc-tests/pom.xml index 40fe4a564..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.5-SNAPSHOT + 2.8.5 4.0.0 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 96c136a14..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.5-SNAPSHOT + 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 608b5f83f..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.5-SNAPSHOT + 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 bcde807d2..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.5-SNAPSHOT + 2.8.5 springdoc-openapi-security-tests