From fcf98fc18c23d35825176a7781dbdbba2cb0ce9a Mon Sep 17 00:00:00 2001 From: MicRyc Date: Tue, 3 Sep 2024 10:19:37 +0200 Subject: [PATCH 01/25] refs #4715 - change JsonSchemaDialect to one accepted by Swagger-UI --- .../src/main/java/io/swagger/v3/core/util/OpenAPI30To31.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/swagger-core/src/main/java/io/swagger/v3/core/util/OpenAPI30To31.java b/modules/swagger-core/src/main/java/io/swagger/v3/core/util/OpenAPI30To31.java index 967ccf02fa..e2cc8fafc9 100644 --- a/modules/swagger-core/src/main/java/io/swagger/v3/core/util/OpenAPI30To31.java +++ b/modules/swagger-core/src/main/java/io/swagger/v3/core/util/OpenAPI30To31.java @@ -10,7 +10,7 @@ public class OpenAPI30To31 { public void process(OpenAPI openAPI) { openAPI.openapi("3.1.0") - .jsonSchemaDialect("https://json-schema.org/draft/2020-12/schema") + .jsonSchemaDialect("https://spec.openapis.org/oas/3.1/dialect/base") .specVersion(SpecVersion.V31); removeReservedExtensionsName(openAPI.getExtensions()); From 6c95bfbd0929e308bf859c5be139e43ec6f70017 Mon Sep 17 00:00:00 2001 From: MicRyc Date: Tue, 10 Sep 2024 13:44:27 +0200 Subject: [PATCH 02/25] Add support for OAS 3.1 schema.types processing to make top level type: object visible in generated spec --- .../v3/core/jackson/ModelResolver.java | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/ModelResolver.java b/modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/ModelResolver.java index 66634f693f..2624ed42d4 100644 --- a/modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/ModelResolver.java +++ b/modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/ModelResolver.java @@ -536,18 +536,24 @@ public Schema resolve(AnnotatedType annotatedType, ModelConverterContext context } } } else if (isComposedSchema) { - model = new ComposedSchema() - .type("object") - .name(name); + model = new ComposedSchema().name(name); + if (openapi31 && resolvedArrayAnnotation == null){ + model.addType("object"); + }else{ + model.type("object"); + } } else { AnnotatedType aType = ReferenceTypeUtils.unwrapReference(annotatedType); if (aType != null) { model = context.resolve(aType); return model; } else { - model = new Schema() - .type("object") - .name(name); + model = new Schema().name(name); + if (openapi31 && resolvedArrayAnnotation == null){ + model.addType("object"); + }else{ + model.type("object"); + } } } @@ -2980,7 +2986,7 @@ public void setOpenapi31(boolean openapi31) { } protected boolean isObjectSchema(Schema schema) { - return "object".equals(schema.getType()) || (schema.getType() == null && schema.getProperties() != null && !schema.getProperties().isEmpty()); + return (schema.getTypes() != null && schema.getTypes().contains("object")) || "object".equals(schema.getType()) || (schema.getType() == null && schema.getProperties() != null && !schema.getProperties().isEmpty()); } protected Schema buildRefSchemaIfObject(Schema schema, ModelConverterContext context) { From 16d403ec84af034b99e8e53701c88a317c2fe800 Mon Sep 17 00:00:00 2001 From: MicRyc Date: Tue, 10 Sep 2024 14:16:50 +0200 Subject: [PATCH 03/25] Add tests for ModelResolver / fix existing tests --- .../v3/core/resolving/Ticket4679Test.java | 1 + .../resolving/resources/TestArrayType.java | 30 +++++++++++++ .../resolving/resources/TestObject4715.java | 34 ++++++++++++++ .../resolving/v31/ModelResolverOAS31Test.java | 44 +++++++++++++++++++ .../java/io/swagger/v3/jaxrs2/ReaderTest.java | 26 ++++++++++- .../resources/petstore/WebHookResource.yaml | 1 + .../callbacks/ComplexCallback31Resource.yaml | 1 + .../parameters/Parameters31Resource.yaml | 7 ++- .../requestbody/RequestBody31Resource.yaml | 1 + 9 files changed, 143 insertions(+), 2 deletions(-) create mode 100644 modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/resources/TestArrayType.java create mode 100644 modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/resources/TestObject4715.java diff --git a/modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/Ticket4679Test.java b/modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/Ticket4679Test.java index 9998f8b6a2..8c51838b3a 100644 --- a/modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/Ticket4679Test.java +++ b/modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/Ticket4679Test.java @@ -15,6 +15,7 @@ public class Ticket4679Test extends SwaggerTestBase{ public void testCustomSchemaImplementation() { String expectedYaml = "ModelWithCustomSchemaImplementationInProperty:\n" + + " type: object\n" + " properties:\n" + " exampleField:\n" + " type: integer\n" + diff --git a/modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/resources/TestArrayType.java b/modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/resources/TestArrayType.java new file mode 100644 index 0000000000..3c180c22b7 --- /dev/null +++ b/modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/resources/TestArrayType.java @@ -0,0 +1,30 @@ +package io.swagger.v3.core.resolving.resources; + +import io.swagger.v3.oas.annotations.media.ArraySchema; + +import java.util.ArrayList; +import java.util.List; + +public class TestArrayType { + + private Integer id; + + @ArraySchema(maxItems = 10) + private List names; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public List getNames() { + return names; + } + + public void setNames(List names) { + this.names = names; + } +} diff --git a/modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/resources/TestObject4715.java b/modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/resources/TestObject4715.java new file mode 100644 index 0000000000..f3e9914135 --- /dev/null +++ b/modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/resources/TestObject4715.java @@ -0,0 +1,34 @@ +package io.swagger.v3.core.resolving.resources; + +public class TestObject4715 { + + private String foo; + + private String bar; + + private Integer id; + + public String getFoo() { + return foo; + } + + public void setFoo(String foo) { + this.foo = foo; + } + + public String getBar() { + return bar; + } + + public void setBar(String bar) { + this.bar = bar; + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } +} diff --git a/modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/v31/ModelResolverOAS31Test.java b/modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/v31/ModelResolverOAS31Test.java index f9aa3ce83c..8b5ce8b67a 100644 --- a/modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/v31/ModelResolverOAS31Test.java +++ b/modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/v31/ModelResolverOAS31Test.java @@ -5,6 +5,8 @@ import io.swagger.v3.core.jackson.ModelResolver; import io.swagger.v3.core.matchers.SerializationMatchers; import io.swagger.v3.core.resolving.SwaggerTestBase; +import io.swagger.v3.core.resolving.resources.TestArrayType; +import io.swagger.v3.core.resolving.resources.TestObject4715; import io.swagger.v3.core.resolving.v31.model.AnnotatedArray; import io.swagger.v3.core.resolving.v31.model.ModelWithDependentSchema; import io.swagger.v3.core.resolving.v31.model.ModelWithOAS31Stuff; @@ -39,6 +41,7 @@ public void testOAS31Fields() { final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); Schema model = context.resolve(new AnnotatedType(ModelWithOAS31Stuff.class)); SerializationMatchers.assertEqualsToYaml31(context.getDefinedModels(), "Address:\n" + + " type: object\n" + " if:\n" + " $ref: '#/components/schemas/AnnotatedCountry'\n" + " then:\n" + @@ -59,10 +62,12 @@ public void testOAS31Fields() { " propertyNames:\n" + " $ref: '#/components/schemas/PropertyNamesPattern'\n" + "AnnotatedCountry:\n" + + " type: object\n" + " properties:\n" + " country:\n" + " const: United States\n" + "Client:\n" + + " type: object\n" + " properties:\n" + " name:\n" + " type: string\n" + @@ -70,6 +75,7 @@ public void testOAS31Fields() { " type: integer\n" + " format: int32\n" + "CreditCard:\n" + + " type: object\n" + " properties:\n" + " billingAddress:\n" + " type: string\n" + @@ -124,6 +130,7 @@ public void testOAS31Fields() { " properties:\n" + " extraObject: {}\n" + "MultipleBaseBean:\n" + + " type: object\n" + " description: MultipleBaseBean\n" + " properties:\n" + " beanType:\n" + @@ -152,14 +159,17 @@ public void testOAS31Fields() { " format: int32\n" + " description: MultipleSub2Bean\n" + "PostalCodeNumberPattern:\n" + + " type: object\n" + " properties:\n" + " postalCode:\n" + " pattern: \"[0-9]{5}(-[0-9]{4})?\"\n" + "PostalCodePattern:\n" + + " type: object\n" + " properties:\n" + " postalCode:\n" + " pattern: \"[A-Z][0-9][A-Z] [0-9][A-Z][0-9]\"\n" + "PropertyNamesPattern:\n" + + " type: object\n" + " pattern: \"^[A-Za-z_][A-Za-z0-9_]*$\"\n"); } @@ -170,10 +180,12 @@ public void testDependentSchemasAnnotation() { io.swagger.v3.oas.models.media.Schema model = context.resolve(new AnnotatedType(ModelWithDependentSchema.class)); SerializationMatchers.assertEqualsToYaml31(context.getDefinedModels(), "BooleanFakeClass:\n" + + " type: object\n" + " properties:\n" + " type:\n" + " type: boolean\n" + "ModelWithDependentSchema:\n" + + " type: object\n" + " dependentSchemas:\n" + " value:\n" + " properties:\n" + @@ -187,4 +199,36 @@ public void testDependentSchemasAnnotation() { " format: int32\n"); } + @Test(description = "Top level type:object should appear in OAS31") + public void testObjectTypeSchemaOAS31(){ + final ModelResolver modelResolver = new ModelResolver(mapper()).openapi31(true); + final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); + io.swagger.v3.oas.models.media.Schema model = context.resolve(new AnnotatedType(TestObject4715.class)); + SerializationMatchers.assertEqualsToYaml31(model, "type: object\n" + + "properties:\n" + + " foo:\n" + + " type: string\n" + + " bar:\n" + + " type: string\n" + + " id:\n" + + " type: integer\n" + + " format: int32"); + } + + @Test + public void testFieldArraySchemaAnnotation() { + final ModelResolver modelResolver = new ModelResolver(mapper()).openapi31(true); + final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); + io.swagger.v3.oas.models.media.Schema model = context.resolve(new AnnotatedType(TestArrayType.class)); + SerializationMatchers.assertEqualsToYaml31(model, " type: object\n" + + " properties:\n" + + " id:\n" + + " type: integer\n" + + " format: int32\n" + + " names:\n" + + " type: array\n" + + " items:\n" + + " type: string\n" + + " maxItems: 10"); + } } diff --git a/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/ReaderTest.java b/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/ReaderTest.java index 0f32a4dd30..53a27ce435 100644 --- a/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/ReaderTest.java +++ b/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/ReaderTest.java @@ -3378,6 +3378,7 @@ public void testOas31Petstore() { "components:\n" + " schemas:\n" + " Bar:\n" + + " type: object\n" + " deprecated: true\n" + " description: Bar\n" + " properties:\n" + @@ -3394,6 +3395,7 @@ public void testOas31Petstore() { " - string\n" + " format: int32\n" + " Category:\n" + + " type: object\n" + " properties:\n" + " id:\n" + " type: integer\n" + @@ -3403,6 +3405,7 @@ public void testOas31Petstore() { " xml:\n" + " name: Category\n" + " Foo:\n" + + " type: object\n" + " deprecated: true\n" + " description: Foo\n" + " properties:\n" + @@ -3420,6 +3423,7 @@ public void testOas31Petstore() { " - object\n" + " format: int32\n" + " IfSchema:\n" + + " type: object\n" + " deprecated: true\n" + " description: if schema\n" + " properties:\n" + @@ -3437,6 +3441,7 @@ public void testOas31Petstore() { " - object\n" + " format: int32\n" + " Pet:\n" + + " type: object\n" + " properties:\n" + " id:\n" + " type: integer\n" + @@ -3470,6 +3475,7 @@ public void testOas31Petstore() { " xml:\n" + " name: Pet\n" + " Tag:\n" + + " type: object\n" + " properties:\n" + " id:\n" + " type: integer\n" + @@ -3510,6 +3516,7 @@ public void test31RefSiblings() { "components:\n" + " schemas:\n" + " Foo:\n" + + " type: object\n" + " deprecated: true\n" + " description: Foo\n" + " properties:\n" + @@ -3527,6 +3534,7 @@ public void test31RefSiblings() { " - object\n" + " format: int32\n" + " SimpleTag:\n" + + " type: object\n" + " properties:\n" + " annotated:\n" + " $ref: '#/components/schemas/SimpleCategory'\n" + @@ -3534,7 +3542,8 @@ public void test31RefSiblings() { " properties:\n" + " foo:\n" + " $ref: '#/components/schemas/Foo'\n" + - " SimpleCategory: {}\n"; + " SimpleCategory:\n" + + " type: object\n" ; SerializationMatchers.assertEqualsToYaml31(openAPI, yaml); } @@ -3558,12 +3567,14 @@ public void testSiblings() { "components:\n" + " schemas:\n" + " Category:\n" + + " type: object\n" + " description: parent\n" + " properties:\n" + " id:\n" + " type: integer\n" + " format: int64\n" + " Pet:\n" + + " type: object\n" + " description: Pet\n" + " properties:\n" + " category:\n" + @@ -3606,6 +3617,7 @@ public void testSiblingsOnResource() { "components:\n" + " schemas:\n" + " PetSimple:\n" + + " type: object\n" + " description: Pet\n"; SerializationMatchers.assertEqualsToYaml31(openAPI, yaml); } @@ -3654,6 +3666,7 @@ public void testSiblingsOnResourceResponse() { "components:\n" + " schemas:\n" + " PetSimple:\n" + + " type: object\n" + " description: Pet\n"; SerializationMatchers.assertEqualsToYaml31(openAPI, yaml); } @@ -3699,6 +3712,7 @@ public void testSiblingsOnResourceRequestBody() { "components:\n" + " schemas:\n" + " PetSimple:\n" + + " type: object\n" + " description: Pet\n"; SerializationMatchers.assertEqualsToYaml31(openAPI, yaml); } @@ -3775,6 +3789,7 @@ public void testSiblingsOnResourceRequestBodyMultiple() { "components:\n" + " schemas:\n" + " PetSimple:\n" + + " type: object\n" + " description: Pet\n"; SerializationMatchers.assertEqualsToYaml31(openAPI, yaml); } @@ -3838,12 +3853,14 @@ public void testSiblingsOnProperty() { "components:\n" + " schemas:\n" + " Category:\n" + + " type: object\n" + " description: parent\n" + " properties:\n" + " id:\n" + " type: integer\n" + " format: int64\n" + " Pet:\n" + + " type: object\n" + " description: Pet\n" + " properties:\n" + " category:\n" + @@ -3934,6 +3951,7 @@ public void testMisc31() { " creditCard:\n" + " $ref: '#/components/schemas/CreditCard'\n" + " MultipleBaseBean:\n" + + " type: object\n" + " description: MultipleBaseBean\n" + " properties:\n" + " beanType:\n" + @@ -3962,6 +3980,7 @@ public void testMisc31() { " format: int32\n" + " description: MultipleSub2Bean\n" + " Address:\n" + + " type: object\n" + " if:\n" + " $ref: '#/components/schemas/AnnotatedCountry'\n" + " then:\n" + @@ -3982,22 +4001,27 @@ public void testMisc31() { " propertyNames:\n" + " $ref: '#/components/schemas/PropertyNamesPattern'\n" + " AnnotatedCountry:\n" + + " type: object\n" + " properties:\n" + " country:\n" + " const: United States\n" + " CreditCard:\n" + + " type: object\n" + " properties:\n" + " billingAddress:\n" + " type: string\n" + " PostalCodeNumberPattern:\n" + + " type: object\n" + " properties:\n" + " postalCode:\n" + " pattern: \"[0-9]{5}(-[0-9]{4})?\"\n" + " PostalCodePattern:\n" + + " type: object\n" + " properties:\n" + " postalCode:\n" + " pattern: \"[A-Z][0-9][A-Z] [0-9][A-Z][0-9]\"\n" + " PropertyNamesPattern:\n" + + " type: object\n" + " pattern: \"^[A-Za-z_][A-Za-z0-9_]*$\"\n"; SerializationMatchers.assertEqualsToYaml31(openAPI, yaml); } diff --git a/modules/swagger-jaxrs2/src/test/resources/petstore/WebHookResource.yaml b/modules/swagger-jaxrs2/src/test/resources/petstore/WebHookResource.yaml index 34ed3ea8f9..8569aafe81 100644 --- a/modules/swagger-jaxrs2/src/test/resources/petstore/WebHookResource.yaml +++ b/modules/swagger-jaxrs2/src/test/resources/petstore/WebHookResource.yaml @@ -2,6 +2,7 @@ openapi: 3.1.0 components: schemas: SubscriptionResponse: + type: object properties: subscriptionId: type: string diff --git a/modules/swagger-jaxrs2/src/test/resources/petstore/callbacks/ComplexCallback31Resource.yaml b/modules/swagger-jaxrs2/src/test/resources/petstore/callbacks/ComplexCallback31Resource.yaml index 3fe539678e..65b5cec4f2 100644 --- a/modules/swagger-jaxrs2/src/test/resources/petstore/callbacks/ComplexCallback31Resource.yaml +++ b/modules/swagger-jaxrs2/src/test/resources/petstore/callbacks/ComplexCallback31Resource.yaml @@ -50,6 +50,7 @@ paths: components: schemas: User: + type: object properties: id: type: integer diff --git a/modules/swagger-jaxrs2/src/test/resources/petstore/parameters/Parameters31Resource.yaml b/modules/swagger-jaxrs2/src/test/resources/petstore/parameters/Parameters31Resource.yaml index 3cb83e1350..e6b22d1bcc 100644 --- a/modules/swagger-jaxrs2/src/test/resources/petstore/parameters/Parameters31Resource.yaml +++ b/modules/swagger-jaxrs2/src/test/resources/petstore/parameters/Parameters31Resource.yaml @@ -100,6 +100,7 @@ paths: components: schemas: Category: + type: object properties: id: type: integer @@ -109,6 +110,7 @@ components: xml: name: Category Pet: + type: object properties: id: type: integer @@ -139,6 +141,7 @@ components: xml: name: Pet Tag: + type: object properties: id: type: integer @@ -146,8 +149,9 @@ components: name: type: string xml: - name: Tag + name: tag User: + type: object properties: id: type: integer @@ -171,6 +175,7 @@ components: xml: name: User SubscriptionResponse: + type: object properties: subscriptionId: type: string diff --git a/modules/swagger-jaxrs2/src/test/resources/petstore/requestbody/RequestBody31Resource.yaml b/modules/swagger-jaxrs2/src/test/resources/petstore/requestbody/RequestBody31Resource.yaml index 3229ea10b2..f01cdb9024 100644 --- a/modules/swagger-jaxrs2/src/test/resources/petstore/requestbody/RequestBody31Resource.yaml +++ b/modules/swagger-jaxrs2/src/test/resources/petstore/requestbody/RequestBody31Resource.yaml @@ -59,6 +59,7 @@ paths: components: schemas: User: + type: object properties: id: type: integer From e0838d0be4016b714bafa78d022c76c4d8c34e2a Mon Sep 17 00:00:00 2001 From: MicRyc Date: Wed, 11 Sep 2024 13:43:30 +0200 Subject: [PATCH 04/25] fix-SWG-11909-NPE during webhooks processing with --- .../src/main/java/io/swagger/v3/core/filter/SpecFilter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/swagger-core/src/main/java/io/swagger/v3/core/filter/SpecFilter.java b/modules/swagger-core/src/main/java/io/swagger/v3/core/filter/SpecFilter.java index 7d2f00a211..aef8b69384 100755 --- a/modules/swagger-core/src/main/java/io/swagger/v3/core/filter/SpecFilter.java +++ b/modules/swagger-core/src/main/java/io/swagger/v3/core/filter/SpecFilter.java @@ -85,7 +85,7 @@ public OpenAPI filter(OpenAPI openAPI, OpenAPISpecFilter filter, Map Date: Mon, 16 Sep 2024 12:14:54 +0200 Subject: [PATCH 05/25] schema resolution options - Phase 1: global inline --- .../v3/core/converter/ModelConverters.java | 33 ++++ .../v3/core/jackson/ModelResolver.java | 32 ++- .../v3/core/util/AnnotationsUtils.java | 49 ++++- .../core/resolving/InlineResolvingTest.java | 172 ++++++++++++++++ .../v3/plugins/gradle/tasks/ResolveTask.java | 18 ++ .../integration/GenericOpenApiContext.java | 35 ++++ .../oas/integration/SwaggerConfiguration.java | 17 ++ .../integration/api/OpenAPIConfiguration.java | 6 + .../java/io/swagger/v3/jaxrs2/Reader.java | 4 +- .../ServletConfigContextUtils.java | 5 + .../ServletOpenApiConfigurationLoader.java | 6 +- .../v3/jaxrs2/integration/SwaggerLoader.java | 20 ++ .../java/io/swagger/v3/jaxrs2/ReaderTest.java | 187 ++++++++++++++++++ .../SchemaResolutionResource.java | 82 ++++++++ .../SchemaResolutionResourceSimple.java | 30 +++ .../swagger/v3/plugin/maven/SwaggerMojo.java | 12 ++ .../swagger/v3/oas/models/media/Schema.java | 21 ++ 17 files changed, 710 insertions(+), 19 deletions(-) create mode 100644 modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/InlineResolvingTest.java create mode 100644 modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/schemaResolution/SchemaResolutionResource.java create mode 100644 modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/schemaResolution/SchemaResolutionResourceSimple.java diff --git a/modules/swagger-core/src/main/java/io/swagger/v3/core/converter/ModelConverters.java b/modules/swagger-core/src/main/java/io/swagger/v3/core/converter/ModelConverters.java index 0bb9c21f02..b9cfc4c661 100644 --- a/modules/swagger-core/src/main/java/io/swagger/v3/core/converter/ModelConverters.java +++ b/modules/swagger-core/src/main/java/io/swagger/v3/core/converter/ModelConverters.java @@ -42,6 +42,15 @@ public ModelConverters(boolean openapi31) { } } + public ModelConverters(boolean openapi31, Schema.SchemaResolution schemaResolution) { + converters = new CopyOnWriteArrayList<>(); + if (openapi31) { + converters.add(new ModelResolver(Json31.mapper()).openapi31(true)); + } else { + converters.add(new ModelResolver(Json.mapper()).schemaResolution(schemaResolution)); + } + } + public Set getSkippedPackages() { return skippedPackages; } @@ -61,6 +70,30 @@ public static ModelConverters getInstance(boolean openapi31) { return SINGLETON; } + public static void reset() { + synchronized (ModelConverters.class) { + SINGLETON = null; + SINGLETON31 = null; + } + } + + public static ModelConverters getInstance(boolean openapi31, Schema.SchemaResolution schemaResolution) { + synchronized (ModelConverters.class) { + if (openapi31) { + if (SINGLETON31 == null) { + SINGLETON31 = new ModelConverters(openapi31); + init(SINGLETON31); + } + return SINGLETON31; + } + if (SINGLETON == null) { + SINGLETON = new ModelConverters(openapi31, schemaResolution); + init(SINGLETON); + } + return SINGLETON; + } + } + private static void init(ModelConverters converter) { converter.addPackageToSkip("java.lang"); converter.addPackageToSkip("groovy.lang"); diff --git a/modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/ModelResolver.java b/modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/ModelResolver.java index 2624ed42d4..8662312474 100644 --- a/modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/ModelResolver.java +++ b/modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/ModelResolver.java @@ -125,6 +125,8 @@ public class ModelResolver extends AbstractModelConverter implements ModelConver private boolean openapi31; + private Schema.SchemaResolution schemaResolution = Schema.SchemaResolution.DEFAULT; + public ModelResolver(ObjectMapper mapper) { super(mapper); } @@ -725,7 +727,7 @@ public Schema resolve(AnnotatedType annotatedType, ModelConverterContext context property = context.resolve(aType); property = clone(property); if (openapi31) { - Optional reResolvedProperty = AnnotationsUtils.getSchemaFromAnnotation(ctxSchema, annotatedType.getComponents(), null, openapi31, property, context); + Optional reResolvedProperty = AnnotationsUtils.getSchemaFromAnnotation(ctxSchema, annotatedType.getComponents(), null, openapi31, property, schemaResolution, context); if (reResolvedProperty.isPresent()) { property = reResolvedProperty.get(); } @@ -773,10 +775,14 @@ public Schema resolve(AnnotatedType annotatedType, ModelConverterContext context } if (context.getDefinedModels().containsKey(pName)) { - property = new Schema().$ref(constructRef(pName)); + if (Schema.SchemaResolution.INLINE.equals(this.schemaResolution)) { + property = context.getDefinedModels().get(pName); + } else { + property = new Schema().$ref(constructRef(pName)); + } property = clone(property); - if (openapi31) { - Optional reResolvedProperty = AnnotationsUtils.getSchemaFromAnnotation(ctxSchema, annotatedType.getComponents(), null, openapi31, property, context); + if (openapi31 || Schema.SchemaResolution.INLINE.equals(this.schemaResolution)) { + Optional reResolvedProperty = AnnotationsUtils.getSchemaFromAnnotation(ctxSchema, annotatedType.getComponents(), null, openapi31, property, this.schemaResolution, context); if (reResolvedProperty.isPresent()) { property = reResolvedProperty.get(); } @@ -1000,7 +1006,9 @@ public Schema resolve(AnnotatedType annotatedType, ModelConverterContext context StringUtils.isNotBlank(model.getName())) { if (context.getDefinedModels().containsKey(model.getName())) { - model = new Schema().$ref(constructRef(model.getName())); + if (!Schema.SchemaResolution.INLINE.equals(this.schemaResolution)) { + model = new Schema().$ref(constructRef(model.getName())); + } } } else if (model != null && model.get$ref() != null) { model = new Schema().$ref(StringUtils.isNotEmpty(model.get$ref()) ? model.get$ref() : model.getName()); @@ -1255,6 +1263,18 @@ private void handleUnwrapped(List props, Schema innerModel, String prefi } } + public Schema.SchemaResolution getSchemaResolution() { + return schemaResolution; + } + + public void setSchemaResolution(Schema.SchemaResolution schemaResolution) { + this.schemaResolution = schemaResolution; + } + + public ModelResolver schemaResolution(Schema.SchemaResolution schemaResolution) { + setSchemaResolution(schemaResolution); + return this; + } private class GeneratorWrapper { @@ -1870,7 +1890,7 @@ protected Map resolveDependentSchemas(JavaType a, Annotation[] a } Annotation[] propAnnotations = new Annotation[]{dependentSchemaAnnotation.schema(), dependentSchemaAnnotation.array()}; Schema existingSchema = null; - Optional resolvedPropSchema = AnnotationsUtils.getSchemaFromAnnotation(dependentSchemaAnnotation.schema(), components, jsonViewAnnotation, openapi31, null, context); + Optional resolvedPropSchema = AnnotationsUtils.getSchemaFromAnnotation(dependentSchemaAnnotation.schema(), components, jsonViewAnnotation, openapi31, null, Schema.SchemaResolution.DEFAULT, context); if (resolvedPropSchema.isPresent()) { existingSchema = resolvedPropSchema.get(); dependentSchemas.put(name, existingSchema); diff --git a/modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java b/modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java index e1ed50c9f2..ef17f1c7d3 100644 --- a/modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java +++ b/modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java @@ -587,24 +587,40 @@ public static Optional getSchemaFromAnnotation( boolean openapi31, Schema existingSchema, ModelConverterContext context) { + return getSchemaFromAnnotation(schema, components, jsonViewAnnotation, openapi31, existingSchema, Schema.SchemaResolution.DEFAULT, null); + } + public static Optional getSchemaFromAnnotation( + io.swagger.v3.oas.annotations.media.Schema schema, + Components components, + JsonView jsonViewAnnotation, + boolean openapi31, + Schema existingSchema, + Schema.SchemaResolution schemaResolution, + ModelConverterContext context) { if (schema == null || !hasSchemaAnnotation(schema)) { - if (existingSchema == null || !openapi31) { + if (existingSchema == null || (!openapi31 && Schema.SchemaResolution.DEFAULT.equals(schemaResolution))) { return Optional.empty(); - } else if (existingSchema != null && openapi31) { + } else if (existingSchema != null && (openapi31 || Schema.SchemaResolution.INLINE.equals(schemaResolution))) { return Optional.of(existingSchema); } } Schema schemaObject = null; if (!openapi31) { if (existingSchema != null) { - return Optional.of(existingSchema); + if (!Schema.SchemaResolution.DEFAULT.equals(schemaResolution)) { + schemaObject = existingSchema; + } else { + return Optional.of(existingSchema); + } } - if (schema.oneOf().length > 0 || - schema.allOf().length > 0 || - schema.anyOf().length > 0) { - schemaObject = new ComposedSchema(); - } else { - schemaObject = new Schema(); + if (Schema.SchemaResolution.DEFAULT.equals(schemaResolution)) { + if (schema != null && (schema.oneOf().length > 0 || + schema.allOf().length > 0 || + schema.anyOf().length > 0)) { + schemaObject = new ComposedSchema(); + } else { + schemaObject = new Schema(); + } } } else { if (existingSchema == null) { @@ -613,6 +629,9 @@ public static Optional getSchemaFromAnnotation( schemaObject = existingSchema; } } + if (schema == null) { + return Optional.of(schemaObject); + } if (StringUtils.isNotBlank(schema.description())) { schemaObject.setDescription(schema.description()); } @@ -1956,11 +1975,15 @@ public static void updateAnnotation(Class clazz, io.swagger.v3.oas.annotation } + public static Annotation mergeSchemaAnnotations( + Annotation[] ctxAnnotations, JavaType type) { + return mergeSchemaAnnotations(ctxAnnotations, type, false); + } /* * returns null if no annotations, otherwise either ArraySchema or Schema */ public static Annotation mergeSchemaAnnotations( - Annotation[] ctxAnnotations, JavaType type) { + Annotation[] ctxAnnotations, JavaType type, boolean contextWins) { // get type array and schema io.swagger.v3.oas.annotations.media.Schema tS = type.getRawClass().getDeclaredAnnotation(io.swagger.v3.oas.annotations.media.Schema.class); if (!hasSchemaAnnotation(tS)) { @@ -2020,6 +2043,9 @@ else if (tS != null && tA == null && cS == null && cA != null) { } else if (tA != null && cA != null) { + if (contextWins) { + return mergeArraySchemaAnnotations(tA, cA); + } return mergeArraySchemaAnnotations(cA, tA); } @@ -2028,6 +2054,9 @@ else if (tS != null && cS == null && cA == null) { } else if (tS != null && cS != null) { + if (contextWins) { + return mergeSchemaAnnotations(cS, tS); + } return mergeSchemaAnnotations(tS, cS); } diff --git a/modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/InlineResolvingTest.java b/modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/InlineResolvingTest.java new file mode 100644 index 0000000000..42afe5c0f9 --- /dev/null +++ b/modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/InlineResolvingTest.java @@ -0,0 +1,172 @@ +package io.swagger.v3.core.resolving; + +import io.swagger.v3.core.converter.AnnotatedType; +import io.swagger.v3.core.converter.ModelConverterContextImpl; +import io.swagger.v3.core.jackson.ModelResolver; +import io.swagger.v3.core.matchers.SerializationMatchers; +import io.swagger.v3.oas.annotations.media.Schema; +import org.testng.annotations.Test; + +public class InlineResolvingTest extends SwaggerTestBase{ + + @Test + public void testInlineResolving() { + + final ModelResolver modelResolver = new ModelResolver(mapper()).openapi31(false).schemaResolution(io.swagger.v3.oas.models.media.Schema.SchemaResolution.INLINE); + final ModelConverterContextImpl c = new ModelConverterContextImpl(modelResolver); + // ModelConverters c = ModelConverters.getInstance(false, io.swagger.v3.oas.models.media.Schema.SchemaResolution.INLINE); + c.resolve(new AnnotatedType(InlineSchemaFirst.class)); + + String expectedYaml = "InlineSchemaFirst:\n" + + " type: object\n" + + " properties:\n" + + " property1:\n" + + " type: object\n" + + " description: InlineSchemaFirst property 1\n" + + " nullable: true\n" + + " example: example\n" + + " property2:\n" + + " type: object\n" + + " description: ' InlineSchemaFirst property 2'\n" + + " example: example 2\n" + + "InlineSchemaPropertyFirst:\n" + + " type: object\n" + + " description: property\n" + + " example: example\n"; + + SerializationMatchers.assertEqualsToYaml(c.getDefinedModels(), expectedYaml); + // stringSchemaMap = c.readAll(InlineSchemaSecond.class); + c.resolve(new AnnotatedType(InlineSchemaSecond.class)); + expectedYaml = "InlineSchemaFirst:\n" + + " type: object\n" + + " properties:\n" + + " property1:\n" + + " type: object\n" + + " description: InlineSchemaFirst property 1\n" + + " nullable: true\n" + + " example: example\n" + + " property2:\n" + + " type: object\n" + + " description: ' InlineSchemaFirst property 2'\n" + + " example: example 2\n" + + "InlineSchemaPropertyFirst:\n" + + " type: object\n" + + " description: property\n" + + " example: example\n" + + "InlineSchemaPropertySecond:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: object\n" + + " properties:\n" + + " property1:\n" + + " type: object\n" + + " description: property 1\n" + + " property2:\n" + + " type: object\n" + + " description: property 2\n" + + " example: example\n" + + " description: propertysecond\n" + + " nullable: true\n" + + " example: examplesecond\n" + + "InlineSchemaPropertySimple:\n" + + " type: object\n" + + " description: property\n" + + " example: example\n" + + "InlineSchemaSecond:\n" + + " type: object\n" + + " properties:\n" + + " propertySecond1:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: object\n" + + " properties:\n" + + " property1:\n" + + " type: object\n" + + " description: property 1\n" + + " property2:\n" + + " type: object\n" + + " description: property 2\n" + + " example: example\n" + + " description: InlineSchemaSecond property 1\n" + + " nullable: true\n" + + " example: examplesecond\n" + + " property2:\n" + + " type: object\n" + + " description: InlineSchemaSecond property 2\n" + + " example: InlineSchemaSecond example 2\n" + + "InlineSchemaSimple:\n" + + " type: object\n" + + " properties:\n" + + " property1:\n" + + " type: object\n" + + " description: property 1\n" + + " property2:\n" + + " type: object\n" + + " description: property 2\n" + + " example: example\n"; + SerializationMatchers.assertEqualsToYaml(c.getDefinedModels(), expectedYaml); + } + + static class InlineSchemaFirst { + + // public String foo; + + @Schema(description = "InlineSchemaFirst property 1", nullable = true) + public InlineSchemaPropertyFirst property1; + + + private InlineSchemaPropertyFirst property2; + + @Schema(description = " InlineSchemaFirst property 2", example = "example 2") + public InlineSchemaPropertyFirst getProperty2() { + return null; + } + } + + static class InlineSchemaSecond { + + // public String foo; + + @Schema(description = "InlineSchemaSecond property 1", nullable = true) + public InlineSchemaPropertySecond propertySecond1; + + + private InlineSchemaPropertyFirst property2; + + @Schema(description = "InlineSchemaSecond property 2", example = "InlineSchemaSecond example 2") + public InlineSchemaPropertyFirst getProperty2() { + return null; + } + } + + @Schema(description = "property", example = "example") + static class InlineSchemaPropertyFirst { + // public String bar; + } + + @Schema(description = "propertysecond", example = "examplesecond") + static class InlineSchemaPropertySecond { + public InlineSchemaSimple bar; + } + + static class InlineSchemaSimple { + + @Schema(description = "property 1") + public InlineSchemaPropertySimple property1; + + + private InlineSchemaPropertySimple property2; + + @Schema(description = "property 2", example = "example") + public InlineSchemaPropertySimple getProperty2() { + return null; + } + } + + @Schema(description = "property") + static class InlineSchemaPropertySimple { + // public String bar; + } +} diff --git a/modules/swagger-gradle-plugin/src/main/java/io/swagger/v3/plugins/gradle/tasks/ResolveTask.java b/modules/swagger-gradle-plugin/src/main/java/io/swagger/v3/plugins/gradle/tasks/ResolveTask.java index 87fcdc415f..c885bd593a 100644 --- a/modules/swagger-gradle-plugin/src/main/java/io/swagger/v3/plugins/gradle/tasks/ResolveTask.java +++ b/modules/swagger-gradle-plugin/src/main/java/io/swagger/v3/plugins/gradle/tasks/ResolveTask.java @@ -77,6 +77,8 @@ public enum Format {JSON, YAML, JSONANDYAML}; private Boolean convertToOpenAPI31 = false; + private String schemaResolution; + private String defaultResponseCode; @Input @@ -386,6 +388,19 @@ public void setConvertToOpenAPI31(Boolean convertToOpenAPI31) { } } + /** + * @since 2.2.24 + */ + @Input + @Optional + public String getSchemaResolution() { + return schemaResolution; + } + + public void setSchemaResolution(String schemaResolution) { + this.schemaResolution = schemaResolution; + } + @TaskAction public void resolve() throws GradleException { if (skip) { @@ -505,6 +520,9 @@ public void resolve() throws GradleException { method=swaggerLoaderClass.getDeclaredMethod("setConvertToOpenAPI31", Boolean.class); method.invoke(swaggerLoader, convertToOpenAPI31); + method=swaggerLoaderClass.getDeclaredMethod("setSchemaResolution", String.class); + method.invoke(swaggerLoader, schemaResolution); + method=swaggerLoaderClass.getDeclaredMethod("resolve"); Map specs = (Map)method.invoke(swaggerLoader); diff --git a/modules/swagger-integration/src/main/java/io/swagger/v3/oas/integration/GenericOpenApiContext.java b/modules/swagger-integration/src/main/java/io/swagger/v3/oas/integration/GenericOpenApiContext.java index ff14aa1c5e..76099eb352 100644 --- a/modules/swagger-integration/src/main/java/io/swagger/v3/oas/integration/GenericOpenApiContext.java +++ b/modules/swagger-integration/src/main/java/io/swagger/v3/oas/integration/GenericOpenApiContext.java @@ -76,6 +76,8 @@ public class GenericOpenApiContext implements O private Boolean convertToOpenAPI31; + private Schema.SchemaResolution schemaResolution; + public long getCacheTTL() { return cacheTTL; } @@ -330,6 +332,28 @@ public T convertToOpenAPI31(Boolean convertToOpenAPI31) { return (T) this; } + /** + * @since 2.2.24 + */ + public Schema.SchemaResolution getSchemaResolution() { + return schemaResolution; + } + + /** + * @since 2.2.24 + */ + public void setSchemaResolution(Schema.SchemaResolution schemaResolution) { + this.schemaResolution = schemaResolution; + } + + /** + * @since 2.2.24 + */ + public T schemaResolution(Schema.SchemaResolution schemaResolution) { + this.schemaResolution = schemaResolution; + return (T) this; + } + protected void register() { OpenApiContextLocator.getInstance().putOpenApiContext(id, this); } @@ -467,6 +491,9 @@ public T init() throws OpenApiConfigurationException { ((SwaggerConfiguration) openApiConfiguration).setId(id); ((SwaggerConfiguration) openApiConfiguration).setOpenAPI31(openAPI31); ((SwaggerConfiguration) openApiConfiguration).setConvertToOpenAPI31(convertToOpenAPI31); + if (schemaResolution != null) { + ((SwaggerConfiguration) openApiConfiguration).setSchemaResolution(schemaResolution); + } } openApiConfiguration = mergeParentConfiguration(openApiConfiguration, parent); @@ -559,6 +586,10 @@ public T init() throws OpenApiConfigurationException { if (openApiConfiguration.isConvertToOpenAPI31() != null && this.convertToOpenAPI31 == null) { this.convertToOpenAPI31 = openApiConfiguration.isConvertToOpenAPI31(); } + + if (openApiConfiguration.getSchemaResolution() != null && this.getSchemaResolution() == null) { + this.schemaResolution = openApiConfiguration.getSchemaResolution(); + } register(); return (T) this; } @@ -635,6 +666,10 @@ private OpenAPIConfiguration mergeParentConfiguration(OpenAPIConfiguration confi merged.setDefaultResponseCode(parentConfig.getDefaultResponseCode()); } + if (merged.getSchemaResolution() == null) { + merged.setSchemaResolution(parentConfig.getSchemaResolution()); + } + return merged; } diff --git a/modules/swagger-integration/src/main/java/io/swagger/v3/oas/integration/SwaggerConfiguration.java b/modules/swagger-integration/src/main/java/io/swagger/v3/oas/integration/SwaggerConfiguration.java index 1bd9041905..c9896626e3 100644 --- a/modules/swagger-integration/src/main/java/io/swagger/v3/oas/integration/SwaggerConfiguration.java +++ b/modules/swagger-integration/src/main/java/io/swagger/v3/oas/integration/SwaggerConfiguration.java @@ -2,6 +2,7 @@ import io.swagger.v3.oas.integration.api.OpenAPIConfiguration; import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.media.Schema; import java.util.Collection; import java.util.Map; @@ -40,6 +41,8 @@ public class SwaggerConfiguration implements OpenAPIConfiguration { private Boolean convertToOpenAPI31; + private Schema.SchemaResolution schemaResolution = Schema.SchemaResolution.DEFAULT; + @Override public String getDefaultResponseCode() { return defaultResponseCode; @@ -373,4 +376,18 @@ public SwaggerConfiguration convertToOpenAPI31(Boolean convertToOpenAPI31) { this.setConvertToOpenAPI31(convertToOpenAPI31); return this; } + + @Override + public Schema.SchemaResolution getSchemaResolution() { + return schemaResolution; + } + + public void setSchemaResolution(Schema.SchemaResolution schemaResolution) { + this.schemaResolution = schemaResolution; + } + + public SwaggerConfiguration schemaResolution(Schema.SchemaResolution schemaResolution) { + this.setSchemaResolution(schemaResolution); + return this; + } } diff --git a/modules/swagger-integration/src/main/java/io/swagger/v3/oas/integration/api/OpenAPIConfiguration.java b/modules/swagger-integration/src/main/java/io/swagger/v3/oas/integration/api/OpenAPIConfiguration.java index ae52702a9c..4854c2f5a1 100644 --- a/modules/swagger-integration/src/main/java/io/swagger/v3/oas/integration/api/OpenAPIConfiguration.java +++ b/modules/swagger-integration/src/main/java/io/swagger/v3/oas/integration/api/OpenAPIConfiguration.java @@ -1,6 +1,7 @@ package io.swagger.v3.oas.integration.api; import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.media.Schema; import java.util.Collection; import java.util.Map; @@ -68,4 +69,9 @@ public interface OpenAPIConfiguration { * @since 2.2.17 */ public String getDefaultResponseCode(); + + /** + * @since 2.2.24 + */ + public Schema.SchemaResolution getSchemaResolution(); } diff --git a/modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/Reader.java b/modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/Reader.java index e7396b9f46..082a1372fd 100644 --- a/modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/Reader.java +++ b/modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/Reader.java @@ -1165,7 +1165,7 @@ protected Operation parseMethod( final Class subResource = getSubResourceWithJaxRsSubresourceLocatorSpecs(method); Schema returnTypeSchema = null; if (!shouldIgnoreClass(returnType.getTypeName()) && !method.getGenericReturnType().equals(subResource)) { - ResolvedSchema resolvedSchema = ModelConverters.getInstance(config.isOpenAPI31()).resolveAsResolvedSchema(new AnnotatedType(returnType).resolveAsRef(true).jsonViewAnnotation(jsonViewAnnotation).components(components)); + ResolvedSchema resolvedSchema = ModelConverters.getInstance(config.isOpenAPI31(), config.getSchemaResolution()).resolveAsResolvedSchema(new AnnotatedType(returnType).resolveAsRef(true).jsonViewAnnotation(jsonViewAnnotation).components(components)); if (resolvedSchema.schema != null) { returnTypeSchema = resolvedSchema.schema; Content content = new Content(); @@ -1318,7 +1318,7 @@ private boolean shouldIgnoreClass(String className) { } ignore = rawClassName.startsWith("javax.ws.rs."); ignore = ignore || rawClassName.equalsIgnoreCase("void"); - ignore = ignore || ModelConverters.getInstance(config.isOpenAPI31()).isRegisteredAsSkippedClass(rawClassName); + ignore = ignore || ModelConverters.getInstance(config.isOpenAPI31(), config.getSchemaResolution()).isRegisteredAsSkippedClass(rawClassName); return ignore; } diff --git a/modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/integration/ServletConfigContextUtils.java b/modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/integration/ServletConfigContextUtils.java index aa26058aaa..a2555f4f0b 100644 --- a/modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/integration/ServletConfigContextUtils.java +++ b/modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/integration/ServletConfigContextUtils.java @@ -63,6 +63,11 @@ public class ServletConfigContextUtils { public static final String OPENAPI_CONFIGURATION_CONVERT_TO_OPENAPI_31_KEY = "openApi.configuration.convertToOpenAPI31"; + /** + * @since 2.2.24 + */ + public static final String OPENAPI_CONFIGURATION_SCHEMA_RESOLUTION_KEY = "openApi.configuration.schemaResolution"; + public static Set resolveResourcePackages(ServletConfig servletConfig) { if (!isServletConfigAvailable(servletConfig)) { return null; diff --git a/modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/integration/ServletOpenApiConfigurationLoader.java b/modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/integration/ServletOpenApiConfigurationLoader.java index baeb5dce76..f54f53769f 100644 --- a/modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/integration/ServletOpenApiConfigurationLoader.java +++ b/modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/integration/ServletOpenApiConfigurationLoader.java @@ -6,6 +6,7 @@ import io.swagger.v3.oas.integration.api.OpenAPIConfigBuilder; import io.swagger.v3.oas.integration.api.OpenAPIConfiguration; import io.swagger.v3.oas.integration.api.OpenApiConfigurationLoader; +import io.swagger.v3.oas.models.media.Schema; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -24,6 +25,7 @@ import static io.swagger.v3.jaxrs2.integration.ServletConfigContextUtils.OPENAPI_CONFIGURATION_READALLRESOURCES_KEY; import static io.swagger.v3.jaxrs2.integration.ServletConfigContextUtils.OPENAPI_CONFIGURATION_READER_KEY; import static io.swagger.v3.jaxrs2.integration.ServletConfigContextUtils.OPENAPI_CONFIGURATION_SCANNER_KEY; +import static io.swagger.v3.jaxrs2.integration.ServletConfigContextUtils.OPENAPI_CONFIGURATION_SCHEMA_RESOLUTION_KEY; import static io.swagger.v3.jaxrs2.integration.ServletConfigContextUtils.OPENAPI_CONFIGURATION_SKIPRESOLVEAPPPATH_KEY; import static io.swagger.v3.jaxrs2.integration.ServletConfigContextUtils.OPENAPI_CONFIGURATION_SORTOUTPUT_KEY; import static io.swagger.v3.jaxrs2.integration.ServletConfigContextUtils.OPENAPI_CONFIGURATION_ALWAYSRESOLVEAPPPATH_KEY; @@ -70,7 +72,9 @@ public OpenAPIConfiguration load(String path) throws IOException { .openAPI31(getBooleanInitParam(servletConfig, OPENAPI_CONFIGURATION_OPENAPI_31_KEY)) .convertToOpenAPI31(getBooleanInitParam(servletConfig, OPENAPI_CONFIGURATION_CONVERT_TO_OPENAPI_31_KEY)) .modelConverterClasses(resolveModelConverterClasses(servletConfig)); - + if (getInitParam(servletConfig, OPENAPI_CONFIGURATION_SCHEMA_RESOLUTION_KEY) != null) { + configuration.schemaResolution(Schema.SchemaResolution.valueOf(getInitParam(servletConfig, OPENAPI_CONFIGURATION_SCHEMA_RESOLUTION_KEY))); + } return configuration; } diff --git a/modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/integration/SwaggerLoader.java b/modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/integration/SwaggerLoader.java index c9375dbe5d..36e5987c5c 100644 --- a/modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/integration/SwaggerLoader.java +++ b/modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/integration/SwaggerLoader.java @@ -10,6 +10,7 @@ import io.swagger.v3.oas.integration.SwaggerConfiguration; import io.swagger.v3.oas.integration.api.OpenApiContext; import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.media.Schema; import org.apache.commons.lang3.StringUtils; import java.util.Arrays; @@ -49,6 +50,8 @@ public class SwaggerLoader { private Boolean convertToOpenAPI31 = false; + private String schemaResolution; + /** * @since 2.0.6 */ @@ -250,6 +253,20 @@ public void setConvertToOpenAPI31(Boolean convertToOpenAPI31) { this.convertToOpenAPI31 = convertToOpenAPI31; } + /** + * @since 2.2.24 + */ + public String getSchemaResolution() { + return schemaResolution; + } + + /** + * @since 2.2.24 + */ + public void setSchemaResolution(String schemaResolution) { + this.schemaResolution = schemaResolution; + } + public Map resolve() throws Exception{ Set ignoredRoutesSet = null; @@ -301,6 +318,9 @@ public Map resolve() throws Exception{ .skipResolveAppPath(skipResolveAppPath) .openAPI31(openAPI31) .convertToOpenAPI31(convertToOpenAPI31); + if (schemaResolution != null) { + config.schemaResolution(Schema.SchemaResolution.valueOf(schemaResolution)); + } try { GenericOpenApiContextBuilder builder = new JaxrsOpenApiContextBuilder() .openApiConfiguration(config); diff --git a/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/ReaderTest.java b/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/ReaderTest.java index 53a27ce435..62575c2f0e 100644 --- a/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/ReaderTest.java +++ b/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/ReaderTest.java @@ -98,6 +98,8 @@ import io.swagger.v3.jaxrs2.resources.generics.ticket3694.Ticket3694ResourceSimpleSameReturn; import io.swagger.v3.jaxrs2.resources.rs.ProcessTokenRestService; import io.swagger.v3.jaxrs2.resources.ticket3624.Service; +import io.swagger.v3.jaxrs2.schemaResolution.SchemaResolutionResource; +import io.swagger.v3.jaxrs2.schemaResolution.SchemaResolutionResourceSimple; import io.swagger.v3.oas.annotations.enums.ParameterIn; import io.swagger.v3.oas.integration.SwaggerConfiguration; import io.swagger.v3.oas.models.Components; @@ -4167,4 +4169,189 @@ public void test4483Response() { " type: string\n"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); } + + @Test + public void testSchemaResolution() { + ModelConverters.reset(); + Reader reader = new Reader(new SwaggerConfiguration().openAPI(new OpenAPI()).schemaResolution(Schema.SchemaResolution.INLINE)); + OpenAPI openAPI = reader.read(SchemaResolutionResource.class); + String yaml = "openapi: 3.0.1\n" + + "paths:\n" + + " /test/inlineSchemaFirst:\n" + + " get:\n" + + " operationId: inlineSchemaFirst\n" + + " responses:\n" + + " default:\n" + + " description: default response\n" + + " content:\n" + + " '*/*':\n" + + " schema:\n" + + " type: object\n" + + " properties:\n" + + " property1:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: InlineSchemaFirst property 1\n" + + " nullable: true\n" + + " example: example\n" + + " property2:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: ' InlineSchemaFirst property 2'\n" + + " example: example 2\n" + + " /test/inlineSchemaSecond:\n" + + " get:\n" + + " operationId: inlineSchemaSecond\n" + + " responses:\n" + + " default:\n" + + " description: default response\n" + + " content:\n" + + " '*/*':\n" + + " schema:\n" + + " type: object\n" + + " properties:\n" + + " foo:\n" + + " type: string\n" + + " propertySecond1:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: object\n" + + " properties:\n" + + " property1:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: property 1\n" + + " property2:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: property 2\n" + + " example: example\n" + + " description: InlineSchemaSecond property 1\n" + + " nullable: true\n" + + " example: examplesecond\n" + + " property2:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: InlineSchemaSecond property 2\n" + + " example: InlineSchemaSecond example 2\n" + + "components:\n" + + " schemas:\n" + + " InlineSchemaFirst:\n" + + " type: object\n" + + " properties:\n" + + " property1:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: InlineSchemaFirst property 1\n" + + " nullable: true\n" + + " example: example\n" + + " property2:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: ' InlineSchemaFirst property 2'\n" + + " example: example 2\n" + + " InlineSchemaPropertyFirst:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: property\n" + + " example: example\n" + + " InlineSchemaPropertySecond:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: object\n" + + " properties:\n" + + " property1:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: property 1\n" + + " property2:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: property 2\n" + + " example: example\n" + + " description: propertysecond\n" + + " nullable: true\n" + + " example: examplesecond\n" + + " InlineSchemaPropertySimple:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: property\n" + + " example: example\n" + + " InlineSchemaSecond:\n" + + " type: object\n" + + " properties:\n" + + " foo:\n" + + " type: string\n" + + " propertySecond1:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: object\n" + + " properties:\n" + + " property1:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: property 1\n" + + " property2:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: property 2\n" + + " example: example\n" + + " description: InlineSchemaSecond property 1\n" + + " nullable: true\n" + + " example: examplesecond\n" + + " property2:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: InlineSchemaSecond property 2\n" + + " example: InlineSchemaSecond example 2\n" + + " InlineSchemaSimple:\n" + + " type: object\n" + + " properties:\n" + + " property1:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: property 1\n" + + " property2:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: property 2\n" + + " example: example\n\n"; + SerializationMatchers.assertEqualsToYaml(openAPI, yaml); + ModelConverters.reset(); + } } diff --git a/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/schemaResolution/SchemaResolutionResource.java b/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/schemaResolution/SchemaResolutionResource.java new file mode 100644 index 0000000000..01e691ba1e --- /dev/null +++ b/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/schemaResolution/SchemaResolutionResource.java @@ -0,0 +1,82 @@ +package io.swagger.v3.jaxrs2.schemaResolution; + +import io.swagger.v3.oas.annotations.media.Schema; +import javax.ws.rs.GET; +import javax.ws.rs.Path; + +@Path("test") +public class SchemaResolutionResource { + + @GET + @Path("/inlineSchemaSecond") + public InlineSchemaSecond inlineSchemaSecond() { + return null; + } + @GET + @Path("/inlineSchemaFirst") + public InlineSchemaFirst inlineSchemaFirst() { + return null; + } + + + static class InlineSchemaFirst { + + // public String foo; + + @Schema(description = "InlineSchemaFirst property 1", nullable = true) + public InlineSchemaPropertyFirst property1; + + + private InlineSchemaPropertyFirst property2; + + @Schema(description = " InlineSchemaFirst property 2", example = "example 2") + public InlineSchemaPropertyFirst getProperty2() { + return null; + } + } + + static class InlineSchemaSecond { + + public String foo; + + @Schema(description = "InlineSchemaSecond property 1", nullable = true) + public InlineSchemaPropertySecond propertySecond1; + + + private InlineSchemaPropertyFirst property2; + + @Schema(description = "InlineSchemaSecond property 2", example = "InlineSchemaSecond example 2") + public InlineSchemaPropertyFirst getProperty2() { + return null; + } + } + + @Schema(description = "property", example = "example") + static class InlineSchemaPropertyFirst { + public String bar; + } + + @Schema(description = "propertysecond", example = "examplesecond") + static class InlineSchemaPropertySecond { + public InlineSchemaSimple bar; + } + + static class InlineSchemaSimple { + + @Schema(description = "property 1") + public InlineSchemaPropertySimple property1; + + + private InlineSchemaPropertySimple property2; + + @Schema(description = "property 2", example = "example") + public InlineSchemaPropertySimple getProperty2() { + return null; + } + } + + @Schema(description = "property") + static class InlineSchemaPropertySimple { + public String bar; + } +} diff --git a/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/schemaResolution/SchemaResolutionResourceSimple.java b/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/schemaResolution/SchemaResolutionResourceSimple.java new file mode 100644 index 0000000000..61ac55e6b6 --- /dev/null +++ b/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/schemaResolution/SchemaResolutionResourceSimple.java @@ -0,0 +1,30 @@ +package io.swagger.v3.jaxrs2.schemaResolution; + +import io.swagger.v3.oas.annotations.media.Schema; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; + +@Path("test") +public class SchemaResolutionResourceSimple { + + @GET + @Path("/inlineSchemaFirst") + public InlineSchemaFirst inlineSchemaFirst() { + return null; + } + + + static class InlineSchemaFirst { + + // public String foo; + + @Schema(description = "InlineSchemaFirst property 1", nullable = true) + public InlineSchemaPropertyFirst property1; + } + + @Schema(description = "property", example = "example") + static class InlineSchemaPropertyFirst { + public String bar; + } +} diff --git a/modules/swagger-maven-plugin/src/main/java/io/swagger/v3/plugin/maven/SwaggerMojo.java b/modules/swagger-maven-plugin/src/main/java/io/swagger/v3/plugin/maven/SwaggerMojo.java index 05911233d7..60bafc3d44 100644 --- a/modules/swagger-maven-plugin/src/main/java/io/swagger/v3/plugin/maven/SwaggerMojo.java +++ b/modules/swagger-maven-plugin/src/main/java/io/swagger/v3/plugin/maven/SwaggerMojo.java @@ -11,6 +11,7 @@ import io.swagger.v3.oas.integration.SwaggerConfiguration; import io.swagger.v3.oas.integration.api.OpenApiContext; import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.media.Schema; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; @@ -184,6 +185,7 @@ private void setDefaultsIfMissing(SwaggerConfiguration config) { if (config.isConvertToOpenAPI31() == null) { config.setConvertToOpenAPI31(convertToOpenAPI31); } + } /** @@ -355,6 +357,10 @@ private SwaggerConfiguration mergeConfig(OpenAPI openAPIInput, SwaggerConfigurat config.openAPI31(openapi31); } + if (StringUtils.isNotBlank(schemaResolution)) { + config.schemaResolution(Schema.SchemaResolution.valueOf(schemaResolution)); + } + return config; } @@ -453,6 +459,12 @@ private boolean isCollectionNotBlank(Collection collection) { @Parameter(property = "resolve.convertToOpenAPI31") private Boolean convertToOpenAPI31; + /** + * @since 2.2.24 + */ + @Parameter(property = "resolve.schemaResolution") + private String schemaResolution; + private String projectEncoding = "UTF-8"; private SwaggerConfiguration config; diff --git a/modules/swagger-models/src/main/java/io/swagger/v3/oas/models/media/Schema.java b/modules/swagger-models/src/main/java/io/swagger/v3/oas/models/media/Schema.java index 8872a74c2c..8f76ad9ce8 100644 --- a/modules/swagger-models/src/main/java/io/swagger/v3/oas/models/media/Schema.java +++ b/modules/swagger-models/src/main/java/io/swagger/v3/oas/models/media/Schema.java @@ -1,6 +1,7 @@ package io.swagger.v3.oas.models.media; import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.models.annotations.OpenAPI30; import io.swagger.v3.oas.models.annotations.OpenAPI31; import io.swagger.v3.oas.models.Components; @@ -44,6 +45,26 @@ public String toString() { } } + public static final String SCHEMA_RESOLUTION_PROPERTY = "schema-resolution"; + public enum SchemaResolution { + @JsonProperty("default") + DEFAULT("default"), + @JsonProperty("inline") + INLINE("inline"), + @JsonProperty("all-of") + ALL_OF("all-of"); + private String value; + + SchemaResolution(String value) { + this.value = value; + } + + @Override + public String toString() { + return String.valueOf(value); + } + } + protected T _default; private String name; From dd98ce045cc0d9c1e67bf49742012512922415ea Mon Sep 17 00:00:00 2001 From: MicRyc Date: Mon, 16 Sep 2024 11:30:37 +0200 Subject: [PATCH 06/25] refs-#4703/#4702-Fix applyBeanValidatorAnnotations method to support both OAS 3.1/3.0 --- .../v3/core/jackson/ModelResolver.java | 49 ++++--- .../resolving/v31/ModelResolverOAS31Test.java | 120 +++++++++++++++++- 2 files changed, 146 insertions(+), 23 deletions(-) diff --git a/modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/ModelResolver.java b/modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/ModelResolver.java index 8662312474..ecb141a430 100644 --- a/modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/ModelResolver.java +++ b/modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/ModelResolver.java @@ -1511,43 +1511,38 @@ protected void applyBeanValidatorAnnotations(Schema property, Annotation[] annot if ("integer".equals(property.getType()) || "number".equals(property.getType())) { property.setMinimum(new BigDecimal(size.min())); property.setMaximum(new BigDecimal(size.max())); - } else if (property instanceof StringSchema) { - StringSchema sp = (StringSchema) property; - sp.minLength(Integer.valueOf(size.min())); - sp.maxLength(Integer.valueOf(size.max())); - } else if (property instanceof ArraySchema) { - ArraySchema sp = (ArraySchema) property; - sp.setMinItems(size.min()); - sp.setMaxItems(size.max()); + } + if (isStringSchema(property)) { + property.setMinLength(Integer.valueOf(size.min())); + property.setMaxLength(Integer.valueOf(size.max())); + } + if (isArraySchema(property)) { + property.setMinItems(size.min()); + property.setMaxItems(size.max()); } } if (annos.containsKey("javax.validation.constraints.DecimalMin")) { DecimalMin min = (DecimalMin) annos.get("javax.validation.constraints.DecimalMin"); - if (property instanceof NumberSchema) { - NumberSchema ap = (NumberSchema) property; - ap.setMinimum(new BigDecimal(min.value())); - ap.setExclusiveMinimum(!min.inclusive()); + if (isNumberSchema(property)) { + property.setMinimum(new BigDecimal(min.value())); + property.setExclusiveMinimum(!min.inclusive()); } } if (annos.containsKey("javax.validation.constraints.DecimalMax")) { DecimalMax max = (DecimalMax) annos.get("javax.validation.constraints.DecimalMax"); - if (property instanceof NumberSchema) { - NumberSchema ap = (NumberSchema) property; - ap.setMaximum(new BigDecimal(max.value())); - ap.setExclusiveMaximum(!max.inclusive()); + if (isNumberSchema(property)) { + property.setMaximum(new BigDecimal(max.value())); + property.setExclusiveMaximum(!max.inclusive()); } } if (annos.containsKey("javax.validation.constraints.Pattern")) { Pattern pattern = (Pattern) annos.get("javax.validation.constraints.Pattern"); - - if (property instanceof StringSchema) { + if (isStringSchema(property)) { property.setPattern(pattern.regexp()); } - - if(property.getItems() != null && property.getItems() instanceof StringSchema) { + if(property.getItems() != null && isStringSchema(property.getItems())) { property.getItems().setPattern(pattern.regexp()); } - } } @@ -3009,6 +3004,18 @@ protected boolean isObjectSchema(Schema schema) { return (schema.getTypes() != null && schema.getTypes().contains("object")) || "object".equals(schema.getType()) || (schema.getType() == null && schema.getProperties() != null && !schema.getProperties().isEmpty()); } + protected boolean isArraySchema(Schema schema){ + return "array".equals(schema.getType()) || (schema.getTypes() != null && schema.getTypes().contains("array")); + } + + protected boolean isStringSchema(Schema schema){ + return "string".equals(schema.getType()) || (schema.getTypes() != null && schema.getTypes().contains("string")); + } + + protected boolean isNumberSchema(Schema schema){ + return "number".equals(schema.getType()) || (schema.getTypes() != null && schema.getTypes().contains("number")); + } + protected Schema buildRefSchemaIfObject(Schema schema, ModelConverterContext context) { if (schema == null) { return null; diff --git a/modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/v31/ModelResolverOAS31Test.java b/modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/v31/ModelResolverOAS31Test.java index 8b5ce8b67a..12e2ca78fc 100644 --- a/modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/v31/ModelResolverOAS31Test.java +++ b/modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/v31/ModelResolverOAS31Test.java @@ -2,6 +2,7 @@ import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverterContextImpl; +import io.swagger.v3.core.converter.ModelConverters; import io.swagger.v3.core.jackson.ModelResolver; import io.swagger.v3.core.matchers.SerializationMatchers; import io.swagger.v3.core.resolving.SwaggerTestBase; @@ -10,10 +11,14 @@ import io.swagger.v3.core.resolving.v31.model.AnnotatedArray; import io.swagger.v3.core.resolving.v31.model.ModelWithDependentSchema; import io.swagger.v3.core.resolving.v31.model.ModelWithOAS31Stuff; -import io.swagger.v3.core.resolving.v31.model.ModelWithOAS31StuffMinimal; -import io.swagger.v3.core.util.Yaml31; import io.swagger.v3.oas.models.media.Schema; import org.testng.annotations.Test; +import javax.validation.constraints.DecimalMax; +import javax.validation.constraints.DecimalMin; +import javax.validation.constraints.Pattern; +import javax.validation.constraints.Size; +import java.util.List; +import java.util.Map; public class ModelResolverOAS31Test extends SwaggerTestBase { @@ -231,4 +236,115 @@ public void testFieldArraySchemaAnnotation() { " type: string\n" + " maxItems: 10"); } + + @Test(description = "@Pattern correctly handled in type parameters of properties using collections when using oas 3.1.0") + public void testModelUsingCollectionTypePropertyHandlesPatternAnnotationForOas31() { + String expectedYaml = "ClassWithUsingPatternOnCollection:\n" + + " type: object\n" + + " properties:\n" + + " myField:\n" + + " type: array\n" + + " items:\n" + + " pattern: myPattern\n" + + " type: string"; + + Map stringSchemaMap = ModelConverters.getInstance(true).readAll(ClassWithUsingPatternOnCollection.class); + SerializationMatchers.assertEqualsToYaml31(stringSchemaMap, expectedYaml); + } + + private static class ClassWithUsingPatternOnCollection { + private List<@Pattern(regexp = "myPattern") String> myField; + + public List getMyField() { + return myField; + } + + public void setMyField(List myField) { + this.myField = myField; + } + } + + @Test(description = "@Size correctly handled in properties using collections when using oas 3.1.0") + public void testModelUsingCollectionTypePropertyHandleSizeAnnotationForOas31() { + String expectedYaml = "ClassWithUsingSizeOnCollection:\n" + + " type: object\n" + + " properties:\n" + + " myField:\n" + + " maxItems: 100\n" + + " minItems: 1\n" + + " type: array\n" + + " items:\n" + + " type: string"; + + Map stringSchemaMap = ModelConverters.getInstance(true).readAll(ClassWithUsingSizeOnCollection.class); + SerializationMatchers.assertEqualsToYaml31(stringSchemaMap, expectedYaml); + } + + private static class ClassWithUsingSizeOnCollection { + @Size(min = 1, max = 100) + private List myField; + + public List getMyField() { + return myField; + } + + public void setMyField(List myField) { + this.myField = myField; + } + } + + @Test(description = "@Size correctly handled for field type String using OAS 3.1.0") + public void testSizeAnnotationOnFieldForOAS31() { + String expectedYaml = "ClassWithUsingSizeOnField:\n" + + " type: object\n" + + " properties:\n" + + " myField:\n" + + " type: string\n" + + " maxLength: 100\n" + + " minLength: 1"; + + Map stringSchemaMap = ModelConverters.getInstance(true).readAll(ClassWithUsingSizeOnField.class); + SerializationMatchers.assertEqualsToYaml31(stringSchemaMap, expectedYaml); + } + + private static class ClassWithUsingSizeOnField { + @Size(min = 1, max = 100) + private String myField; + + public String getMyField() { + return myField; + } + + public void setMyField(String myField) { + this.myField = myField; + } + } + + @Test(description = "@DecimalMax/Min annotations correctly handled for field type Number using OAS 3.1.0") + public void testDecimalAnnotationsOnField() { + String expectedYaml = "ClassWithUsingDecimalAnnotationsOnField:\n" + + " type: object\n" + + " properties:\n" + + " myField:\n" + + " type: number\n" + + " maximum: 100\n" + + " minimum: 1"; + + Map stringSchemaMap = ModelConverters.getInstance(true).readAll(ClassWithUsingDecimalAnnotationsOnField.class); + SerializationMatchers.assertEqualsToYaml31(stringSchemaMap, expectedYaml); + } + + private static class ClassWithUsingDecimalAnnotationsOnField { + @DecimalMin("1") + @DecimalMax("100") + private Number myField; + + public Number getMyField() { + return myField; + } + + public void setMyField(Number myField) { + this.myField = myField; + } + } } From a9510c3025d97ee2f81849ff13ba8618ce084e9a Mon Sep 17 00:00:00 2001 From: MicRyc Date: Thu, 19 Sep 2024 15:08:45 +0200 Subject: [PATCH 07/25] Add integer check for isNumberSchema --- .../java/io/swagger/v3/core/jackson/ModelResolver.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/ModelResolver.java b/modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/ModelResolver.java index ecb141a430..1cb9e12bbf 100644 --- a/modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/ModelResolver.java +++ b/modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/ModelResolver.java @@ -1495,20 +1495,20 @@ protected void applyBeanValidatorAnnotations(Schema property, Annotation[] annot } } if (annos.containsKey("javax.validation.constraints.Min")) { - if ("integer".equals(property.getType()) || "number".equals(property.getType())) { + if (isNumberSchema(property)) { Min min = (Min) annos.get("javax.validation.constraints.Min"); property.setMinimum(new BigDecimal(min.value())); } } if (annos.containsKey("javax.validation.constraints.Max")) { - if ("integer".equals(property.getType()) || "number".equals(property.getType())) { + if (isNumberSchema(property)) { Max max = (Max) annos.get("javax.validation.constraints.Max"); property.setMaximum(new BigDecimal(max.value())); } } if (annos.containsKey("javax.validation.constraints.Size")) { Size size = (Size) annos.get("javax.validation.constraints.Size"); - if ("integer".equals(property.getType()) || "number".equals(property.getType())) { + if (isNumberSchema(property)) { property.setMinimum(new BigDecimal(size.min())); property.setMaximum(new BigDecimal(size.max())); } @@ -3013,7 +3013,7 @@ protected boolean isStringSchema(Schema schema){ } protected boolean isNumberSchema(Schema schema){ - return "number".equals(schema.getType()) || (schema.getTypes() != null && schema.getTypes().contains("number")); + return "number".equals(schema.getType()) || (schema.getTypes() != null && schema.getTypes().contains("number")) || "integer".equals(schema.getType()) || (schema.getTypes() != null && schema.getTypes().contains("integer")); } protected Schema buildRefSchemaIfObject(Schema schema, ModelConverterContext context) { From 5fc5d0e61d04a00417a1afe3375e97569a75a8f0 Mon Sep 17 00:00:00 2001 From: frantuma Date: Mon, 23 Sep 2024 12:43:17 +0200 Subject: [PATCH 08/25] schema resolution options - Phase 2: global allOf --- .../v3/core/converter/ModelConverters.java | 4 +- .../v3/core/jackson/ModelResolver.java | 38 ++- .../v3/core/util/AnnotationsUtils.java | 6 + .../v3/core/util/ParameterProcessor.java | 61 ++++- .../v3/core/resolving/AllofResolvingTest.java | 165 ++++++++++++ .../integration/GenericOpenApiContext.java | 2 +- .../v3/jaxrs2/DefaultParameterExtension.java | 13 +- .../java/io/swagger/v3/jaxrs2/Reader.java | 9 +- .../jaxrs2/ext/AbstractOpenAPIExtension.java | 7 + .../v3/jaxrs2/ext/OpenAPIExtension.java | 5 + .../swagger/v3/jaxrs2/util/ReaderUtils.java | 8 +- .../java/io/swagger/v3/jaxrs2/ReaderTest.java | 189 -------------- .../v3/jaxrs2/SchemaResolutionAllOfTest.java | 60 +++++ .../v3/jaxrs2/SchemaResolutionInlineTest.java | 235 ++++++++++++++++++ .../SchemaResolutionResource.java | 2 +- .../SchemaResolutionResourceSimple.java | 14 +- pom.xml | 2 +- 17 files changed, 607 insertions(+), 213 deletions(-) create mode 100644 modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/AllofResolvingTest.java create mode 100644 modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/SchemaResolutionAllOfTest.java create mode 100644 modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/SchemaResolutionInlineTest.java diff --git a/modules/swagger-core/src/main/java/io/swagger/v3/core/converter/ModelConverters.java b/modules/swagger-core/src/main/java/io/swagger/v3/core/converter/ModelConverters.java index b9cfc4c661..7149e587c5 100644 --- a/modules/swagger-core/src/main/java/io/swagger/v3/core/converter/ModelConverters.java +++ b/modules/swagger-core/src/main/java/io/swagger/v3/core/converter/ModelConverters.java @@ -45,7 +45,7 @@ public ModelConverters(boolean openapi31) { public ModelConverters(boolean openapi31, Schema.SchemaResolution schemaResolution) { converters = new CopyOnWriteArrayList<>(); if (openapi31) { - converters.add(new ModelResolver(Json31.mapper()).openapi31(true)); + converters.add(new ModelResolver(Json31.mapper()).openapi31(true).schemaResolution(schemaResolution)); } else { converters.add(new ModelResolver(Json.mapper()).schemaResolution(schemaResolution)); } @@ -81,7 +81,7 @@ public static ModelConverters getInstance(boolean openapi31, Schema.SchemaResolu synchronized (ModelConverters.class) { if (openapi31) { if (SINGLETON31 == null) { - SINGLETON31 = new ModelConverters(openapi31); + SINGLETON31 = new ModelConverters(openapi31, Schema.SchemaResolution.DEFAULT); init(SINGLETON31); } return SINGLETON31; diff --git a/modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/ModelResolver.java b/modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/ModelResolver.java index 1cb9e12bbf..dc9e74add1 100644 --- a/modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/ModelResolver.java +++ b/modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/ModelResolver.java @@ -682,7 +682,7 @@ public Schema resolve(AnnotatedType annotatedType, ModelConverterContext context Annotation[] ctxAnnotation31 = null; - if (openapi31) { + if (Schema.SchemaResolution.ALL_OF.equals(this.schemaResolution) || openapi31) { List ctxAnnotations31List = new ArrayList<>(); if (annotations != null) { for (Annotation a : annotations) { @@ -701,7 +701,6 @@ public Schema resolve(AnnotatedType annotatedType, ModelConverterContext context AnnotatedType aType = new AnnotatedType() .type(propType) - .ctxAnnotations(openapi31 ? ctxAnnotation31 : annotations) .parent(model) .resolveAsRef(annotatedType.isResolveAsRef()) .jsonViewAnnotation(annotatedType.getJsonViewAnnotation()) @@ -709,7 +708,11 @@ public Schema resolve(AnnotatedType annotatedType, ModelConverterContext context .schemaProperty(true) .components(annotatedType.getComponents()) .propertyName(propName); - + if (Schema.SchemaResolution.ALL_OF.equals(this.schemaResolution) || openapi31) { + aType.ctxAnnotations(ctxAnnotation31); + } else { + aType.ctxAnnotations(annotations); + } final AnnotatedMember propMember = member; aType.jsonUnwrappedHandler(t -> { JsonUnwrapped uw = propMember.getAnnotation(JsonUnwrapped.class); @@ -726,6 +729,7 @@ public Schema resolve(AnnotatedType annotatedType, ModelConverterContext context }); property = context.resolve(aType); property = clone(property); + Schema ctxProperty = null; if (openapi31) { Optional reResolvedProperty = AnnotationsUtils.getSchemaFromAnnotation(ctxSchema, annotatedType.getComponents(), null, openapi31, property, schemaResolution, context); if (reResolvedProperty.isPresent()) { @@ -736,6 +740,16 @@ public Schema resolve(AnnotatedType annotatedType, ModelConverterContext context property = reResolvedProperty.get(); } + } else if (Schema.SchemaResolution.ALL_OF.equals(this.schemaResolution)) { + Optional reResolvedProperty = AnnotationsUtils.getSchemaFromAnnotation(ctxSchema, annotatedType.getComponents(), null, openapi31, null, schemaResolution, context); + if (reResolvedProperty.isPresent()) { + ctxProperty = reResolvedProperty.get(); + } + reResolvedProperty = AnnotationsUtils.getArraySchema(ctxArraySchema, annotatedType.getComponents(), null, openapi31, ctxProperty); + if (reResolvedProperty.isPresent()) { + ctxProperty = reResolvedProperty.get(); + } + } if (property != null) { Boolean required = md.getRequired(); @@ -777,10 +791,15 @@ public Schema resolve(AnnotatedType annotatedType, ModelConverterContext context if (context.getDefinedModels().containsKey(pName)) { if (Schema.SchemaResolution.INLINE.equals(this.schemaResolution)) { property = context.getDefinedModels().get(pName); + } else if (Schema.SchemaResolution.ALL_OF.equals(this.schemaResolution) && ctxProperty != null) { + property = new Schema() + .addAllOfItem(ctxProperty) + .addAllOfItem(new Schema().$ref(constructRef(pName))); } else { property = new Schema().$ref(constructRef(pName)); } property = clone(property); + // TODO: why is this needed? is it not handled before? if (openapi31 || Schema.SchemaResolution.INLINE.equals(this.schemaResolution)) { Optional reResolvedProperty = AnnotationsUtils.getSchemaFromAnnotation(ctxSchema, annotatedType.getComponents(), null, openapi31, property, this.schemaResolution, context); if (reResolvedProperty.isPresent()) { @@ -794,7 +813,13 @@ public Schema resolve(AnnotatedType annotatedType, ModelConverterContext context } } else if (property.get$ref() != null) { if (!openapi31) { - property = new Schema().$ref(StringUtils.isNotEmpty(property.get$ref()) ? property.get$ref() : property.getName()); + if (Schema.SchemaResolution.ALL_OF.equals(this.schemaResolution) && ctxProperty != null) { + property = new Schema() + .addAllOfItem(ctxProperty) + .addAllOfItem(new Schema().$ref(StringUtils.isNotEmpty(property.get$ref()) ? property.get$ref() : property.getName())); + } else { + property = new Schema().$ref(StringUtils.isNotEmpty(property.get$ref()) ? property.get$ref() : property.getName()); + } } else { if (StringUtils.isEmpty(property.get$ref())) { property.$ref(property.getName()); @@ -807,9 +832,12 @@ public Schema resolve(AnnotatedType annotatedType, ModelConverterContext context if (property != null && io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED.equals(requiredMode)) { addRequiredItem(model, property.getName()); } + if (ctxProperty == null) { + ctxProperty = property; + } final boolean applyNotNullAnnotations = io.swagger.v3.oas.annotations.media.Schema.RequiredMode.AUTO.equals(requiredMode); annotations = addGenericTypeArgumentAnnotationsForOptionalField(propDef, annotations); - applyBeanValidatorAnnotations(propDef, property, annotations, model, applyNotNullAnnotations); + applyBeanValidatorAnnotations(propDef, ctxProperty, annotations, model, applyNotNullAnnotations); props.add(property); } diff --git a/modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java b/modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java index ef17f1c7d3..bdfbc2e691 100644 --- a/modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java +++ b/modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java @@ -621,6 +621,12 @@ public static Optional getSchemaFromAnnotation( } else { schemaObject = new Schema(); } + } else if (Schema.SchemaResolution.ALL_OF.equals(schemaResolution)) { + if (existingSchema == null) { + schemaObject = new Schema(); + } else { + schemaObject = existingSchema; + } } } else { if (existingSchema == null) { diff --git a/modules/swagger-core/src/main/java/io/swagger/v3/core/util/ParameterProcessor.java b/modules/swagger-core/src/main/java/io/swagger/v3/core/util/ParameterProcessor.java index 5c977bdfed..d219d52a55 100644 --- a/modules/swagger-core/src/main/java/io/swagger/v3/core/util/ParameterProcessor.java +++ b/modules/swagger-core/src/main/java/io/swagger/v3/core/util/ParameterProcessor.java @@ -42,6 +42,19 @@ public static Parameter applyAnnotations( String[] methodTypes, JsonView jsonViewAnnotation, boolean openapi31) { + return applyAnnotations(parameter, type, annotations, components, classTypes, methodTypes, jsonViewAnnotation, openapi31, null); + } + + public static Parameter applyAnnotations( + Parameter parameter, + Type type, + List annotations, + Components components, + String[] classTypes, + String[] methodTypes, + JsonView jsonViewAnnotation, + boolean openapi31, + Schema.SchemaResolution schemaResolution) { final AnnotationsHelper helper = new AnnotationsHelper(annotations, type); if (helper.isContext()) { @@ -59,17 +72,57 @@ public static Parameter applyAnnotations( if (paramSchemaOrArrayAnnotation != null) { reworkedAnnotations.add(paramSchemaOrArrayAnnotation); } + io.swagger.v3.oas.annotations.media.Schema ctxSchema = AnnotationsUtils.getSchemaAnnotation(annotations.toArray(new Annotation[0])); + io.swagger.v3.oas.annotations.media.ArraySchema ctxArraySchema = AnnotationsUtils.getArraySchemaAnnotation(annotations.toArray(new Annotation[0])); + Annotation[] ctxAnnotation31 = null; + + if (Schema.SchemaResolution.ALL_OF.equals(schemaResolution)) { + List ctxAnnotations31List = new ArrayList<>(); + if (annotations != null) { + for (Annotation a : annotations) { + if ( + !(a instanceof io.swagger.v3.oas.annotations.media.Schema) && + !(a instanceof io.swagger.v3.oas.annotations.media.ArraySchema)) { + ctxAnnotations31List.add(a); + } + } + ctxAnnotation31 = ctxAnnotations31List.toArray(new Annotation[ctxAnnotations31List.size()]); + } + } AnnotatedType annotatedType = new AnnotatedType() .type(type) .resolveAsRef(true) .skipOverride(true) - .jsonViewAnnotation(jsonViewAnnotation) - .ctxAnnotations(reworkedAnnotations.toArray(new Annotation[reworkedAnnotations.size()])); + .jsonViewAnnotation(jsonViewAnnotation); + + if (Schema.SchemaResolution.ALL_OF.equals(schemaResolution)) { + annotatedType.ctxAnnotations(ctxAnnotation31); + } else { + annotatedType.ctxAnnotations(reworkedAnnotations.toArray(new Annotation[reworkedAnnotations.size()])); + } - final ResolvedSchema resolvedSchema = ModelConverters.getInstance(openapi31).resolveAsResolvedSchema(annotatedType); + final ResolvedSchema resolvedSchema = ModelConverters.getInstance(openapi31, schemaResolution).resolveAsResolvedSchema(annotatedType); if (resolvedSchema.schema != null) { - parameter.setSchema(resolvedSchema.schema); + Schema resSchema = AnnotationsUtils.clone(resolvedSchema.schema, openapi31); + Schema ctxSchemaObject = null; + if (Schema.SchemaResolution.ALL_OF.equals(schemaResolution)) { + Optional reResolvedSchema = AnnotationsUtils.getSchemaFromAnnotation(ctxSchema, annotatedType.getComponents(), null, openapi31, null, schemaResolution, null); + if (reResolvedSchema.isPresent()) { + ctxSchemaObject = reResolvedSchema.get(); + } + reResolvedSchema = AnnotationsUtils.getArraySchema(ctxArraySchema, annotatedType.getComponents(), null, openapi31, ctxSchemaObject); + if (reResolvedSchema.isPresent()) { + ctxSchemaObject = reResolvedSchema.get(); + } + + } + if (Schema.SchemaResolution.ALL_OF.equals(schemaResolution) && ctxSchemaObject != null) { + resSchema = new Schema() + .addAllOfItem(ctxSchemaObject) + .addAllOfItem(resolvedSchema.schema); + } + parameter.setSchema(resSchema); } resolvedSchema.referencedSchemas.forEach(components::addSchemas); diff --git a/modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/AllofResolvingTest.java b/modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/AllofResolvingTest.java new file mode 100644 index 0000000000..bbec9310c1 --- /dev/null +++ b/modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/AllofResolvingTest.java @@ -0,0 +1,165 @@ +package io.swagger.v3.core.resolving; + +import io.swagger.v3.core.converter.AnnotatedType; +import io.swagger.v3.core.converter.ModelConverterContextImpl; +import io.swagger.v3.core.jackson.ModelResolver; +import io.swagger.v3.core.matchers.SerializationMatchers; +import io.swagger.v3.oas.annotations.media.Schema; +import org.testng.annotations.Test; + +public class AllofResolvingTest extends SwaggerTestBase { + + @Test + public void testAllofResolving() { + + final ModelResolver modelResolver = new ModelResolver(mapper()).openapi31(false).schemaResolution(io.swagger.v3.oas.models.media.Schema.SchemaResolution.ALL_OF); + final ModelConverterContextImpl c = new ModelConverterContextImpl(modelResolver); + // ModelConverters c = ModelConverters.getInstance(false, io.swagger.v3.oas.models.media.Schema.SchemaResolution.INLINE); + c.resolve(new AnnotatedType(UserSchema.class)); + + String expectedYaml = "UserProperty:\n" + + " type: object\n" + + " description: Represents a user-specific property\n" + + " example: User-specific example value\n" + + "UserSchema:\n" + + " type: object\n" + + " properties:\n" + + " propertyOne:\n" + + " allOf:\n" + + " - type: object\n" + + " description: First user schema property\n" + + " nullable: true\n" + + " - $ref: '#/components/schemas/UserProperty'\n" + + " propertyTwo:\n" + + " allOf:\n" + + " - type: object\n" + + " description: Second user schema property\n" + + " example: example value for propertyTwo\n" + + " - $ref: '#/components/schemas/UserProperty'\n" + + " propertyThree:\n" + + " allOf:\n" + + " - type: object\n" + + " description: \"Third user schema property, with example for testing\"\n" + + " example: example value for propertyThree\n" + + " - $ref: '#/components/schemas/UserProperty'\n"; + + SerializationMatchers.assertEqualsToYaml(c.getDefinedModels(), expectedYaml); + // stringSchemaMap = c.readAll(InlineSchemaSecond.class); + c.resolve(new AnnotatedType(OrderSchema.class)); + expectedYaml = "BasicProperty:\n" + + " type: object\n" + + " description: Represents a basic schema property\n" + + "OrderProperty:\n" + + " type: object\n" + + " properties:\n" + + " basicProperty:\n" + + " $ref: '#/components/schemas/BasicProperty'\n" + + " description: Represents an order-specific property\n" + + " example: Order-specific example value\n" + + "OrderSchema:\n" + + " type: object\n" + + " properties:\n" + + " propertyOne:\n" + + " allOf:\n" + + " - type: object\n" + + " description: First order schema property\n" + + " nullable: true\n" + + " - $ref: '#/components/schemas/OrderProperty'\n" + + " userProperty:\n" + + " allOf:\n" + + " - type: object\n" + + " description: \"Order schema property, references UserProperty\"\n" + + " example: example value for userProperty\n" + + " - $ref: '#/components/schemas/UserProperty'\n" + + "UserProperty:\n" + + " type: object\n" + + " description: Represents a user-specific property\n" + + " example: User-specific example value\n" + + "UserSchema:\n" + + " type: object\n" + + " properties:\n" + + " propertyOne:\n" + + " allOf:\n" + + " - type: object\n" + + " description: First user schema property\n" + + " nullable: true\n" + + " - $ref: '#/components/schemas/UserProperty'\n" + + " propertyTwo:\n" + + " allOf:\n" + + " - type: object\n" + + " description: Second user schema property\n" + + " example: example value for propertyTwo\n" + + " - $ref: '#/components/schemas/UserProperty'\n" + + " propertyThree:\n" + + " allOf:\n" + + " - type: object\n" + + " description: \"Third user schema property, with example for testing\"\n" + + " example: example value for propertyThree\n" + + " - $ref: '#/components/schemas/UserProperty'\n"; + SerializationMatchers.assertEqualsToYaml(c.getDefinedModels(), expectedYaml); + } + + // Renamed class to better describe what it represents + static class UserSchema { + + @Schema(description = "First user schema property", nullable = true) + public UserProperty propertyOne; + + private UserProperty propertyTwo; + + @Schema(description = "Second user schema property", example = "example value for propertyTwo") + public UserProperty getPropertyTwo() { + return propertyTwo; + } + + // Third property with no specific annotation. It's good to add some description or example for clarity + @Schema(description = "Third user schema property, with example for testing", example = "example value for propertyThree") + public UserProperty getPropertyThree() { + return null; // returning null as per the test scenario + } + } + + // Renamed class to represent a different entity for the schema test + static class OrderSchema { + + @Schema(description = "First order schema property", nullable = true) + public OrderProperty propertyOne; + + private UserProperty userProperty; + + @Schema(description = "Order schema property, references UserProperty", example = "example value for userProperty") + public UserProperty getUserProperty() { + return userProperty; + } + } + + // Renamed properties to make them clearer about their role in the schema + @Schema(description = "Represents a user-specific property", example = "User-specific example value") + static class UserProperty { + // public String value; + } + + @Schema(description = "Represents an order-specific property", example = "Order-specific example value") + static class OrderProperty { + public BasicProperty basicProperty; + } + + static class BasicSchema { + + @Schema(description = "First basic schema property") + public BasicProperty propertyOne; + + private BasicProperty propertyTwo; + + @Schema(description = "Second basic schema property", example = "example value for propertyTwo") + public BasicProperty getPropertyTwo() { + return propertyTwo; + } + } + + // Renamed to represent a basic property common in various schemas + @Schema(description = "Represents a basic schema property") + static class BasicProperty { + // public String value; + } +} diff --git a/modules/swagger-integration/src/main/java/io/swagger/v3/oas/integration/GenericOpenApiContext.java b/modules/swagger-integration/src/main/java/io/swagger/v3/oas/integration/GenericOpenApiContext.java index 76099eb352..27a4216144 100644 --- a/modules/swagger-integration/src/main/java/io/swagger/v3/oas/integration/GenericOpenApiContext.java +++ b/modules/swagger-integration/src/main/java/io/swagger/v3/oas/integration/GenericOpenApiContext.java @@ -552,7 +552,7 @@ public T init() throws OpenApiConfigurationException { if (objectMapperProcessor != null) { ObjectMapper mapper = IntegrationObjectMapperFactory.createJson(); objectMapperProcessor.processJsonObjectMapper(mapper); - ModelConverters.getInstance(Boolean.TRUE.equals(openApiConfiguration.isOpenAPI31())).addConverter(new ModelResolver(mapper)); + ModelConverters.getInstance(Boolean.TRUE.equals(openApiConfiguration.isOpenAPI31()), openApiConfiguration.getSchemaResolution()).addConverter(new ModelResolver(mapper)); objectMapperProcessor.processOutputJsonObjectMapper(outputJsonMapper); objectMapperProcessor.processOutputYamlObjectMapper(outputYamlMapper); diff --git a/modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/DefaultParameterExtension.java b/modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/DefaultParameterExtension.java index ed958c0a33..541dda6b52 100644 --- a/modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/DefaultParameterExtension.java +++ b/modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/DefaultParameterExtension.java @@ -120,7 +120,7 @@ public ResolvedParameter extractParameters(List annotations, annotations, components, classConsumes == null ? new String[0] : classConsumes.value(), - methodConsumes == null ? new String[0] : methodConsumes.value(), jsonViewAnnotation, openapi31); + methodConsumes == null ? new String[0] : methodConsumes.value(), jsonViewAnnotation, openapi31, this.schemaResolution); if (unknownParameter != null) { if (StringUtils.isNotBlank(unknownParameter.getIn()) && !"form".equals(unknownParameter.getIn())) { extractParametersResult.parameters.add(unknownParameter); @@ -141,7 +141,8 @@ public ResolvedParameter extractParameters(List annotations, classConsumes == null ? new String[0] : classConsumes.value(), methodConsumes == null ? new String[0] : methodConsumes.value(), jsonViewAnnotation, - openapi31); + openapi31, + this.schemaResolution); if (processedParameter != null) { extractParametersResult.parameters.add(processedParameter); } @@ -264,7 +265,9 @@ private boolean handleAdditionalAnnotation(List parameters, List parameters, List cls, final List globalParameters = new ArrayList<>(); // look for constructor-level annotated properties - globalParameters.addAll(ReaderUtils.collectConstructorParameters(cls, components, classConsumes, null)); + globalParameters.addAll(ReaderUtils.collectConstructorParameters(cls, components, classConsumes, null, config.getSchemaResolution())); // look for field-level annotated properties globalParameters.addAll(ReaderUtils.collectFieldParameters(cls, components, classConsumes, null)); @@ -1525,8 +1525,11 @@ protected ResolvedParameter getParameters(Type type, List annotation LOGGER.debug("trying extension {}", extension); extension.setOpenAPI31(Boolean.TRUE.equals(config.isOpenAPI31())); - - return extension.extractParameters(annotations, type, typesToSkip, components, classConsumes, methodConsumes, true, jsonViewAnnotation, chain); + Schema.SchemaResolution curSchemaResolution = config.getSchemaResolution(); + extension.setSchemaResolution(config.getSchemaResolution()); + ResolvedParameter resolvedParameter = extension.extractParameters(annotations, type, typesToSkip, components, classConsumes, methodConsumes, true, jsonViewAnnotation, chain); + ((SwaggerConfiguration)config).setSchemaResolution(curSchemaResolution); + return resolvedParameter; } private Set extractOperationIdFromPathItem(PathItem path) { diff --git a/modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/ext/AbstractOpenAPIExtension.java b/modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/ext/AbstractOpenAPIExtension.java index a8792d4e2a..197e248b24 100644 --- a/modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/ext/AbstractOpenAPIExtension.java +++ b/modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/ext/AbstractOpenAPIExtension.java @@ -6,6 +6,7 @@ import io.swagger.v3.jaxrs2.ResolvedParameter; import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.Operation; +import io.swagger.v3.oas.models.media.Schema; import java.lang.annotation.Annotation; import java.lang.reflect.Method; @@ -17,6 +18,7 @@ public abstract class AbstractOpenAPIExtension implements OpenAPIExtension { protected boolean openapi31; + protected Schema.SchemaResolution schemaResolution; @Override public String extractOperationMethod(Method method, Iterator chain) { @@ -68,4 +70,9 @@ protected JavaType constructType(Type type) { public void setOpenAPI31(boolean openapi31) { this.openapi31 = openapi31; } + + @Override + public void setSchemaResolution(Schema.SchemaResolution schemaResolution) { + this.schemaResolution = schemaResolution; + } } diff --git a/modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/ext/OpenAPIExtension.java b/modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/ext/OpenAPIExtension.java index d966120a0d..b82e8b581d 100644 --- a/modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/ext/OpenAPIExtension.java +++ b/modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/ext/OpenAPIExtension.java @@ -4,6 +4,7 @@ import io.swagger.v3.jaxrs2.ResolvedParameter; import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.Operation; +import io.swagger.v3.oas.models.media.Schema; import java.lang.annotation.Annotation; import java.lang.reflect.Method; @@ -31,4 +32,8 @@ ResolvedParameter extractParameters(List annotations, Type type, Set default void setOpenAPI31(boolean openapi31) { //todo: override me! } + + default void setSchemaResolution(Schema.SchemaResolution schemaResolution) { + //todo: override me! + } } diff --git a/modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/util/ReaderUtils.java b/modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/util/ReaderUtils.java index 8933a0497e..581bc0bbb4 100644 --- a/modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/util/ReaderUtils.java +++ b/modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/util/ReaderUtils.java @@ -7,6 +7,7 @@ import io.swagger.v3.jaxrs2.ext.OpenAPIExtensions; import io.swagger.v3.oas.integration.api.OpenAPIConfiguration; import io.swagger.v3.oas.models.Components; +import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.parameters.Parameter; import org.apache.commons.lang3.StringUtils; @@ -35,6 +36,9 @@ public class ReaderUtils { private static final String OPTIONS_METHOD = "options"; private static final String PATH_DELIMITER = "/"; + public static List collectConstructorParameters(Class cls, Components components, javax.ws.rs.Consumes classConsumes, JsonView jsonViewAnnotation) { + return collectConstructorParameters(cls, components, classConsumes, jsonViewAnnotation, null); + } /** * Collects constructor-level parameters from class. * @@ -42,7 +46,7 @@ public class ReaderUtils { * @param components * @return the collection of supported parameters */ - public static List collectConstructorParameters(Class cls, Components components, javax.ws.rs.Consumes classConsumes, JsonView jsonViewAnnotation) { + public static List collectConstructorParameters(Class cls, Components components, javax.ws.rs.Consumes classConsumes, JsonView jsonViewAnnotation, Schema.SchemaResolution schemaResolution) { if (cls.isLocalClass() || (cls.isMemberClass() && !Modifier.isStatic(cls.getModifiers()))) { return Collections.emptyList(); } @@ -77,7 +81,7 @@ public static List collectConstructorParameters(Class cls, Compone components, classConsumes == null ? new String[0] : classConsumes.value(), null, - jsonViewAnnotation); + jsonViewAnnotation, false, schemaResolution); if (processedParameter != null) { parameters.add(processedParameter); } diff --git a/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/ReaderTest.java b/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/ReaderTest.java index 62575c2f0e..e3ae222c2c 100644 --- a/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/ReaderTest.java +++ b/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/ReaderTest.java @@ -98,8 +98,6 @@ import io.swagger.v3.jaxrs2.resources.generics.ticket3694.Ticket3694ResourceSimpleSameReturn; import io.swagger.v3.jaxrs2.resources.rs.ProcessTokenRestService; import io.swagger.v3.jaxrs2.resources.ticket3624.Service; -import io.swagger.v3.jaxrs2.schemaResolution.SchemaResolutionResource; -import io.swagger.v3.jaxrs2.schemaResolution.SchemaResolutionResourceSimple; import io.swagger.v3.oas.annotations.enums.ParameterIn; import io.swagger.v3.oas.integration.SwaggerConfiguration; import io.swagger.v3.oas.models.Components; @@ -145,9 +143,7 @@ import java.util.Optional; import java.util.Set; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionStage; import java.util.concurrent.CopyOnWriteArrayList; -import java.util.stream.Collectors; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; @@ -4169,189 +4165,4 @@ public void test4483Response() { " type: string\n"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); } - - @Test - public void testSchemaResolution() { - ModelConverters.reset(); - Reader reader = new Reader(new SwaggerConfiguration().openAPI(new OpenAPI()).schemaResolution(Schema.SchemaResolution.INLINE)); - OpenAPI openAPI = reader.read(SchemaResolutionResource.class); - String yaml = "openapi: 3.0.1\n" + - "paths:\n" + - " /test/inlineSchemaFirst:\n" + - " get:\n" + - " operationId: inlineSchemaFirst\n" + - " responses:\n" + - " default:\n" + - " description: default response\n" + - " content:\n" + - " '*/*':\n" + - " schema:\n" + - " type: object\n" + - " properties:\n" + - " property1:\n" + - " type: object\n" + - " properties:\n" + - " bar:\n" + - " type: string\n" + - " description: InlineSchemaFirst property 1\n" + - " nullable: true\n" + - " example: example\n" + - " property2:\n" + - " type: object\n" + - " properties:\n" + - " bar:\n" + - " type: string\n" + - " description: ' InlineSchemaFirst property 2'\n" + - " example: example 2\n" + - " /test/inlineSchemaSecond:\n" + - " get:\n" + - " operationId: inlineSchemaSecond\n" + - " responses:\n" + - " default:\n" + - " description: default response\n" + - " content:\n" + - " '*/*':\n" + - " schema:\n" + - " type: object\n" + - " properties:\n" + - " foo:\n" + - " type: string\n" + - " propertySecond1:\n" + - " type: object\n" + - " properties:\n" + - " bar:\n" + - " type: object\n" + - " properties:\n" + - " property1:\n" + - " type: object\n" + - " properties:\n" + - " bar:\n" + - " type: string\n" + - " description: property 1\n" + - " property2:\n" + - " type: object\n" + - " properties:\n" + - " bar:\n" + - " type: string\n" + - " description: property 2\n" + - " example: example\n" + - " description: InlineSchemaSecond property 1\n" + - " nullable: true\n" + - " example: examplesecond\n" + - " property2:\n" + - " type: object\n" + - " properties:\n" + - " bar:\n" + - " type: string\n" + - " description: InlineSchemaSecond property 2\n" + - " example: InlineSchemaSecond example 2\n" + - "components:\n" + - " schemas:\n" + - " InlineSchemaFirst:\n" + - " type: object\n" + - " properties:\n" + - " property1:\n" + - " type: object\n" + - " properties:\n" + - " bar:\n" + - " type: string\n" + - " description: InlineSchemaFirst property 1\n" + - " nullable: true\n" + - " example: example\n" + - " property2:\n" + - " type: object\n" + - " properties:\n" + - " bar:\n" + - " type: string\n" + - " description: ' InlineSchemaFirst property 2'\n" + - " example: example 2\n" + - " InlineSchemaPropertyFirst:\n" + - " type: object\n" + - " properties:\n" + - " bar:\n" + - " type: string\n" + - " description: property\n" + - " example: example\n" + - " InlineSchemaPropertySecond:\n" + - " type: object\n" + - " properties:\n" + - " bar:\n" + - " type: object\n" + - " properties:\n" + - " property1:\n" + - " type: object\n" + - " properties:\n" + - " bar:\n" + - " type: string\n" + - " description: property 1\n" + - " property2:\n" + - " type: object\n" + - " properties:\n" + - " bar:\n" + - " type: string\n" + - " description: property 2\n" + - " example: example\n" + - " description: propertysecond\n" + - " nullable: true\n" + - " example: examplesecond\n" + - " InlineSchemaPropertySimple:\n" + - " type: object\n" + - " properties:\n" + - " bar:\n" + - " type: string\n" + - " description: property\n" + - " example: example\n" + - " InlineSchemaSecond:\n" + - " type: object\n" + - " properties:\n" + - " foo:\n" + - " type: string\n" + - " propertySecond1:\n" + - " type: object\n" + - " properties:\n" + - " bar:\n" + - " type: object\n" + - " properties:\n" + - " property1:\n" + - " type: object\n" + - " properties:\n" + - " bar:\n" + - " type: string\n" + - " description: property 1\n" + - " property2:\n" + - " type: object\n" + - " properties:\n" + - " bar:\n" + - " type: string\n" + - " description: property 2\n" + - " example: example\n" + - " description: InlineSchemaSecond property 1\n" + - " nullable: true\n" + - " example: examplesecond\n" + - " property2:\n" + - " type: object\n" + - " properties:\n" + - " bar:\n" + - " type: string\n" + - " description: InlineSchemaSecond property 2\n" + - " example: InlineSchemaSecond example 2\n" + - " InlineSchemaSimple:\n" + - " type: object\n" + - " properties:\n" + - " property1:\n" + - " type: object\n" + - " properties:\n" + - " bar:\n" + - " type: string\n" + - " description: property 1\n" + - " property2:\n" + - " type: object\n" + - " properties:\n" + - " bar:\n" + - " type: string\n" + - " description: property 2\n" + - " example: example\n\n"; - SerializationMatchers.assertEqualsToYaml(openAPI, yaml); - ModelConverters.reset(); - } } diff --git a/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/SchemaResolutionAllOfTest.java b/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/SchemaResolutionAllOfTest.java new file mode 100644 index 0000000000..4235b7aecc --- /dev/null +++ b/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/SchemaResolutionAllOfTest.java @@ -0,0 +1,60 @@ +package io.swagger.v3.jaxrs2; + +import io.swagger.v3.jaxrs2.matchers.SerializationMatchers; +import io.swagger.v3.jaxrs2.schemaResolution.SchemaResolutionResourceSimple; +import io.swagger.v3.oas.integration.SwaggerConfiguration; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.media.Schema; +import org.testng.annotations.Test; + +public class SchemaResolutionAllOfTest { + + @Test + public void testSchemaResolutionAllOf() { + Reader reader = new Reader(new SwaggerConfiguration().openAPI(new OpenAPI()).schemaResolution(Schema.SchemaResolution.ALL_OF)); + OpenAPI openAPI = reader.read(SchemaResolutionResourceSimple.class); + String yaml = "openapi: 3.0.1\n" + + "paths:\n" + + " /test/inlineSchemaFirst:\n" + + " get:\n" + + " operationId: inlineSchemaFirst\n" + + " responses:\n" + + " default:\n" + + " description: InlineSchemaFirst Response API\n" + + " content:\n" + + " '*/*':\n" + + " schema:\n" + + " $ref: '#/components/schemas/InlineSchemaFirst'\n" + + " /test/inlineSchemaSecond:\n" + + " get:\n" + + " operationId: inlineSchemaFirst_1\n" + + " requestBody:\n" + + " content:\n" + + " '*/*':\n" + + " schema:\n" + + " allOf:\n" + + " - description: InlineSchemaSecond API\n" + + " - $ref: '#/components/schemas/InlineSchemaFirst'\n" + + " responses:\n" + + " default:\n" + + " description: default response\n" + + " content:\n" + + " '*/*': {}\n" + + "components:\n" + + " schemas:\n" + + " InlineSchemaFirst:\n" + + " type: object\n" + + " properties:\n" + + " property1:\n" + + " $ref: '#/components/schemas/InlineSchemaPropertyFirst'\n" + + " InlineSchemaPropertyFirst:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: property\n" + + " nullable: true\n" + + " example: example\n"; + SerializationMatchers.assertEqualsToYaml(openAPI, yaml); + } +} diff --git a/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/SchemaResolutionInlineTest.java b/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/SchemaResolutionInlineTest.java new file mode 100644 index 0000000000..320e99b751 --- /dev/null +++ b/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/SchemaResolutionInlineTest.java @@ -0,0 +1,235 @@ +package io.swagger.v3.jaxrs2; + +import io.swagger.v3.core.converter.ModelConverters; +import io.swagger.v3.jaxrs2.matchers.SerializationMatchers; +import io.swagger.v3.jaxrs2.schemaResolution.SchemaResolutionResource; +import io.swagger.v3.oas.integration.SwaggerConfiguration; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.media.Schema; +import org.testng.annotations.Test; + +public class SchemaResolutionInlineTest { + @Test + public void testSchemaResolutionInline() { + ModelConverters.reset(); + Reader reader = new Reader(new SwaggerConfiguration().openAPI(new OpenAPI()).schemaResolution(Schema.SchemaResolution.INLINE)); + OpenAPI openAPI = reader.read(SchemaResolutionResource.class); + String yaml = "openapi: 3.0.1\n" + + "paths:\n" + + " /test/inlineSchemaFirst:\n" + + " get:\n" + + " operationId: inlineSchemaFirst\n" + + " responses:\n" + + " default:\n" + + " description: default response\n" + + " content:\n" + + " '*/*':\n" + + " schema:\n" + + " type: object\n" + + " properties:\n" + + " property1:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: InlineSchemaFirst property 1\n" + + " nullable: true\n" + + " example: example\n" + + " property2:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: ' InlineSchemaFirst property 2'\n" + + " example: example 2\n" + + " /test/inlineSchemaSecond:\n" + + " get:\n" + + " operationId: inlineSchemaSecond\n" + + " requestBody:\n" + + " content:\n" + + " '*/*':\n" + + " schema:\n" + + " type: object\n" + + " properties:\n" + + " foo:\n" + + " type: string\n" + + " propertySecond1:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: object\n" + + " properties:\n" + + " property1:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: property 1\n" + + " property2:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: property 2\n" + + " example: example\n" + + " description: InlineSchemaSecond property 1\n" + + " nullable: true\n" + + " example: examplesecond\n" + + " property2:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: InlineSchemaSecond property 2\n" + + " example: InlineSchemaSecond example 2\n" + + " description: InlineSchemaSecond API\n" + + " responses:\n" + + " default:\n" + + " description: default response\n" + + " content:\n" + + " '*/*':\n" + + " schema:\n" + + " type: object\n" + + " properties:\n" + + " foo:\n" + + " type: string\n" + + " propertySecond1:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: object\n" + + " properties:\n" + + " property1:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: property 1\n" + + " property2:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: property 2\n" + + " example: example\n" + + " description: InlineSchemaSecond property 1\n" + + " nullable: true\n" + + " example: examplesecond\n" + + " property2:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: InlineSchemaSecond property 2\n" + + " example: InlineSchemaSecond example 2\n" + + "components:\n" + + " schemas:\n" + + " InlineSchemaFirst:\n" + + " type: object\n" + + " properties:\n" + + " property1:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: InlineSchemaFirst property 1\n" + + " nullable: true\n" + + " example: example\n" + + " property2:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: ' InlineSchemaFirst property 2'\n" + + " example: example 2\n" + + " InlineSchemaPropertyFirst:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: property\n" + + " example: example\n" + + " InlineSchemaPropertySecond:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: object\n" + + " properties:\n" + + " property1:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: property 1\n" + + " property2:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: property 2\n" + + " example: example\n" + + " description: propertysecond\n" + + " nullable: true\n" + + " example: examplesecond\n" + + " InlineSchemaPropertySimple:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: property\n" + + " example: example\n" + + " InlineSchemaSecond:\n" + + " type: object\n" + + " properties:\n" + + " foo:\n" + + " type: string\n" + + " propertySecond1:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: object\n" + + " properties:\n" + + " property1:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: property 1\n" + + " property2:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: property 2\n" + + " example: example\n" + + " description: InlineSchemaSecond property 1\n" + + " nullable: true\n" + + " example: examplesecond\n" + + " property2:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: InlineSchemaSecond property 2\n" + + " example: InlineSchemaSecond example 2\n" + + " description: InlineSchemaSecond API\n" + + " InlineSchemaSimple:\n" + + " type: object\n" + + " properties:\n" + + " property1:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: property 1\n" + + " property2:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: property 2\n" + + " example: example\n\n"; + SerializationMatchers.assertEqualsToYaml(openAPI, yaml); + ModelConverters.reset(); + } +} diff --git a/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/schemaResolution/SchemaResolutionResource.java b/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/schemaResolution/SchemaResolutionResource.java index 01e691ba1e..6f909e1d44 100644 --- a/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/schemaResolution/SchemaResolutionResource.java +++ b/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/schemaResolution/SchemaResolutionResource.java @@ -9,7 +9,7 @@ public class SchemaResolutionResource { @GET @Path("/inlineSchemaSecond") - public InlineSchemaSecond inlineSchemaSecond() { + public InlineSchemaSecond inlineSchemaSecond(@Schema(description = "InlineSchemaSecond API") InlineSchemaSecond inlineSchemaSecond) { return null; } @GET diff --git a/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/schemaResolution/SchemaResolutionResourceSimple.java b/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/schemaResolution/SchemaResolutionResourceSimple.java index 61ac55e6b6..fc043bc168 100644 --- a/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/schemaResolution/SchemaResolutionResourceSimple.java +++ b/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/schemaResolution/SchemaResolutionResourceSimple.java @@ -1,20 +1,32 @@ package io.swagger.v3.jaxrs2.schemaResolution; +import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.GET; import javax.ws.rs.Path; +import javax.ws.rs.core.Response; @Path("test") public class SchemaResolutionResourceSimple { + @GET @Path("/inlineSchemaFirst") - public InlineSchemaFirst inlineSchemaFirst() { + @ApiResponse(description = "InlineSchemaFirst Response API", content = @Content(schema = @Schema(implementation = InlineSchemaFirst.class))) + public Response inlineSchemaFirst() { return null; } + @GET + @Path("/inlineSchemaSecond") + public void inlineSchemaFirst(@Schema(description = "InlineSchemaSecond API") InlineSchemaFirst inlineSchemaFirst) { + } + + + static class InlineSchemaFirst { // public String foo; diff --git a/pom.xml b/pom.xml index 355de17851..7a1473c3f8 100644 --- a/pom.xml +++ b/pom.xml @@ -654,7 +654,7 @@ 4.5.14 1.16.0 - 2.22.2 + 3.5.0 3.2.1 2.22.2 From 9b0326b7f1f05bf3ff092be45b3039092151d7e5 Mon Sep 17 00:00:00 2001 From: Victor Uria Valle Date: Sun, 14 Jul 2024 03:21:36 +0200 Subject: [PATCH 09/25] Fix thread safety in Json.mapper() (refs #4672) --- .../src/main/java/io/swagger/v3/core/util/Json.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/modules/swagger-core/src/main/java/io/swagger/v3/core/util/Json.java b/modules/swagger-core/src/main/java/io/swagger/v3/core/util/Json.java index 84c318fd62..899c7476ed 100644 --- a/modules/swagger-core/src/main/java/io/swagger/v3/core/util/Json.java +++ b/modules/swagger-core/src/main/java/io/swagger/v3/core/util/Json.java @@ -6,13 +6,12 @@ public class Json { - private static ObjectMapper mapper; + private static final class ObjectMapperHolder { + private static final ObjectMapper MAPPER = ObjectMapperFactory.createJson(); + } public static ObjectMapper mapper() { - if (mapper == null) { - mapper = ObjectMapperFactory.createJson(); - } - return mapper; + return ObjectMapperHolder.MAPPER; } public static ObjectWriter pretty() { From 516610bfd1803e88a5630d5f4680fb2e7c08ed40 Mon Sep 17 00:00:00 2001 From: frantuma Date: Mon, 23 Sep 2024 13:10:06 +0200 Subject: [PATCH 10/25] Make Jackson ObjectMapper initialization thread safe --- .../java/io/swagger/v3/core/util/Json31.java | 19 +++++++++---------- .../java/io/swagger/v3/core/util/Yaml.java | 10 +++++----- .../java/io/swagger/v3/core/util/Yaml31.java | 11 ++++++----- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/modules/swagger-core/src/main/java/io/swagger/v3/core/util/Json31.java b/modules/swagger-core/src/main/java/io/swagger/v3/core/util/Json31.java index 16a883c090..0ac52783a8 100644 --- a/modules/swagger-core/src/main/java/io/swagger/v3/core/util/Json31.java +++ b/modules/swagger-core/src/main/java/io/swagger/v3/core/util/Json31.java @@ -13,23 +13,22 @@ public class Json31 { - private static ObjectMapper mapper; - private static ObjectMapper converterMapper; + private static final class ObjectMapperHolder { + private static final ObjectMapper MAPPER = ObjectMapperFactory.createJson31(); + } + + private static final class ConverterMapperHolder { + private static final ObjectMapper MAPPER = ObjectMapperFactory.createJsonConverter(); + } static Logger LOGGER = LoggerFactory.getLogger(Json31.class); public static ObjectMapper mapper() { - if (mapper == null) { - mapper = ObjectMapperFactory.createJson31(); - } - return mapper; + return ObjectMapperHolder.MAPPER; } public static ObjectMapper converterMapper() { - if (converterMapper == null) { - converterMapper = ObjectMapperFactory.createJsonConverter(); - } - return converterMapper; + return ConverterMapperHolder.MAPPER; } public static ObjectWriter pretty() { diff --git a/modules/swagger-core/src/main/java/io/swagger/v3/core/util/Yaml.java b/modules/swagger-core/src/main/java/io/swagger/v3/core/util/Yaml.java index eaef8709fb..2a77b70305 100644 --- a/modules/swagger-core/src/main/java/io/swagger/v3/core/util/Yaml.java +++ b/modules/swagger-core/src/main/java/io/swagger/v3/core/util/Yaml.java @@ -5,13 +5,13 @@ import com.fasterxml.jackson.databind.ObjectWriter; public class Yaml { - static ObjectMapper mapper; + + private static final class ObjectMapperHolder { + private static final ObjectMapper MAPPER = ObjectMapperFactory.createYaml(); + } public static ObjectMapper mapper() { - if (mapper == null) { - mapper = ObjectMapperFactory.createYaml(); - } - return mapper; + return ObjectMapperHolder.MAPPER; } public static ObjectWriter pretty() { diff --git a/modules/swagger-core/src/main/java/io/swagger/v3/core/util/Yaml31.java b/modules/swagger-core/src/main/java/io/swagger/v3/core/util/Yaml31.java index ba16433896..75d9819a84 100644 --- a/modules/swagger-core/src/main/java/io/swagger/v3/core/util/Yaml31.java +++ b/modules/swagger-core/src/main/java/io/swagger/v3/core/util/Yaml31.java @@ -11,15 +11,16 @@ import java.util.Map; public class Yaml31 { - static ObjectMapper mapper; + + private static final class ObjectMapperHolder { + private static final ObjectMapper MAPPER = ObjectMapperFactory.createYaml31(); + } + static Logger LOGGER = LoggerFactory.getLogger(Yaml31.class); public static ObjectMapper mapper() { - if (mapper == null) { - mapper = ObjectMapperFactory.createYaml31(); - } - return mapper; + return ObjectMapperHolder.MAPPER; } public static ObjectWriter pretty() { From f868cf13004f19b5ca6ea72bb3ce8ac3018ae3f7 Mon Sep 17 00:00:00 2001 From: Dmitriy Pavlov Date: Thu, 13 Jun 2024 10:41:34 +0400 Subject: [PATCH 11/25] Removed unnecessary cast that crashes for 3.1 schema Fixes #4657 Extra: fixed yaml checks - yaml by default always uses \n separator --- .../java/io/swagger/v3/core/util/AnnotationsUtils.java | 6 +++--- .../core/serialization/OpenAPI3_1SerializationTest.java | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java b/modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java index bdfbc2e691..e4654e177c 100644 --- a/modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java +++ b/modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java @@ -849,21 +849,21 @@ public static Optional getSchemaFromAnnotation( Class[] schemaImplementations = schema.oneOf(); for (Class schemaImplementation : schemaImplementations) { Schema oneOfSchemaObject = resolveSchemaFromType(schemaImplementation, components, jsonViewAnnotation, openapi31, null, null, context); - ((ComposedSchema) schemaObject).addOneOfItem(oneOfSchemaObject); + schemaObject.addOneOfItem(oneOfSchemaObject); } } if (schema.anyOf().length > 0) { Class[] schemaImplementations = schema.anyOf(); for (Class schemaImplementation : schemaImplementations) { Schema anyOfSchemaObject = resolveSchemaFromType(schemaImplementation, components, jsonViewAnnotation, openapi31, null, null, context); - ((ComposedSchema) schemaObject).addAnyOfItem(anyOfSchemaObject); + schemaObject.addAnyOfItem(anyOfSchemaObject); } } if (schema.allOf().length > 0) { Class[] schemaImplementations = schema.allOf(); for (Class schemaImplementation : schemaImplementations) { Schema allOfSchemaObject = resolveSchemaFromType(schemaImplementation, components, jsonViewAnnotation, openapi31, null, null, context); - ((ComposedSchema) schemaObject).addAllOfItem(allOfSchemaObject); + schemaObject.addAllOfItem(allOfSchemaObject); } } if (schema.additionalProperties().equals(io.swagger.v3.oas.annotations.media.Schema.AdditionalPropertiesValue.TRUE)) { diff --git a/modules/swagger-core/src/test/java/io/swagger/v3/core/serialization/OpenAPI3_1SerializationTest.java b/modules/swagger-core/src/test/java/io/swagger/v3/core/serialization/OpenAPI3_1SerializationTest.java index 97c5d02d98..d0da2377d7 100644 --- a/modules/swagger-core/src/test/java/io/swagger/v3/core/serialization/OpenAPI3_1SerializationTest.java +++ b/modules/swagger-core/src/test/java/io/swagger/v3/core/serialization/OpenAPI3_1SerializationTest.java @@ -1468,11 +1468,11 @@ public void testBooleanAdditionalPropertiesSerialization() throws Exception{ openAPI = Yaml31.mapper().readValue(expectedYaml, OpenAPI.class); ser = Yaml31.pretty(openAPI); - assertEquals(ser, withJacksonSystemLineSeparator(expectedYaml)); + assertEquals(ser, expectedYaml); assertTrue(Boolean.TRUE.equals(openAPI.getComponents().getSchemas().get("test").getAdditionalProperties())); openAPI = Yaml.mapper().readValue(expectedYaml, OpenAPI.class); ser = Yaml.pretty(openAPI); - assertEquals(ser, withJacksonSystemLineSeparator(expectedYaml)); + assertEquals(ser, expectedYaml); assertTrue(Boolean.TRUE.equals(openAPI.getComponents().getSchemas().get("test").getAdditionalProperties())); expectedJson = "{\n" + @@ -1505,11 +1505,11 @@ public void testBooleanAdditionalPropertiesSerialization() throws Exception{ openAPI = Yaml31.mapper().readValue(expectedYaml, OpenAPI.class); ser = Yaml31.pretty(openAPI); - assertEquals(ser, withJacksonSystemLineSeparator(expectedYaml)); + assertEquals(ser, expectedYaml); assertTrue(Boolean.TRUE.equals(openAPI.getComponents().getSchemas().get("test").getAdditionalProperties())); openAPI = Yaml.mapper().readValue(expectedYaml, OpenAPI.class); ser = Yaml.pretty(openAPI); - assertEquals(ser, withJacksonSystemLineSeparator(expectedYaml)); + assertEquals(ser, expectedYaml); assertTrue(Boolean.TRUE.equals(openAPI.getComponents().getSchemas().get("test").getAdditionalProperties())); } From dbe4ecbf035a1e40657ac6118528e21bf203948a Mon Sep 17 00:00:00 2001 From: frantuma Date: Mon, 23 Sep 2024 14:10:51 +0200 Subject: [PATCH 12/25] Update dependencies --- .../pom.xml | 6 +++--- modules/swagger-maven-plugin/pom.xml | 6 +++--- .../swagger-maven-plugin-jakarta/pom.xml | 6 +++--- modules/swagger-project-jakarta/pom.xml | 20 +++++++++---------- pom.xml | 12 +++++------ 5 files changed, 25 insertions(+), 25 deletions(-) diff --git a/modules/swagger-eclipse-transformer-maven-plugin/pom.xml b/modules/swagger-eclipse-transformer-maven-plugin/pom.xml index d9f23d22fd..62b46c5dc3 100644 --- a/modules/swagger-eclipse-transformer-maven-plugin/pom.xml +++ b/modules/swagger-eclipse-transformer-maven-plugin/pom.xml @@ -13,7 +13,7 @@ swagger-eclipse-transformer-maven-plugin maven-plugin - 3.9.6 + 3.9.9 0.20 3.3.0 1.2.6 @@ -94,7 +94,7 @@ org.apache.maven.plugin-tools maven-plugin-annotations - 3.10.2 + 3.15.0 provided @@ -127,7 +127,7 @@ org.codehaus.plexus plexus-component-annotations - 2.1.1 + 2.2.0 org.apache.maven diff --git a/modules/swagger-maven-plugin/pom.xml b/modules/swagger-maven-plugin/pom.xml index e314cab31f..b85e5adc19 100644 --- a/modules/swagger-maven-plugin/pom.xml +++ b/modules/swagger-maven-plugin/pom.xml @@ -88,7 +88,7 @@ org.apache.maven.plugin-tools maven-plugin-annotations - 3.10.2 + 3.15.0 provided @@ -150,7 +150,7 @@ org.codehaus.plexus plexus-component-annotations - 2.1.1 + 2.2.0 io.swagger.core.v3 @@ -290,7 +290,7 @@ UTF-8 - 3.9.6 + 3.9.9 4.13.2 9.4.53.v20231009 1.26.1 diff --git a/modules/swagger-project-jakarta/modules/swagger-maven-plugin-jakarta/pom.xml b/modules/swagger-project-jakarta/modules/swagger-maven-plugin-jakarta/pom.xml index 67364ce61e..5eb19a186e 100644 --- a/modules/swagger-project-jakarta/modules/swagger-maven-plugin-jakarta/pom.xml +++ b/modules/swagger-project-jakarta/modules/swagger-maven-plugin-jakarta/pom.xml @@ -141,7 +141,7 @@ org.apache.maven.plugin-tools maven-plugin-annotations - 3.10.2 + 3.15.0 provided @@ -163,7 +163,7 @@ org.codehaus.plexus plexus-component-annotations - 2.1.1 + 2.2.0 @@ -176,6 +176,6 @@ UTF-8 - 3.9.6 + 3.9.9 diff --git a/modules/swagger-project-jakarta/pom.xml b/modules/swagger-project-jakarta/pom.xml index 11639bc6c5..93b92a8f3a 100644 --- a/modules/swagger-project-jakarta/pom.xml +++ b/modules/swagger-project-jakarta/pom.xml @@ -475,24 +475,24 @@ 8 2.2.3 - 2.12.7 - 2.2 + 2.13.0 + 2.3 3.1.0 - 3.0.2 + 3.1.0 3.0.1 - 2.1.2 + 2.1.3 6.4.0 5.0.0 - 3.1.5 + 3.1.8 4.13.2 2.16.2 2.16.2 - 1.5.3 - 4.8.165 + 1.5.8 + 4.8.176 32.1.3-jre 1.10.14 - 3.14.0 - 2.15.1 + 3.17.0 + 2.17.0 2.0.9 9.4.53.v20231009 7.9.0 @@ -512,7 +512,7 @@ UTF-8 https://oss.sonatype.org/content/repositories/snapshots/ 0.5.0 - 3.9.6 + 3.9.9 1.26.1 diff --git a/pom.xml b/pom.xml index 7a1473c3f8..d672f1c074 100644 --- a/pom.xml +++ b/pom.xml @@ -629,8 +629,8 @@ 8 2.2.3 - 2.12.7 - 2.2 + 2.13.0 + 2.3 2.1.6 2.3.3 1.2.2 @@ -640,12 +640,12 @@ 4.13.2 2.16.2 2.16.2 - 1.5.3 - 4.8.165 + 1.5.8 + 4.8.176 32.1.3-jre 1.10.14 - 3.14.0 - 2.15.1 + 3.17.0 + 2.17.0 2.0.9 9.4.53.v20231009 7.8.0 From 675d6bf970d9f3c6175f043b80c82407336f756d Mon Sep 17 00:00:00 2001 From: frantuma Date: Mon, 23 Sep 2024 12:29:52 +0000 Subject: [PATCH 13/25] prepare release 2.2.24 --- README.md | 5 +++-- modules/swagger-annotations/pom.xml | 2 +- modules/swagger-core/pom.xml | 2 +- .../swagger-eclipse-transformer-maven-plugin/pom.xml | 2 +- modules/swagger-gradle-plugin/README.md | 4 ++-- modules/swagger-gradle-plugin/gradle.properties | 2 +- .../io/swagger/v3/plugins/gradle/SwaggerPlugin.java | 2 +- .../v3/plugins/gradle/SwaggerResolveTest.java | 4 ++-- modules/swagger-integration/pom.xml | 2 +- .../swagger-jaxrs2-servlet-initializer-v2/pom.xml | 2 +- modules/swagger-jaxrs2-servlet-initializer/pom.xml | 2 +- modules/swagger-jaxrs2/pom.xml | 2 +- modules/swagger-maven-plugin/README.md | 12 ++++++------ modules/swagger-maven-plugin/pom.xml | 2 +- modules/swagger-models/pom.xml | 2 +- .../modules/swagger-annotations-jakarta/pom.xml | 2 +- .../modules/swagger-core-jakarta/pom.xml | 2 +- .../modules/swagger-integration-jakarta/pom.xml | 2 +- .../modules/swagger-jaxrs2-jakarta/pom.xml | 2 +- .../pom.xml | 2 +- .../pom.xml | 2 +- .../modules/swagger-maven-plugin-jakarta/pom.xml | 2 +- .../modules/swagger-models-jakarta/pom.xml | 2 +- modules/swagger-project-jakarta/pom.xml | 2 +- pom.xml | 2 +- 25 files changed, 34 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index a87ea4465f..4db0c7d06f 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,8 @@ The OpenAPI Specification has undergone several revisions since initial creation Swagger core Version | Release Date | OpenAPI Spec compatibility | Notes | Status ------------------------- | ------------ | -------------------------- | ----- | ---- -2.2.23 (**current stable**)| 2024-08-28 | 3.x | [tag v2.2.23](https://github.com/swagger-api/swagger-core/tree/v2.2.23) | Supported +2.2.24 (**current stable**)| 2024-09-23 | 3.x | [tag v2.2.24](https://github.com/swagger-api/swagger-core/tree/v2.2.24) | Supported +2.2.23 | 2024-08-28 | 3.x | [tag v2.2.23](https://github.com/swagger-api/swagger-core/tree/v2.2.23) | Supported 2.2.22 | 2024-05-15 | 3.x | [tag v2.2.22](https://github.com/swagger-api/swagger-core/tree/v2.2.22) | Supported 2.2.21 | 2024-03-20 | 3.x | [tag v2.2.21](https://github.com/swagger-api/swagger-core/tree/v2.2.21) | Supported 2.2.20 | 2023-12-19 | 3.x | [tag v2.2.20](https://github.com/swagger-api/swagger-core/tree/v2.2.20) | Supported @@ -116,7 +117,7 @@ You need the following installed and available in your $PATH: * Jackson 2.4.5 or greater -### To build from source (currently 2.2.24-SNAPSHOT) +### To build from source (currently 2.2.25-SNAPSHOT) ``` # first time building locally mvn -N diff --git a/modules/swagger-annotations/pom.xml b/modules/swagger-annotations/pom.xml index f106d90afa..f1dded4025 100644 --- a/modules/swagger-annotations/pom.xml +++ b/modules/swagger-annotations/pom.xml @@ -3,7 +3,7 @@ io.swagger.core.v3 swagger-project - 2.2.24-SNAPSHOT + 2.2.24 ../.. 4.0.0 diff --git a/modules/swagger-core/pom.xml b/modules/swagger-core/pom.xml index 4c181abdc8..dca3290989 100644 --- a/modules/swagger-core/pom.xml +++ b/modules/swagger-core/pom.xml @@ -3,7 +3,7 @@ io.swagger.core.v3 swagger-project - 2.2.24-SNAPSHOT + 2.2.24 ../.. 4.0.0 diff --git a/modules/swagger-eclipse-transformer-maven-plugin/pom.xml b/modules/swagger-eclipse-transformer-maven-plugin/pom.xml index 62b46c5dc3..3fed3f1c3c 100644 --- a/modules/swagger-eclipse-transformer-maven-plugin/pom.xml +++ b/modules/swagger-eclipse-transformer-maven-plugin/pom.xml @@ -4,7 +4,7 @@ io.swagger.core.v3 swagger-project - 2.2.24-SNAPSHOT + 2.2.24 ../.. 4.0.0 diff --git a/modules/swagger-gradle-plugin/README.md b/modules/swagger-gradle-plugin/README.md index b353bc3240..ee545bb995 100644 --- a/modules/swagger-gradle-plugin/README.md +++ b/modules/swagger-gradle-plugin/README.md @@ -26,7 +26,7 @@ Alternatively provide as value a classpath with the following dependencies (repl ``` plugins { - id "io.swagger.core.v3.swagger-gradle-plugin" version "2.2.23" + id "io.swagger.core.v3.swagger-gradle-plugin" version "2.2.24" } ``` ### Gradle 1.x and 2.0 @@ -43,7 +43,7 @@ buildscript { } } dependencies { - classpath "io.swagger.core.v3:swagger-gradle-plugin:2.2.23" + classpath "io.swagger.core.v3:swagger-gradle-plugin:2.2.24" } } diff --git a/modules/swagger-gradle-plugin/gradle.properties b/modules/swagger-gradle-plugin/gradle.properties index 34cd5d274e..04d3f3183e 100644 --- a/modules/swagger-gradle-plugin/gradle.properties +++ b/modules/swagger-gradle-plugin/gradle.properties @@ -1,2 +1,2 @@ -version=2.2.24-SNAPSHOT +version=2.2.24 jettyVersion=9.4.53.v20231009 diff --git a/modules/swagger-gradle-plugin/src/main/java/io/swagger/v3/plugins/gradle/SwaggerPlugin.java b/modules/swagger-gradle-plugin/src/main/java/io/swagger/v3/plugins/gradle/SwaggerPlugin.java index c68341250b..d0101ae81b 100644 --- a/modules/swagger-gradle-plugin/src/main/java/io/swagger/v3/plugins/gradle/SwaggerPlugin.java +++ b/modules/swagger-gradle-plugin/src/main/java/io/swagger/v3/plugins/gradle/SwaggerPlugin.java @@ -16,7 +16,7 @@ public void apply(Project project) { config.defaultDependencies(new Action() { public void execute(DependencySet dependencies) { dependencies.add(project.getDependencies().create("org.apache.commons:commons-lang3:3.12.0")); - dependencies.add(project.getDependencies().create("io.swagger.core.v3:swagger-jaxrs2:2.2.24-SNAPSHOT")); + dependencies.add(project.getDependencies().create("io.swagger.core.v3:swagger-jaxrs2:2.2.24")); dependencies.add(project.getDependencies().create("javax.ws.rs:javax.ws.rs-api:2.1")); dependencies.add(project.getDependencies().create("javax.servlet:javax.servlet-api:3.1.0")); } diff --git a/modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/SwaggerResolveTest.java b/modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/SwaggerResolveTest.java index 9768aa6c97..fd59f06623 100644 --- a/modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/SwaggerResolveTest.java +++ b/modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/SwaggerResolveTest.java @@ -81,7 +81,7 @@ public void testSwaggerResolveTask() throws IOException { " mavenCentral()\n" + "}\n" + "dependencies { \n" + - " implementation 'io.swagger.core.v3:swagger-jaxrs2:2.2.24-SNAPSHOT'\n" + + " implementation 'io.swagger.core.v3:swagger-jaxrs2:2.2.24'\n" + " implementation 'javax.ws.rs:javax.ws.rs-api:2.1'\n" + " implementation 'javax.servlet:javax.servlet-api:3.1.0'\n" + " testImplementation 'com.github.tomakehurst:wiremock:2.27.2'\n" + @@ -154,7 +154,7 @@ public void testSwaggerResolveWithOAS31OptionTask() throws IOException { " mavenCentral()\n" + "}\n" + "dependencies { \n" + - " implementation 'io.swagger.core.v3:swagger-jaxrs2:2.2.24-SNAPSHOT'\n" + + " implementation 'io.swagger.core.v3:swagger-jaxrs2:2.2.24'\n" + " implementation 'javax.ws.rs:javax.ws.rs-api:2.1'\n" + " implementation 'javax.servlet:javax.servlet-api:3.1.0'\n" + " testImplementation 'com.github.tomakehurst:wiremock:2.27.2'\n" + diff --git a/modules/swagger-integration/pom.xml b/modules/swagger-integration/pom.xml index 55383f6672..d7b211a42d 100644 --- a/modules/swagger-integration/pom.xml +++ b/modules/swagger-integration/pom.xml @@ -6,7 +6,7 @@ io.swagger.core.v3 swagger-project - 2.2.24-SNAPSHOT + 2.2.24 ../.. swagger-integration diff --git a/modules/swagger-jaxrs2-servlet-initializer-v2/pom.xml b/modules/swagger-jaxrs2-servlet-initializer-v2/pom.xml index cebc663de5..369396e16f 100644 --- a/modules/swagger-jaxrs2-servlet-initializer-v2/pom.xml +++ b/modules/swagger-jaxrs2-servlet-initializer-v2/pom.xml @@ -5,7 +5,7 @@ swagger-project io.swagger.core.v3 - 2.2.24-SNAPSHOT + 2.2.24 ../../ 4.0.0 diff --git a/modules/swagger-jaxrs2-servlet-initializer/pom.xml b/modules/swagger-jaxrs2-servlet-initializer/pom.xml index e90c67d2d3..21527e0cc9 100644 --- a/modules/swagger-jaxrs2-servlet-initializer/pom.xml +++ b/modules/swagger-jaxrs2-servlet-initializer/pom.xml @@ -5,7 +5,7 @@ swagger-project io.swagger.core.v3 - 2.2.24-SNAPSHOT + 2.2.24 ../../ 4.0.0 diff --git a/modules/swagger-jaxrs2/pom.xml b/modules/swagger-jaxrs2/pom.xml index 43a4a18c20..e7281645e7 100644 --- a/modules/swagger-jaxrs2/pom.xml +++ b/modules/swagger-jaxrs2/pom.xml @@ -5,7 +5,7 @@ swagger-project io.swagger.core.v3 - 2.2.24-SNAPSHOT + 2.2.24 ../../ 4.0.0 diff --git a/modules/swagger-maven-plugin/README.md b/modules/swagger-maven-plugin/README.md index 1e76742b2b..aab1b1931d 100644 --- a/modules/swagger-maven-plugin/README.md +++ b/modules/swagger-maven-plugin/README.md @@ -22,7 +22,7 @@ Both `javax` and `jakarta` examples are provided below io.swagger.core.v3 swagger-maven-plugin - 2.2.23 + 2.2.24 openapi ${project.build.directory}/generatedtest @@ -47,7 +47,7 @@ Both `javax` and `jakarta` examples are provided below io.swagger.core.v3 swagger-jaxrs2 - 2.2.23 + 2.2.24 @@ -73,7 +73,7 @@ Both `javax` and `jakarta` examples are provided below io.swagger.core.v3 swagger-maven-plugin-jakarta - 2.2.23 + 2.2.24 openapi ${project.build.directory}/generatedtest @@ -98,7 +98,7 @@ Both `javax` and `jakarta` examples are provided below io.swagger.core.v3 swagger-jaxrs2-jakarta - 2.2.23 + 2.2.24 @@ -126,7 +126,7 @@ Both `javax` and `jakarta` examples are provided below io.swagger.core.v3 swagger-maven-plugin - 2.2.23 + 2.2.24 openapi ${project.build.directory}/generatedtest @@ -155,7 +155,7 @@ Both `javax` and `jakarta` examples are provided below io.swagger.core.v3 swagger-maven-plugin-jakarta - 2.2.23 + 2.2.24 openapi ${project.build.directory}/generatedtest diff --git a/modules/swagger-maven-plugin/pom.xml b/modules/swagger-maven-plugin/pom.xml index b85e5adc19..2e5a47bc9a 100644 --- a/modules/swagger-maven-plugin/pom.xml +++ b/modules/swagger-maven-plugin/pom.xml @@ -4,7 +4,7 @@ io.swagger.core.v3 swagger-project - 2.2.24-SNAPSHOT + 2.2.24 ../.. 4.0.0 diff --git a/modules/swagger-models/pom.xml b/modules/swagger-models/pom.xml index 3b0cabbe4e..32c5045a6f 100644 --- a/modules/swagger-models/pom.xml +++ b/modules/swagger-models/pom.xml @@ -4,7 +4,7 @@ io.swagger.core.v3 swagger-project - 2.2.24-SNAPSHOT + 2.2.24 ../.. 4.0.0 diff --git a/modules/swagger-project-jakarta/modules/swagger-annotations-jakarta/pom.xml b/modules/swagger-project-jakarta/modules/swagger-annotations-jakarta/pom.xml index caf6327b60..d70b9f3caf 100644 --- a/modules/swagger-project-jakarta/modules/swagger-annotations-jakarta/pom.xml +++ b/modules/swagger-project-jakarta/modules/swagger-annotations-jakarta/pom.xml @@ -4,7 +4,7 @@ io.swagger.core.v3 swagger-project-jakarta - 2.2.24-SNAPSHOT + 2.2.24 ../.. 4.0.0 diff --git a/modules/swagger-project-jakarta/modules/swagger-core-jakarta/pom.xml b/modules/swagger-project-jakarta/modules/swagger-core-jakarta/pom.xml index 896ca77849..e239b0b6ab 100644 --- a/modules/swagger-project-jakarta/modules/swagger-core-jakarta/pom.xml +++ b/modules/swagger-project-jakarta/modules/swagger-core-jakarta/pom.xml @@ -4,7 +4,7 @@ io.swagger.core.v3 swagger-project-jakarta - 2.2.24-SNAPSHOT + 2.2.24 ../.. 4.0.0 diff --git a/modules/swagger-project-jakarta/modules/swagger-integration-jakarta/pom.xml b/modules/swagger-project-jakarta/modules/swagger-integration-jakarta/pom.xml index d9091ea7d8..d72487b9d9 100644 --- a/modules/swagger-project-jakarta/modules/swagger-integration-jakarta/pom.xml +++ b/modules/swagger-project-jakarta/modules/swagger-integration-jakarta/pom.xml @@ -4,7 +4,7 @@ io.swagger.core.v3 swagger-project-jakarta - 2.2.24-SNAPSHOT + 2.2.24 ../.. 4.0.0 diff --git a/modules/swagger-project-jakarta/modules/swagger-jaxrs2-jakarta/pom.xml b/modules/swagger-project-jakarta/modules/swagger-jaxrs2-jakarta/pom.xml index 044997af99..9ef639431a 100644 --- a/modules/swagger-project-jakarta/modules/swagger-jaxrs2-jakarta/pom.xml +++ b/modules/swagger-project-jakarta/modules/swagger-jaxrs2-jakarta/pom.xml @@ -4,7 +4,7 @@ io.swagger.core.v3 swagger-project-jakarta - 2.2.24-SNAPSHOT + 2.2.24 ../.. 4.0.0 diff --git a/modules/swagger-project-jakarta/modules/swagger-jaxrs2-servlet-initializer-jakarta/pom.xml b/modules/swagger-project-jakarta/modules/swagger-jaxrs2-servlet-initializer-jakarta/pom.xml index ecd6390232..2e9b73fce1 100644 --- a/modules/swagger-project-jakarta/modules/swagger-jaxrs2-servlet-initializer-jakarta/pom.xml +++ b/modules/swagger-project-jakarta/modules/swagger-jaxrs2-servlet-initializer-jakarta/pom.xml @@ -4,7 +4,7 @@ io.swagger.core.v3 swagger-project-jakarta - 2.2.24-SNAPSHOT + 2.2.24 ../.. 4.0.0 diff --git a/modules/swagger-project-jakarta/modules/swagger-jaxrs2-servlet-initializer-v2-jakarta/pom.xml b/modules/swagger-project-jakarta/modules/swagger-jaxrs2-servlet-initializer-v2-jakarta/pom.xml index 0d2a616115..c577f70032 100644 --- a/modules/swagger-project-jakarta/modules/swagger-jaxrs2-servlet-initializer-v2-jakarta/pom.xml +++ b/modules/swagger-project-jakarta/modules/swagger-jaxrs2-servlet-initializer-v2-jakarta/pom.xml @@ -4,7 +4,7 @@ io.swagger.core.v3 swagger-project-jakarta - 2.2.24-SNAPSHOT + 2.2.24 ../.. 4.0.0 diff --git a/modules/swagger-project-jakarta/modules/swagger-maven-plugin-jakarta/pom.xml b/modules/swagger-project-jakarta/modules/swagger-maven-plugin-jakarta/pom.xml index 5eb19a186e..9fcb4a5b92 100644 --- a/modules/swagger-project-jakarta/modules/swagger-maven-plugin-jakarta/pom.xml +++ b/modules/swagger-project-jakarta/modules/swagger-maven-plugin-jakarta/pom.xml @@ -4,7 +4,7 @@ io.swagger.core.v3 swagger-project-jakarta - 2.2.24-SNAPSHOT + 2.2.24 ../.. 4.0.0 diff --git a/modules/swagger-project-jakarta/modules/swagger-models-jakarta/pom.xml b/modules/swagger-project-jakarta/modules/swagger-models-jakarta/pom.xml index c9bce80e88..08ff43e536 100644 --- a/modules/swagger-project-jakarta/modules/swagger-models-jakarta/pom.xml +++ b/modules/swagger-project-jakarta/modules/swagger-models-jakarta/pom.xml @@ -4,7 +4,7 @@ io.swagger.core.v3 swagger-project-jakarta - 2.2.24-SNAPSHOT + 2.2.24 ../.. 4.0.0 diff --git a/modules/swagger-project-jakarta/pom.xml b/modules/swagger-project-jakarta/pom.xml index 93b92a8f3a..ac90bf86cc 100644 --- a/modules/swagger-project-jakarta/pom.xml +++ b/modules/swagger-project-jakarta/pom.xml @@ -6,7 +6,7 @@ pom swagger-project-jakarta swagger-project-jakarta - 2.2.24-SNAPSHOT + 2.2.24 https://github.com/swagger-api/swagger-core scm:git:git@github.com:swagger-api/swagger-core.git diff --git a/pom.xml b/pom.xml index d672f1c074..0177f4f3dc 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ pom swagger-project swagger-project - 2.2.24-SNAPSHOT + 2.2.24 https://github.com/swagger-api/swagger-core scm:git:git@github.com:swagger-api/swagger-core.git From 24fca016b28d3f8363b29471312d3678a0f7a542 Mon Sep 17 00:00:00 2001 From: frantuma Date: Mon, 23 Sep 2024 12:46:26 +0000 Subject: [PATCH 14/25] bump snapshot 2.2.25-SNAPSHOT --- modules/swagger-annotations/pom.xml | 2 +- modules/swagger-core/pom.xml | 2 +- modules/swagger-eclipse-transformer-maven-plugin/pom.xml | 2 +- modules/swagger-gradle-plugin/gradle.properties | 2 +- .../main/java/io/swagger/v3/plugins/gradle/SwaggerPlugin.java | 2 +- .../java/io/swagger/v3/plugins/gradle/SwaggerResolveTest.java | 4 ++-- modules/swagger-integration/pom.xml | 2 +- modules/swagger-jaxrs2-servlet-initializer-v2/pom.xml | 2 +- modules/swagger-jaxrs2-servlet-initializer/pom.xml | 2 +- modules/swagger-jaxrs2/pom.xml | 2 +- modules/swagger-maven-plugin/pom.xml | 2 +- modules/swagger-models/pom.xml | 2 +- .../modules/swagger-annotations-jakarta/pom.xml | 2 +- .../modules/swagger-core-jakarta/pom.xml | 2 +- .../modules/swagger-integration-jakarta/pom.xml | 2 +- .../modules/swagger-jaxrs2-jakarta/pom.xml | 2 +- .../swagger-jaxrs2-servlet-initializer-jakarta/pom.xml | 2 +- .../swagger-jaxrs2-servlet-initializer-v2-jakarta/pom.xml | 2 +- .../modules/swagger-maven-plugin-jakarta/pom.xml | 2 +- .../modules/swagger-models-jakarta/pom.xml | 2 +- modules/swagger-project-jakarta/pom.xml | 2 +- pom.xml | 2 +- 22 files changed, 23 insertions(+), 23 deletions(-) diff --git a/modules/swagger-annotations/pom.xml b/modules/swagger-annotations/pom.xml index f1dded4025..c563ed56be 100644 --- a/modules/swagger-annotations/pom.xml +++ b/modules/swagger-annotations/pom.xml @@ -3,7 +3,7 @@ io.swagger.core.v3 swagger-project - 2.2.24 + 2.2.25-SNAPSHOT ../.. 4.0.0 diff --git a/modules/swagger-core/pom.xml b/modules/swagger-core/pom.xml index dca3290989..38dd64a970 100644 --- a/modules/swagger-core/pom.xml +++ b/modules/swagger-core/pom.xml @@ -3,7 +3,7 @@ io.swagger.core.v3 swagger-project - 2.2.24 + 2.2.25-SNAPSHOT ../.. 4.0.0 diff --git a/modules/swagger-eclipse-transformer-maven-plugin/pom.xml b/modules/swagger-eclipse-transformer-maven-plugin/pom.xml index 3fed3f1c3c..344092265c 100644 --- a/modules/swagger-eclipse-transformer-maven-plugin/pom.xml +++ b/modules/swagger-eclipse-transformer-maven-plugin/pom.xml @@ -4,7 +4,7 @@ io.swagger.core.v3 swagger-project - 2.2.24 + 2.2.25-SNAPSHOT ../.. 4.0.0 diff --git a/modules/swagger-gradle-plugin/gradle.properties b/modules/swagger-gradle-plugin/gradle.properties index 04d3f3183e..5255de4e81 100644 --- a/modules/swagger-gradle-plugin/gradle.properties +++ b/modules/swagger-gradle-plugin/gradle.properties @@ -1,2 +1,2 @@ -version=2.2.24 +version=2.2.25-SNAPSHOT jettyVersion=9.4.53.v20231009 diff --git a/modules/swagger-gradle-plugin/src/main/java/io/swagger/v3/plugins/gradle/SwaggerPlugin.java b/modules/swagger-gradle-plugin/src/main/java/io/swagger/v3/plugins/gradle/SwaggerPlugin.java index d0101ae81b..bb84ad9523 100644 --- a/modules/swagger-gradle-plugin/src/main/java/io/swagger/v3/plugins/gradle/SwaggerPlugin.java +++ b/modules/swagger-gradle-plugin/src/main/java/io/swagger/v3/plugins/gradle/SwaggerPlugin.java @@ -16,7 +16,7 @@ public void apply(Project project) { config.defaultDependencies(new Action() { public void execute(DependencySet dependencies) { dependencies.add(project.getDependencies().create("org.apache.commons:commons-lang3:3.12.0")); - dependencies.add(project.getDependencies().create("io.swagger.core.v3:swagger-jaxrs2:2.2.24")); + dependencies.add(project.getDependencies().create("io.swagger.core.v3:swagger-jaxrs2:2.2.25-SNAPSHOT")); dependencies.add(project.getDependencies().create("javax.ws.rs:javax.ws.rs-api:2.1")); dependencies.add(project.getDependencies().create("javax.servlet:javax.servlet-api:3.1.0")); } diff --git a/modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/SwaggerResolveTest.java b/modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/SwaggerResolveTest.java index fd59f06623..b08cd781bd 100644 --- a/modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/SwaggerResolveTest.java +++ b/modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/SwaggerResolveTest.java @@ -81,7 +81,7 @@ public void testSwaggerResolveTask() throws IOException { " mavenCentral()\n" + "}\n" + "dependencies { \n" + - " implementation 'io.swagger.core.v3:swagger-jaxrs2:2.2.24'\n" + + " implementation 'io.swagger.core.v3:swagger-jaxrs2:2.2.25-SNAPSHOT'\n" + " implementation 'javax.ws.rs:javax.ws.rs-api:2.1'\n" + " implementation 'javax.servlet:javax.servlet-api:3.1.0'\n" + " testImplementation 'com.github.tomakehurst:wiremock:2.27.2'\n" + @@ -154,7 +154,7 @@ public void testSwaggerResolveWithOAS31OptionTask() throws IOException { " mavenCentral()\n" + "}\n" + "dependencies { \n" + - " implementation 'io.swagger.core.v3:swagger-jaxrs2:2.2.24'\n" + + " implementation 'io.swagger.core.v3:swagger-jaxrs2:2.2.25-SNAPSHOT'\n" + " implementation 'javax.ws.rs:javax.ws.rs-api:2.1'\n" + " implementation 'javax.servlet:javax.servlet-api:3.1.0'\n" + " testImplementation 'com.github.tomakehurst:wiremock:2.27.2'\n" + diff --git a/modules/swagger-integration/pom.xml b/modules/swagger-integration/pom.xml index d7b211a42d..2f09522c04 100644 --- a/modules/swagger-integration/pom.xml +++ b/modules/swagger-integration/pom.xml @@ -6,7 +6,7 @@ io.swagger.core.v3 swagger-project - 2.2.24 + 2.2.25-SNAPSHOT ../.. swagger-integration diff --git a/modules/swagger-jaxrs2-servlet-initializer-v2/pom.xml b/modules/swagger-jaxrs2-servlet-initializer-v2/pom.xml index 369396e16f..13e2782106 100644 --- a/modules/swagger-jaxrs2-servlet-initializer-v2/pom.xml +++ b/modules/swagger-jaxrs2-servlet-initializer-v2/pom.xml @@ -5,7 +5,7 @@ swagger-project io.swagger.core.v3 - 2.2.24 + 2.2.25-SNAPSHOT ../../ 4.0.0 diff --git a/modules/swagger-jaxrs2-servlet-initializer/pom.xml b/modules/swagger-jaxrs2-servlet-initializer/pom.xml index 21527e0cc9..f539b91a88 100644 --- a/modules/swagger-jaxrs2-servlet-initializer/pom.xml +++ b/modules/swagger-jaxrs2-servlet-initializer/pom.xml @@ -5,7 +5,7 @@ swagger-project io.swagger.core.v3 - 2.2.24 + 2.2.25-SNAPSHOT ../../ 4.0.0 diff --git a/modules/swagger-jaxrs2/pom.xml b/modules/swagger-jaxrs2/pom.xml index e7281645e7..45c6887658 100644 --- a/modules/swagger-jaxrs2/pom.xml +++ b/modules/swagger-jaxrs2/pom.xml @@ -5,7 +5,7 @@ swagger-project io.swagger.core.v3 - 2.2.24 + 2.2.25-SNAPSHOT ../../ 4.0.0 diff --git a/modules/swagger-maven-plugin/pom.xml b/modules/swagger-maven-plugin/pom.xml index 2e5a47bc9a..c8a4ab7d9b 100644 --- a/modules/swagger-maven-plugin/pom.xml +++ b/modules/swagger-maven-plugin/pom.xml @@ -4,7 +4,7 @@ io.swagger.core.v3 swagger-project - 2.2.24 + 2.2.25-SNAPSHOT ../.. 4.0.0 diff --git a/modules/swagger-models/pom.xml b/modules/swagger-models/pom.xml index 32c5045a6f..6c26b3cb84 100644 --- a/modules/swagger-models/pom.xml +++ b/modules/swagger-models/pom.xml @@ -4,7 +4,7 @@ io.swagger.core.v3 swagger-project - 2.2.24 + 2.2.25-SNAPSHOT ../.. 4.0.0 diff --git a/modules/swagger-project-jakarta/modules/swagger-annotations-jakarta/pom.xml b/modules/swagger-project-jakarta/modules/swagger-annotations-jakarta/pom.xml index d70b9f3caf..119ff9a8b0 100644 --- a/modules/swagger-project-jakarta/modules/swagger-annotations-jakarta/pom.xml +++ b/modules/swagger-project-jakarta/modules/swagger-annotations-jakarta/pom.xml @@ -4,7 +4,7 @@ io.swagger.core.v3 swagger-project-jakarta - 2.2.24 + 2.2.25-SNAPSHOT ../.. 4.0.0 diff --git a/modules/swagger-project-jakarta/modules/swagger-core-jakarta/pom.xml b/modules/swagger-project-jakarta/modules/swagger-core-jakarta/pom.xml index e239b0b6ab..44d028fd66 100644 --- a/modules/swagger-project-jakarta/modules/swagger-core-jakarta/pom.xml +++ b/modules/swagger-project-jakarta/modules/swagger-core-jakarta/pom.xml @@ -4,7 +4,7 @@ io.swagger.core.v3 swagger-project-jakarta - 2.2.24 + 2.2.25-SNAPSHOT ../.. 4.0.0 diff --git a/modules/swagger-project-jakarta/modules/swagger-integration-jakarta/pom.xml b/modules/swagger-project-jakarta/modules/swagger-integration-jakarta/pom.xml index d72487b9d9..8a0698762a 100644 --- a/modules/swagger-project-jakarta/modules/swagger-integration-jakarta/pom.xml +++ b/modules/swagger-project-jakarta/modules/swagger-integration-jakarta/pom.xml @@ -4,7 +4,7 @@ io.swagger.core.v3 swagger-project-jakarta - 2.2.24 + 2.2.25-SNAPSHOT ../.. 4.0.0 diff --git a/modules/swagger-project-jakarta/modules/swagger-jaxrs2-jakarta/pom.xml b/modules/swagger-project-jakarta/modules/swagger-jaxrs2-jakarta/pom.xml index 9ef639431a..e1c14fac70 100644 --- a/modules/swagger-project-jakarta/modules/swagger-jaxrs2-jakarta/pom.xml +++ b/modules/swagger-project-jakarta/modules/swagger-jaxrs2-jakarta/pom.xml @@ -4,7 +4,7 @@ io.swagger.core.v3 swagger-project-jakarta - 2.2.24 + 2.2.25-SNAPSHOT ../.. 4.0.0 diff --git a/modules/swagger-project-jakarta/modules/swagger-jaxrs2-servlet-initializer-jakarta/pom.xml b/modules/swagger-project-jakarta/modules/swagger-jaxrs2-servlet-initializer-jakarta/pom.xml index 2e9b73fce1..c0c0e1f361 100644 --- a/modules/swagger-project-jakarta/modules/swagger-jaxrs2-servlet-initializer-jakarta/pom.xml +++ b/modules/swagger-project-jakarta/modules/swagger-jaxrs2-servlet-initializer-jakarta/pom.xml @@ -4,7 +4,7 @@ io.swagger.core.v3 swagger-project-jakarta - 2.2.24 + 2.2.25-SNAPSHOT ../.. 4.0.0 diff --git a/modules/swagger-project-jakarta/modules/swagger-jaxrs2-servlet-initializer-v2-jakarta/pom.xml b/modules/swagger-project-jakarta/modules/swagger-jaxrs2-servlet-initializer-v2-jakarta/pom.xml index c577f70032..f50ce23682 100644 --- a/modules/swagger-project-jakarta/modules/swagger-jaxrs2-servlet-initializer-v2-jakarta/pom.xml +++ b/modules/swagger-project-jakarta/modules/swagger-jaxrs2-servlet-initializer-v2-jakarta/pom.xml @@ -4,7 +4,7 @@ io.swagger.core.v3 swagger-project-jakarta - 2.2.24 + 2.2.25-SNAPSHOT ../.. 4.0.0 diff --git a/modules/swagger-project-jakarta/modules/swagger-maven-plugin-jakarta/pom.xml b/modules/swagger-project-jakarta/modules/swagger-maven-plugin-jakarta/pom.xml index 9fcb4a5b92..6bf09650e5 100644 --- a/modules/swagger-project-jakarta/modules/swagger-maven-plugin-jakarta/pom.xml +++ b/modules/swagger-project-jakarta/modules/swagger-maven-plugin-jakarta/pom.xml @@ -4,7 +4,7 @@ io.swagger.core.v3 swagger-project-jakarta - 2.2.24 + 2.2.25-SNAPSHOT ../.. 4.0.0 diff --git a/modules/swagger-project-jakarta/modules/swagger-models-jakarta/pom.xml b/modules/swagger-project-jakarta/modules/swagger-models-jakarta/pom.xml index 08ff43e536..6edc084255 100644 --- a/modules/swagger-project-jakarta/modules/swagger-models-jakarta/pom.xml +++ b/modules/swagger-project-jakarta/modules/swagger-models-jakarta/pom.xml @@ -4,7 +4,7 @@ io.swagger.core.v3 swagger-project-jakarta - 2.2.24 + 2.2.25-SNAPSHOT ../.. 4.0.0 diff --git a/modules/swagger-project-jakarta/pom.xml b/modules/swagger-project-jakarta/pom.xml index ac90bf86cc..78178d194e 100644 --- a/modules/swagger-project-jakarta/pom.xml +++ b/modules/swagger-project-jakarta/pom.xml @@ -6,7 +6,7 @@ pom swagger-project-jakarta swagger-project-jakarta - 2.2.24 + 2.2.25-SNAPSHOT https://github.com/swagger-api/swagger-core scm:git:git@github.com:swagger-api/swagger-core.git diff --git a/pom.xml b/pom.xml index 0177f4f3dc..c04f364181 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ pom swagger-project swagger-project - 2.2.24 + 2.2.25-SNAPSHOT https://github.com/swagger-api/swagger-core scm:git:git@github.com:swagger-api/swagger-core.git From 744f28384ac0baabbdd24d7a23c19b652f6e7c73 Mon Sep 17 00:00:00 2001 From: frantuma Date: Tue, 24 Sep 2024 13:40:52 +0200 Subject: [PATCH 15/25] add schemaResolution to readme --- modules/swagger-gradle-plugin/README.md | 7 +++- modules/swagger-maven-plugin/README.md | 52 +++++++++++++------------ 2 files changed, 34 insertions(+), 25 deletions(-) diff --git a/modules/swagger-gradle-plugin/README.md b/modules/swagger-gradle-plugin/README.md index ee545bb995..70ba27b9c4 100644 --- a/modules/swagger-gradle-plugin/README.md +++ b/modules/swagger-gradle-plugin/README.md @@ -97,6 +97,8 @@ Parameter | Description | Required | Default `contextId`|see [Context](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#context)|false| `outputPath`|**DEPRECATED** output path where file(s) are saved|false| `defaultResponseCode`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)|false| +`openapi31`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)| false | +`schemaResolution`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)| DEFAULT | **Note** parameter `openApiFile` corresponds to [config](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties) openAPI. It points to a location of a file in YAML or JSON format representing the input spec that will be merged with the resolved spec. Typically used to add Info section, or any other meta data. An example of such file: @@ -121,5 +123,8 @@ info: Since version 2.1.6, `sortOutput` parameter is available, allowing to sort object properties and map keys alphabetically. Since version 2.1.6, `objectMapperProcessorClass` allows to configure also the ObjectMapper instance used to serialize the resolved OpenAPI Since version 2.1.9, `alwaysResolveAppPath` parameter is available, allowing to trigger resolving of Application Path from annotation also not in runtime (e.g. using servlet in separate application, or in maven plugin at build time, etc) +Since version 2.2.12, `openapi31` parameter is available, if set to true the resolved spec will be processed into a 3.1.0 specification by resolving according to OAS 3.1 rules Since version 2.1.15, `skipResolveAppPath` parameter is available, allowing to skip resolving of Application Path from annotation -Since version 2.2.17, `defaultResponseCode` parameter is available, allowing to set the code used when resolving responses with no http status code annotation \ No newline at end of file +Since version 2.2.17, `defaultResponseCode` parameter is available, allowing to set the code used when resolving responses with no http status code annotation +Since version 2.2.17, `defaultResponseCode` parameter is available, allowing to set the code used when resolving responses with no http status code annotation +Since version 2.2.24, `schemaResolution` parameter is available, allowing to specify how object schemas and object properties within schemas are resolved for OAS 3.0 specification \ No newline at end of file diff --git a/modules/swagger-maven-plugin/README.md b/modules/swagger-maven-plugin/README.md index aab1b1931d..81ec2fdb07 100644 --- a/modules/swagger-maven-plugin/README.md +++ b/modules/swagger-maven-plugin/README.md @@ -177,29 +177,31 @@ Both `javax` and `jakarta` examples are provided below #### Parameters Parameter | Description | Required | Default ---------- | ----------- | --------- | ------- -`outputPath`|output path where file(s) are saved|true| -`outputFileName`|file name (no extension)|false|`openapi` -`outputFormat`|file format (`JSON`, `YAML`, `JSONANDYAML`|false|`JSON` -`skip`|if `TRUE` skip execution|false|`FALSE` -`encoding`|encoding of output file(s)|false| -`resourcePackages`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)|false| -`resourceClasses`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)|false| -`prettyPrint`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)|false|`TRUE` -`sortOutput`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)|false|`FALSE` -`alwaysResolveAppPath`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)|false|`FALSE` -`skipResolveAppPath`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)|false|`FALSE` -`openapiFilePath`|path to openapi file to be merged with resolved specification, see [config](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)|false| -`configurationFilePath`|path to swagger config file to be merged with resolved specification, see [config](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration)|false| -`filterClass`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)|false| -`readerClass`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)|false| -`scannerClass`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)|false| -`readAllResources`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)|false| -`ignoredRoutes`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)|false| -`objectMapperProcessorClass`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)|false| -`defaultResponseCode`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)|false| -`modelConverterClasses`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)|false| -`contextId`|see [Context](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#context)|false|${project.artifactId} +--------- | ----------- |---------| ------- +`outputPath`|output path where file(s) are saved| true | +`outputFileName`|file name (no extension)| false |`openapi` +`outputFormat`|file format (`JSON`, `YAML`, `JSONANDYAML`| false |`JSON` +`skip`|if `TRUE` skip execution| false |`FALSE` +`encoding`|encoding of output file(s)| false | +`resourcePackages`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)| false | +`resourceClasses`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)| false | +`prettyPrint`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)| false |`TRUE` +`sortOutput`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)| false |`FALSE` +`alwaysResolveAppPath`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)| false |`FALSE` +`skipResolveAppPath`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)| false |`FALSE` +`openapiFilePath`|path to openapi file to be merged with resolved specification, see [config](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)| false | +`configurationFilePath`|path to swagger config file to be merged with resolved specification, see [config](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration)| false | +`filterClass`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)| false | +`readerClass`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)| false | +`scannerClass`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)| false | +`readAllResources`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)| false | +`ignoredRoutes`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)| false | +`objectMapperProcessorClass`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)| false | +`defaultResponseCode`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)| false | +`modelConverterClasses`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)| false | +`contextId`|see [Context](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#context)| false |${project.artifactId} +`openapi31`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)| false | +`schemaResolution`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)| DEFAULT | *** @@ -207,6 +209,8 @@ Since version 2.0.8, `configurationFilePath` parameter is available, allowing to Since version 2.1.6, `sortOutput` parameter is available, allowing to sort object properties and map keys alphabetically. Since version 2.1.6, `objectMapperProcessorClass` allows to configure also the ObjectMapper instance used to serialize the resolved OpenAPI -Since version 2.1.9, `alwaysResolveAppPath` parameter is available, allowing to trigger resolving of Application Path from annotaion also not in runtime (e.g. using servlet in separate application, or in maven plugin at build time, etc) +Since version 2.1.9, `alwaysResolveAppPath` parameter is available, allowing to trigger resolving of Application Path from annotation also not in runtime (e.g. using servlet in separate application, or in maven plugin at build time, etc) +Since version 2.2.12, `openapi31` parameter is available, if set to true the resolved spec will be processed into a 3.1.0 specification by resolving according to OAS 3.1 rules Since version 2.1.15, `skipResolveAppPath` parameter is available, allowing to skip resolving of Application Path from annotation Since version 2.2.17, `defaultResponseCode` parameter is available, allowing to set the code used when resolving responses with no http status code annotation +Since version 2.2.24, `schemaResolution` parameter is available, allowing to specify how object schemas and object properties within schemas are resolved for OAS 3.0 specification \ No newline at end of file From 9f57589ae350fd5ad0a2c990a235988bb23b913b Mon Sep 17 00:00:00 2001 From: frantuma Date: Thu, 26 Sep 2024 13:12:12 +0200 Subject: [PATCH 16/25] schema resolution options - Phase 3: global all-of-ref --- .../v3/core/jackson/ModelResolver.java | 21 +++- .../v3/core/util/AnnotationsUtils.java | 2 +- .../v3/core/util/ParameterProcessor.java | 9 +- modules/swagger-jaxrs2/pom.xml | 3 +- .../jaxrs2/SchemaResolutionAllOfRefTest.java | 112 ++++++++++++++++++ .../swagger/v3/oas/models/media/Schema.java | 5 +- 6 files changed, 141 insertions(+), 11 deletions(-) create mode 100644 modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/SchemaResolutionAllOfRefTest.java diff --git a/modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/ModelResolver.java b/modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/ModelResolver.java index dc9e74add1..3f6c15f94a 100644 --- a/modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/ModelResolver.java +++ b/modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/ModelResolver.java @@ -682,7 +682,10 @@ public Schema resolve(AnnotatedType annotatedType, ModelConverterContext context Annotation[] ctxAnnotation31 = null; - if (Schema.SchemaResolution.ALL_OF.equals(this.schemaResolution) || openapi31) { + if ( + Schema.SchemaResolution.ALL_OF.equals(this.schemaResolution) || + Schema.SchemaResolution.ALL_OF_REF.equals(this.schemaResolution) || + openapi31) { List ctxAnnotations31List = new ArrayList<>(); if (annotations != null) { for (Annotation a : annotations) { @@ -692,8 +695,8 @@ public Schema resolve(AnnotatedType annotatedType, ModelConverterContext context ctxAnnotations31List.add(a); } if ((ctxSchema != null) && (!ctxSchema.implementation().equals(Void.class) || StringUtils.isNotEmpty(ctxSchema.type()))) { - ctxAnnotations31List.add(a); - } + ctxAnnotations31List.add(a); + } } ctxAnnotation31 = ctxAnnotations31List.toArray(new Annotation[ctxAnnotations31List.size()]); } @@ -708,7 +711,10 @@ public Schema resolve(AnnotatedType annotatedType, ModelConverterContext context .schemaProperty(true) .components(annotatedType.getComponents()) .propertyName(propName); - if (Schema.SchemaResolution.ALL_OF.equals(this.schemaResolution) || openapi31) { + if ( + Schema.SchemaResolution.ALL_OF.equals(this.schemaResolution) || + Schema.SchemaResolution.ALL_OF_REF.equals(this.schemaResolution) || + openapi31) { aType.ctxAnnotations(ctxAnnotation31); } else { aType.ctxAnnotations(annotations); @@ -740,7 +746,7 @@ public Schema resolve(AnnotatedType annotatedType, ModelConverterContext context property = reResolvedProperty.get(); } - } else if (Schema.SchemaResolution.ALL_OF.equals(this.schemaResolution)) { + } else if (Schema.SchemaResolution.ALL_OF.equals(this.schemaResolution) || Schema.SchemaResolution.ALL_OF_REF.equals(this.schemaResolution)) { Optional reResolvedProperty = AnnotationsUtils.getSchemaFromAnnotation(ctxSchema, annotatedType.getComponents(), null, openapi31, null, schemaResolution, context); if (reResolvedProperty.isPresent()) { ctxProperty = reResolvedProperty.get(); @@ -795,6 +801,8 @@ public Schema resolve(AnnotatedType annotatedType, ModelConverterContext context property = new Schema() .addAllOfItem(ctxProperty) .addAllOfItem(new Schema().$ref(constructRef(pName))); + } else if (Schema.SchemaResolution.ALL_OF_REF.equals(this.schemaResolution) && ctxProperty != null) { + property = ctxProperty.addAllOfItem(new Schema().$ref(constructRef(pName))); } else { property = new Schema().$ref(constructRef(pName)); } @@ -817,6 +825,9 @@ public Schema resolve(AnnotatedType annotatedType, ModelConverterContext context property = new Schema() .addAllOfItem(ctxProperty) .addAllOfItem(new Schema().$ref(StringUtils.isNotEmpty(property.get$ref()) ? property.get$ref() : property.getName())); + } else if (Schema.SchemaResolution.ALL_OF_REF.equals(this.schemaResolution) && ctxProperty != null) { + property = ctxProperty + .addAllOfItem(new Schema().$ref(StringUtils.isNotEmpty(property.get$ref()) ? property.get$ref() : property.getName())); } else { property = new Schema().$ref(StringUtils.isNotEmpty(property.get$ref()) ? property.get$ref() : property.getName()); } diff --git a/modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java b/modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java index e4654e177c..bfd909a494 100644 --- a/modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java +++ b/modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java @@ -621,7 +621,7 @@ public static Optional getSchemaFromAnnotation( } else { schemaObject = new Schema(); } - } else if (Schema.SchemaResolution.ALL_OF.equals(schemaResolution)) { + } else if (Schema.SchemaResolution.ALL_OF.equals(schemaResolution) || Schema.SchemaResolution.ALL_OF_REF.equals(schemaResolution)) { if (existingSchema == null) { schemaObject = new Schema(); } else { diff --git a/modules/swagger-core/src/main/java/io/swagger/v3/core/util/ParameterProcessor.java b/modules/swagger-core/src/main/java/io/swagger/v3/core/util/ParameterProcessor.java index d219d52a55..18e1277328 100644 --- a/modules/swagger-core/src/main/java/io/swagger/v3/core/util/ParameterProcessor.java +++ b/modules/swagger-core/src/main/java/io/swagger/v3/core/util/ParameterProcessor.java @@ -76,7 +76,7 @@ public static Parameter applyAnnotations( io.swagger.v3.oas.annotations.media.ArraySchema ctxArraySchema = AnnotationsUtils.getArraySchemaAnnotation(annotations.toArray(new Annotation[0])); Annotation[] ctxAnnotation31 = null; - if (Schema.SchemaResolution.ALL_OF.equals(schemaResolution)) { + if (Schema.SchemaResolution.ALL_OF.equals(schemaResolution) || Schema.SchemaResolution.ALL_OF_REF.equals(schemaResolution)) { List ctxAnnotations31List = new ArrayList<>(); if (annotations != null) { for (Annotation a : annotations) { @@ -95,7 +95,7 @@ public static Parameter applyAnnotations( .skipOverride(true) .jsonViewAnnotation(jsonViewAnnotation); - if (Schema.SchemaResolution.ALL_OF.equals(schemaResolution)) { + if (Schema.SchemaResolution.ALL_OF.equals(schemaResolution) || Schema.SchemaResolution.ALL_OF_REF.equals(schemaResolution)) { annotatedType.ctxAnnotations(ctxAnnotation31); } else { annotatedType.ctxAnnotations(reworkedAnnotations.toArray(new Annotation[reworkedAnnotations.size()])); @@ -106,7 +106,7 @@ public static Parameter applyAnnotations( if (resolvedSchema.schema != null) { Schema resSchema = AnnotationsUtils.clone(resolvedSchema.schema, openapi31); Schema ctxSchemaObject = null; - if (Schema.SchemaResolution.ALL_OF.equals(schemaResolution)) { + if (Schema.SchemaResolution.ALL_OF.equals(schemaResolution) || Schema.SchemaResolution.ALL_OF_REF.equals(schemaResolution)) { Optional reResolvedSchema = AnnotationsUtils.getSchemaFromAnnotation(ctxSchema, annotatedType.getComponents(), null, openapi31, null, schemaResolution, null); if (reResolvedSchema.isPresent()) { ctxSchemaObject = reResolvedSchema.get(); @@ -121,6 +121,9 @@ public static Parameter applyAnnotations( resSchema = new Schema() .addAllOfItem(ctxSchemaObject) .addAllOfItem(resolvedSchema.schema); + } else if (Schema.SchemaResolution.ALL_OF_REF.equals(schemaResolution) && ctxSchemaObject != null) { + resSchema = ctxSchemaObject + .addAllOfItem(resolvedSchema.schema); } parameter.setSchema(resSchema); } diff --git a/modules/swagger-jaxrs2/pom.xml b/modules/swagger-jaxrs2/pom.xml index 45c6887658..985108505b 100644 --- a/modules/swagger-jaxrs2/pom.xml +++ b/modules/swagger-jaxrs2/pom.xml @@ -96,7 +96,8 @@ maven-surefire-plugin ${surefire-version} - --add-opens java.base/java.lang=ALL-UNNAMED + -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005 --add-opens java.base/java.lang=ALL-UNNAMED + 0 diff --git a/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/SchemaResolutionAllOfRefTest.java b/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/SchemaResolutionAllOfRefTest.java new file mode 100644 index 0000000000..f2a5cb29eb --- /dev/null +++ b/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/SchemaResolutionAllOfRefTest.java @@ -0,0 +1,112 @@ +package io.swagger.v3.jaxrs2; + +import io.swagger.v3.core.converter.ModelConverters; +import io.swagger.v3.jaxrs2.matchers.SerializationMatchers; +import io.swagger.v3.jaxrs2.schemaResolution.SchemaResolutionResource; +import io.swagger.v3.oas.integration.SwaggerConfiguration; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.media.Schema; +import org.testng.annotations.Test; + +public class SchemaResolutionAllOfRefTest { + + @Test + public void testSchemaResolutionAllOfRef() { + ModelConverters.reset(); + Reader reader = new Reader(new SwaggerConfiguration().openAPI(new OpenAPI()).schemaResolution(Schema.SchemaResolution.ALL_OF_REF)); + OpenAPI openAPI = reader.read(SchemaResolutionResource.class); + String yaml = "openapi: 3.0.1\n" + + "paths:\n" + + " /test/inlineSchemaFirst:\n" + + " get:\n" + + " operationId: inlineSchemaFirst\n" + + " responses:\n" + + " default:\n" + + " description: default response\n" + + " content:\n" + + " '*/*':\n" + + " schema:\n" + + " $ref: \"#/components/schemas/InlineSchemaFirst\"\n" + + " /test/inlineSchemaSecond:\n" + + " get:\n" + + " operationId: inlineSchemaSecond\n" + + " requestBody:\n" + + " content:\n" + + " '*/*':\n" + + " schema:\n" + + " description: InlineSchemaSecond API\n" + + " allOf:\n" + + " - $ref: \"#/components/schemas/InlineSchemaSecond\"\n" + + " responses:\n" + + " default:\n" + + " description: default response\n" + + " content:\n" + + " '*/*':\n" + + " schema:\n" + + " $ref: \"#/components/schemas/InlineSchemaSecond\"\n" + + "components:\n" + + " schemas:\n" + + " InlineSchemaFirst:\n" + + " type: object\n" + + " properties:\n" + + " property1:\n" + + " description: InlineSchemaFirst property 1\n" + + " nullable: true\n" + + " allOf:\n" + + " - $ref: \"#/components/schemas/InlineSchemaPropertyFirst\"\n" + + " property2:\n" + + " description: ' InlineSchemaFirst property 2'\n" + + " example: example 2\n" + + " allOf:\n" + + " - $ref: \"#/components/schemas/InlineSchemaPropertyFirst\"\n" + + " InlineSchemaPropertyFirst:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: property\n" + + " example: example\n" + + " InlineSchemaPropertySecond:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " $ref: \"#/components/schemas/InlineSchemaSimple\"\n" + + " description: propertysecond\n" + + " example: examplesecond\n" + + " InlineSchemaPropertySimple:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: property\n" + + " InlineSchemaSecond:\n" + + " type: object\n" + + " properties:\n" + + " foo:\n" + + " type: string\n" + + " propertySecond1:\n" + + " description: InlineSchemaSecond property 1\n" + + " nullable: true\n" + + " allOf:\n" + + " - $ref: \"#/components/schemas/InlineSchemaPropertySecond\"\n" + + " property2:\n" + + " description: InlineSchemaSecond property 2\n" + + " example: InlineSchemaSecond example 2\n" + + " allOf:\n" + + " - $ref: \"#/components/schemas/InlineSchemaPropertyFirst\"\n" + + " InlineSchemaSimple:\n" + + " type: object\n" + + " properties:\n" + + " property1:\n" + + " description: property 1\n" + + " allOf:\n" + + " - $ref: \"#/components/schemas/InlineSchemaPropertySimple\"\n" + + " property2:\n" + + " description: property 2\n" + + " example: example\n" + + " allOf:\n" + + " - $ref: \"#/components/schemas/InlineSchemaPropertySimple\"\n"; + SerializationMatchers.assertEqualsToYaml(openAPI, yaml); + ModelConverters.reset(); + } +} diff --git a/modules/swagger-models/src/main/java/io/swagger/v3/oas/models/media/Schema.java b/modules/swagger-models/src/main/java/io/swagger/v3/oas/models/media/Schema.java index 8f76ad9ce8..d17c2a4f62 100644 --- a/modules/swagger-models/src/main/java/io/swagger/v3/oas/models/media/Schema.java +++ b/modules/swagger-models/src/main/java/io/swagger/v3/oas/models/media/Schema.java @@ -52,7 +52,10 @@ public enum SchemaResolution { @JsonProperty("inline") INLINE("inline"), @JsonProperty("all-of") - ALL_OF("all-of"); + ALL_OF("all-of"), + @JsonProperty("all-of-ref") + ALL_OF_REF("all-of-ref"); + private String value; SchemaResolution(String value) { From dd028ca60fc818e20b0f8e449fd4c98efa650cd7 Mon Sep 17 00:00:00 2001 From: frantuma Date: Wed, 2 Oct 2024 13:33:54 +0200 Subject: [PATCH 17/25] schema resolution options - Phase 4: granular schema resolution via @Schema.schemaResolution --- .../v3/oas/annotations/media/Schema.java | 21 ++++ .../v3/core/jackson/ModelResolver.java | 28 +++-- .../v3/core/util/AnnotationsUtils.java | 15 +++ .../SchemaResolutionAnnotationTest.java | 117 ++++++++++++++++++ .../SchemaResolutionAnnotatedResource.java | 83 +++++++++++++ ...hemaResolutionAnnotatedSimpleResource.java | 32 +++++ 6 files changed, 283 insertions(+), 13 deletions(-) create mode 100644 modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/SchemaResolutionAnnotationTest.java create mode 100644 modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/schemaResolution/SchemaResolutionAnnotatedResource.java create mode 100644 modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/schemaResolution/SchemaResolutionAnnotatedSimpleResource.java diff --git a/modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/media/Schema.java b/modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/media/Schema.java index b5d02b0a83..6d1e9223b6 100644 --- a/modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/media/Schema.java +++ b/modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/media/Schema.java @@ -554,6 +554,14 @@ enum RequiredMode { NOT_REQUIRED; } + enum SchemaResolution { + AUTO, + DEFAULT, + INLINE, + ALL_OF, + ALL_OF_REF; + } + /** * Allows to specify the dependentRequired value ** @@ -616,4 +624,17 @@ enum RequiredMode { */ @OpenAPI31 String _const() default ""; + + /** + * Allows to specify the schema resolution mode for object schemas + * + * SchemaResolution.DEFAULT: bundled into components/schemas, $ref with no siblings + * SchemaResolution.INLINE: inline schema, no $ref + * SchemaResolution.ALL_OF: bundled into components/schemas, $ref and any context annotation resolution into allOf + * SchemaResolution.ALL_OF_REF: bundled into components/schemas, $ref into allOf, context annotation resolution into root + * + * @return the schema resolution mode for this schema + * + */ + SchemaResolution schemaResolution() default SchemaResolution.AUTO; } diff --git a/modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/ModelResolver.java b/modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/ModelResolver.java index 3f6c15f94a..011a6d3676 100644 --- a/modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/ModelResolver.java +++ b/modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/ModelResolver.java @@ -681,10 +681,10 @@ public Schema resolve(AnnotatedType annotatedType, ModelConverterContext context io.swagger.v3.oas.annotations.media.Schema.RequiredMode requiredMode = resolveRequiredMode(propResolvedSchemaAnnotation); Annotation[] ctxAnnotation31 = null; - + Schema.SchemaResolution resolvedSchemaResolution = AnnotationsUtils.resolveSchemaResolution(this.schemaResolution, ctxSchema); if ( - Schema.SchemaResolution.ALL_OF.equals(this.schemaResolution) || - Schema.SchemaResolution.ALL_OF_REF.equals(this.schemaResolution) || + Schema.SchemaResolution.ALL_OF.equals(resolvedSchemaResolution) || + Schema.SchemaResolution.ALL_OF_REF.equals(resolvedSchemaResolution) || openapi31) { List ctxAnnotations31List = new ArrayList<>(); if (annotations != null) { @@ -712,8 +712,8 @@ public Schema resolve(AnnotatedType annotatedType, ModelConverterContext context .components(annotatedType.getComponents()) .propertyName(propName); if ( - Schema.SchemaResolution.ALL_OF.equals(this.schemaResolution) || - Schema.SchemaResolution.ALL_OF_REF.equals(this.schemaResolution) || + Schema.SchemaResolution.ALL_OF.equals(resolvedSchemaResolution) || + Schema.SchemaResolution.ALL_OF_REF.equals(resolvedSchemaResolution) || openapi31) { aType.ctxAnnotations(ctxAnnotation31); } else { @@ -746,7 +746,7 @@ public Schema resolve(AnnotatedType annotatedType, ModelConverterContext context property = reResolvedProperty.get(); } - } else if (Schema.SchemaResolution.ALL_OF.equals(this.schemaResolution) || Schema.SchemaResolution.ALL_OF_REF.equals(this.schemaResolution)) { + } else if (Schema.SchemaResolution.ALL_OF.equals(resolvedSchemaResolution) || Schema.SchemaResolution.ALL_OF_REF.equals(resolvedSchemaResolution)) { Optional reResolvedProperty = AnnotationsUtils.getSchemaFromAnnotation(ctxSchema, annotatedType.getComponents(), null, openapi31, null, schemaResolution, context); if (reResolvedProperty.isPresent()) { ctxProperty = reResolvedProperty.get(); @@ -795,20 +795,20 @@ public Schema resolve(AnnotatedType annotatedType, ModelConverterContext context } if (context.getDefinedModels().containsKey(pName)) { - if (Schema.SchemaResolution.INLINE.equals(this.schemaResolution)) { + if (Schema.SchemaResolution.INLINE.equals(resolvedSchemaResolution)) { property = context.getDefinedModels().get(pName); - } else if (Schema.SchemaResolution.ALL_OF.equals(this.schemaResolution) && ctxProperty != null) { + } else if (Schema.SchemaResolution.ALL_OF.equals(resolvedSchemaResolution) && ctxProperty != null) { property = new Schema() .addAllOfItem(ctxProperty) .addAllOfItem(new Schema().$ref(constructRef(pName))); - } else if (Schema.SchemaResolution.ALL_OF_REF.equals(this.schemaResolution) && ctxProperty != null) { + } else if (Schema.SchemaResolution.ALL_OF_REF.equals(resolvedSchemaResolution) && ctxProperty != null) { property = ctxProperty.addAllOfItem(new Schema().$ref(constructRef(pName))); } else { property = new Schema().$ref(constructRef(pName)); } property = clone(property); // TODO: why is this needed? is it not handled before? - if (openapi31 || Schema.SchemaResolution.INLINE.equals(this.schemaResolution)) { + if (openapi31 || Schema.SchemaResolution.INLINE.equals(resolvedSchemaResolution)) { Optional reResolvedProperty = AnnotationsUtils.getSchemaFromAnnotation(ctxSchema, annotatedType.getComponents(), null, openapi31, property, this.schemaResolution, context); if (reResolvedProperty.isPresent()) { property = reResolvedProperty.get(); @@ -821,11 +821,11 @@ public Schema resolve(AnnotatedType annotatedType, ModelConverterContext context } } else if (property.get$ref() != null) { if (!openapi31) { - if (Schema.SchemaResolution.ALL_OF.equals(this.schemaResolution) && ctxProperty != null) { + if (Schema.SchemaResolution.ALL_OF.equals(resolvedSchemaResolution) && ctxProperty != null) { property = new Schema() .addAllOfItem(ctxProperty) .addAllOfItem(new Schema().$ref(StringUtils.isNotEmpty(property.get$ref()) ? property.get$ref() : property.getName())); - } else if (Schema.SchemaResolution.ALL_OF_REF.equals(this.schemaResolution) && ctxProperty != null) { + } else if (Schema.SchemaResolution.ALL_OF_REF.equals(resolvedSchemaResolution) && ctxProperty != null) { property = ctxProperty .addAllOfItem(new Schema().$ref(StringUtils.isNotEmpty(property.get$ref()) ? property.get$ref() : property.getName())); } else { @@ -1040,12 +1040,14 @@ public Schema resolve(AnnotatedType annotatedType, ModelConverterContext context context.defineModel(name, model, annotatedType, null); } + Schema.SchemaResolution resolvedSchemaResolution = AnnotationsUtils.resolveSchemaResolution(this.schemaResolution, resolvedSchemaAnnotation); + if (model != null && annotatedType.isResolveAsRef() && (isComposedSchema || isObjectSchema(model)) && StringUtils.isNotBlank(model.getName())) { if (context.getDefinedModels().containsKey(model.getName())) { - if (!Schema.SchemaResolution.INLINE.equals(this.schemaResolution)) { + if (!Schema.SchemaResolution.INLINE.equals(resolvedSchemaResolution)) { model = new Schema().$ref(constructRef(model.getName())); } } diff --git a/modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java b/modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java index bfd909a494..cb26009e0a 100644 --- a/modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java +++ b/modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java @@ -2658,6 +2658,15 @@ public Class additionalPropertiesSchema() { return patch.additionalPropertiesSchema(); } + /* We always want the patch to take precedence in schema resolution behavior */ + @Override + public SchemaResolution schemaResolution() { + if (!patch.schemaResolution().equals(SchemaResolution.DEFAULT) || master.schemaResolution().equals(SchemaResolution.DEFAULT)) { + return patch.schemaResolution(); + } + return master.schemaResolution(); + } + }; return (io.swagger.v3.oas.annotations.media.Schema)schema; @@ -2874,4 +2883,10 @@ public io.swagger.v3.oas.annotations.media.Schema[] prefixItems() { return (io.swagger.v3.oas.annotations.media.ArraySchema)newArraySchema; } + public static Schema.SchemaResolution resolveSchemaResolution(Schema.SchemaResolution globalSchemaResolution, io.swagger.v3.oas.annotations.media.Schema schemaAnnotation) { + if (schemaAnnotation != null && !io.swagger.v3.oas.annotations.media.Schema.SchemaResolution.AUTO.equals(schemaAnnotation.schemaResolution())) { + return Schema.SchemaResolution.valueOf(schemaAnnotation.schemaResolution().toString()); + } + return globalSchemaResolution; + } } diff --git a/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/SchemaResolutionAnnotationTest.java b/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/SchemaResolutionAnnotationTest.java new file mode 100644 index 0000000000..c5e77c3492 --- /dev/null +++ b/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/SchemaResolutionAnnotationTest.java @@ -0,0 +1,117 @@ +package io.swagger.v3.jaxrs2; + +import io.swagger.v3.core.converter.ModelConverters; +import io.swagger.v3.jaxrs2.matchers.SerializationMatchers; +import io.swagger.v3.jaxrs2.schemaResolution.SchemaResolutionAnnotatedResource; +import io.swagger.v3.oas.integration.SwaggerConfiguration; +import io.swagger.v3.oas.models.OpenAPI; +import org.testng.annotations.Test; + +public class SchemaResolutionAnnotationTest { + + @Test + public void testSchemaResolutionAnnotation() { + ModelConverters.reset(); + Reader reader = new Reader(new SwaggerConfiguration().openAPI(new OpenAPI())); + OpenAPI openAPI = reader.read(SchemaResolutionAnnotatedResource.class); + String yaml = "openapi: 3.0.1\n" + + "paths:\n" + + " /test/inlineSchemaFirst:\n" + + " get:\n" + + " operationId: inlineSchemaFirst\n" + + " responses:\n" + + " default:\n" + + " description: default response\n" + + " content:\n" + + " '*/*':\n" + + " schema:\n" + + " $ref: '#/components/schemas/InlineSchemaFirst'\n" + + " /test/inlineSchemaSecond:\n" + + " get:\n" + + " operationId: inlineSchemaSecond\n" + + " requestBody:\n" + + " content:\n" + + " '*/*':\n" + + " schema:\n" + + " type: object\n" + + " properties:\n" + + " foo:\n" + + " type: string\n" + + " propertySecond1:\n" + + " $ref: '#/components/schemas/InlineSchemaPropertySecond'\n" + + " property2:\n" + + " $ref: '#/components/schemas/InlineSchemaPropertyFirst'\n" + + " description: InlineSchemaSecond API\n" + + " responses:\n" + + " default:\n" + + " description: default response\n" + + " content:\n" + + " '*/*':\n" + + " schema:\n" + + " $ref: '#/components/schemas/InlineSchemaSecond'\n" + + "components:\n" + + " schemas:\n" + + " InlineSchemaFirst:\n" + + " type: object\n" + + " properties:\n" + + " property1:\n" + + " description: InlineSchemaFirst property 1\n" + + " nullable: true\n" + + " allOf:\n" + + " - $ref: '#/components/schemas/InlineSchemaPropertyFirst'\n" + + " property2:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: property\n" + + " example: example\n" + + " InlineSchemaPropertyFirst:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: property\n" + + " example: example\n" + + " InlineSchemaPropertySecond:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " $ref: '#/components/schemas/InlineSchemaSimple'\n" + + " description: propertysecond\n" + + " nullable: true\n" + + " example: examplesecond\n" + + " InlineSchemaPropertySimple:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: property\n" + + " InlineSchemaSecond:\n" + + " type: object\n" + + " properties:\n" + + " foo:\n" + + " type: string\n" + + " propertySecond1:\n" + + " $ref: '#/components/schemas/InlineSchemaPropertySecond'\n" + + " property2:\n" + + " $ref: '#/components/schemas/InlineSchemaPropertyFirst'\n" + + " description: InlineSchemaSecond API\n" + + " InlineSchemaSimple:\n" + + " type: object\n" + + " properties:\n" + + " property1:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: property\n" + + " property2:\n" + + " description: property 2\n" + + " example: example\n" + + " allOf:\n" + + " - $ref: '#/components/schemas/InlineSchemaPropertySimple'\n"; + SerializationMatchers.assertEqualsToYaml(openAPI, yaml); + ModelConverters.reset(); + } +} diff --git a/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/schemaResolution/SchemaResolutionAnnotatedResource.java b/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/schemaResolution/SchemaResolutionAnnotatedResource.java new file mode 100644 index 0000000000..575e374752 --- /dev/null +++ b/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/schemaResolution/SchemaResolutionAnnotatedResource.java @@ -0,0 +1,83 @@ +package io.swagger.v3.jaxrs2.schemaResolution; + +import io.swagger.v3.oas.annotations.media.Schema; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; + +@Path("test") +public class SchemaResolutionAnnotatedResource { + + @GET + @Path("/inlineSchemaSecond") + public InlineSchemaSecond inlineSchemaSecond(@Schema(description = "InlineSchemaSecond API", schemaResolution = Schema.SchemaResolution.INLINE) InlineSchemaSecond inlineSchemaSecond) { + return null; + } + @GET + @Path("/inlineSchemaFirst") + public InlineSchemaFirst inlineSchemaFirst() { + return null; + } + + + static class InlineSchemaFirst { + + // public String foo; + + @Schema(description = "InlineSchemaFirst property 1", nullable = true, schemaResolution = Schema.SchemaResolution.ALL_OF_REF) + public InlineSchemaPropertyFirst property1; + + + private InlineSchemaPropertyFirst property2; + + @Schema(description = " InlineSchemaFirst property 2", example = "example 2", schemaResolution = Schema.SchemaResolution.INLINE) + public InlineSchemaPropertyFirst getProperty2() { + return null; + } + } + + static class InlineSchemaSecond { + + public String foo; + + @Schema(description = "InlineSchemaSecond property 1", nullable = true) + public InlineSchemaPropertySecond propertySecond1; + + + private InlineSchemaPropertyFirst property2; + + @Schema(description = "InlineSchemaSecond property 2", example = "InlineSchemaSecond example 2") + public InlineSchemaPropertyFirst getProperty2() { + return null; + } + } + + @Schema(description = "property", example = "example") + static class InlineSchemaPropertyFirst { + public String bar; + } + + @Schema(description = "propertysecond", example = "examplesecond") + static class InlineSchemaPropertySecond { + public InlineSchemaSimple bar; + } + + static class InlineSchemaSimple { + + @Schema(description = "property 1", schemaResolution = Schema.SchemaResolution.INLINE) + public InlineSchemaPropertySimple property1; + + + private InlineSchemaPropertySimple property2; + + @Schema(description = "property 2", example = "example", schemaResolution = Schema.SchemaResolution.ALL_OF_REF) + public InlineSchemaPropertySimple getProperty2() { + return null; + } + } + + @Schema(description = "property") + static class InlineSchemaPropertySimple { + public String bar; + } +} diff --git a/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/schemaResolution/SchemaResolutionAnnotatedSimpleResource.java b/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/schemaResolution/SchemaResolutionAnnotatedSimpleResource.java new file mode 100644 index 0000000000..013dd4d26e --- /dev/null +++ b/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/schemaResolution/SchemaResolutionAnnotatedSimpleResource.java @@ -0,0 +1,32 @@ +package io.swagger.v3.jaxrs2.schemaResolution; + +import io.swagger.v3.oas.annotations.media.Schema; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; + +@Path("test") +public class SchemaResolutionAnnotatedSimpleResource { + + @GET + @Path("/inlineSchemaFirst") + public InlineSchemaFirst inlineSchemaFirst() { + return null; + } + + + static class InlineSchemaFirst { + + private InlineSchemaPropertyFirst property2; + + @Schema(description = " InlineSchemaFirst property 2", example = "example 2", schemaResolution = Schema.SchemaResolution.INLINE) + public InlineSchemaPropertyFirst getProperty2() { + return null; + } + } + + @Schema(description = "property", example = "example") + static class InlineSchemaPropertyFirst { + // public String bar; + } +} From 2a88599250be4781810e1b21941ca68616bea985 Mon Sep 17 00:00:00 2001 From: Ruslan Gazizov <86663214+ruslangazizov@users.noreply.github.com> Date: Fri, 4 Aug 2023 13:24:03 +0300 Subject: [PATCH 18/25] Update Schema.java --- .../main/java/io/swagger/v3/oas/annotations/media/Schema.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/media/Schema.java b/modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/media/Schema.java index 6d1e9223b6..0ba732c6e5 100644 --- a/modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/media/Schema.java +++ b/modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/media/Schema.java @@ -237,7 +237,7 @@ boolean writeOnly() default false; /** - * Allows to specify the access mode (AccessMode.READ_ONLY, READ_WRITE) + * Allows to specify the access mode (AccessMode.READ_ONLY, WRITE_ONLY, READ_WRITE) * * AccessMode.READ_ONLY: value will not be written to during a request but may be returned during a response. * AccessMode.WRITE_ONLY: value will only be written to during a request but not returned during a response. @@ -246,7 +246,7 @@ * @return the accessMode for this schema (property) * */ - AccessMode accessMode() default AccessMode.AUTO; + AccessMode accessMode() default AccessMode.AUTO; /** * Provides an example of the schema. When associated with a specific media type, the example string shall be parsed by the consumer to be treated as an object or an array. From 1cd887bb77900ec7d885e821477328a91b1cae7c Mon Sep 17 00:00:00 2001 From: frantuma Date: Wed, 2 Oct 2024 12:06:10 +0000 Subject: [PATCH 19/25] prepare release 2.2.25 --- README.md | 5 +++-- modules/swagger-annotations/pom.xml | 2 +- modules/swagger-core/pom.xml | 2 +- .../swagger-eclipse-transformer-maven-plugin/pom.xml | 2 +- modules/swagger-gradle-plugin/README.md | 4 ++-- modules/swagger-gradle-plugin/gradle.properties | 2 +- .../io/swagger/v3/plugins/gradle/SwaggerPlugin.java | 2 +- .../v3/plugins/gradle/SwaggerResolveTest.java | 4 ++-- modules/swagger-integration/pom.xml | 2 +- .../swagger-jaxrs2-servlet-initializer-v2/pom.xml | 2 +- modules/swagger-jaxrs2-servlet-initializer/pom.xml | 2 +- modules/swagger-jaxrs2/pom.xml | 2 +- modules/swagger-maven-plugin/README.md | 12 ++++++------ modules/swagger-maven-plugin/pom.xml | 2 +- modules/swagger-models/pom.xml | 2 +- .../modules/swagger-annotations-jakarta/pom.xml | 2 +- .../modules/swagger-core-jakarta/pom.xml | 2 +- .../modules/swagger-integration-jakarta/pom.xml | 2 +- .../modules/swagger-jaxrs2-jakarta/pom.xml | 2 +- .../pom.xml | 2 +- .../pom.xml | 2 +- .../modules/swagger-maven-plugin-jakarta/pom.xml | 2 +- .../modules/swagger-models-jakarta/pom.xml | 2 +- modules/swagger-project-jakarta/pom.xml | 2 +- pom.xml | 2 +- 25 files changed, 34 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index 4db0c7d06f..db90aa5c35 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,8 @@ The OpenAPI Specification has undergone several revisions since initial creation Swagger core Version | Release Date | OpenAPI Spec compatibility | Notes | Status ------------------------- | ------------ | -------------------------- | ----- | ---- -2.2.24 (**current stable**)| 2024-09-23 | 3.x | [tag v2.2.24](https://github.com/swagger-api/swagger-core/tree/v2.2.24) | Supported +2.2.25 (**current stable**)| 2024-10-02 | 3.x | [tag v2.2.25](https://github.com/swagger-api/swagger-core/tree/v2.2.25) | Supported +2.2.24 | 2024-09-23 | 3.x | [tag v2.2.24](https://github.com/swagger-api/swagger-core/tree/v2.2.24) | Supported 2.2.23 | 2024-08-28 | 3.x | [tag v2.2.23](https://github.com/swagger-api/swagger-core/tree/v2.2.23) | Supported 2.2.22 | 2024-05-15 | 3.x | [tag v2.2.22](https://github.com/swagger-api/swagger-core/tree/v2.2.22) | Supported 2.2.21 | 2024-03-20 | 3.x | [tag v2.2.21](https://github.com/swagger-api/swagger-core/tree/v2.2.21) | Supported @@ -117,7 +118,7 @@ You need the following installed and available in your $PATH: * Jackson 2.4.5 or greater -### To build from source (currently 2.2.25-SNAPSHOT) +### To build from source (currently 2.2.26-SNAPSHOT) ``` # first time building locally mvn -N diff --git a/modules/swagger-annotations/pom.xml b/modules/swagger-annotations/pom.xml index c563ed56be..44257e582b 100644 --- a/modules/swagger-annotations/pom.xml +++ b/modules/swagger-annotations/pom.xml @@ -3,7 +3,7 @@ io.swagger.core.v3 swagger-project - 2.2.25-SNAPSHOT + 2.2.25 ../.. 4.0.0 diff --git a/modules/swagger-core/pom.xml b/modules/swagger-core/pom.xml index 38dd64a970..b19f9a2c5d 100644 --- a/modules/swagger-core/pom.xml +++ b/modules/swagger-core/pom.xml @@ -3,7 +3,7 @@ io.swagger.core.v3 swagger-project - 2.2.25-SNAPSHOT + 2.2.25 ../.. 4.0.0 diff --git a/modules/swagger-eclipse-transformer-maven-plugin/pom.xml b/modules/swagger-eclipse-transformer-maven-plugin/pom.xml index 344092265c..0794af493e 100644 --- a/modules/swagger-eclipse-transformer-maven-plugin/pom.xml +++ b/modules/swagger-eclipse-transformer-maven-plugin/pom.xml @@ -4,7 +4,7 @@ io.swagger.core.v3 swagger-project - 2.2.25-SNAPSHOT + 2.2.25 ../.. 4.0.0 diff --git a/modules/swagger-gradle-plugin/README.md b/modules/swagger-gradle-plugin/README.md index 70ba27b9c4..b613c51807 100644 --- a/modules/swagger-gradle-plugin/README.md +++ b/modules/swagger-gradle-plugin/README.md @@ -26,7 +26,7 @@ Alternatively provide as value a classpath with the following dependencies (repl ``` plugins { - id "io.swagger.core.v3.swagger-gradle-plugin" version "2.2.24" + id "io.swagger.core.v3.swagger-gradle-plugin" version "2.2.25" } ``` ### Gradle 1.x and 2.0 @@ -43,7 +43,7 @@ buildscript { } } dependencies { - classpath "io.swagger.core.v3:swagger-gradle-plugin:2.2.24" + classpath "io.swagger.core.v3:swagger-gradle-plugin:2.2.25" } } diff --git a/modules/swagger-gradle-plugin/gradle.properties b/modules/swagger-gradle-plugin/gradle.properties index 5255de4e81..3deccbb95f 100644 --- a/modules/swagger-gradle-plugin/gradle.properties +++ b/modules/swagger-gradle-plugin/gradle.properties @@ -1,2 +1,2 @@ -version=2.2.25-SNAPSHOT +version=2.2.25 jettyVersion=9.4.53.v20231009 diff --git a/modules/swagger-gradle-plugin/src/main/java/io/swagger/v3/plugins/gradle/SwaggerPlugin.java b/modules/swagger-gradle-plugin/src/main/java/io/swagger/v3/plugins/gradle/SwaggerPlugin.java index bb84ad9523..36bd941aaa 100644 --- a/modules/swagger-gradle-plugin/src/main/java/io/swagger/v3/plugins/gradle/SwaggerPlugin.java +++ b/modules/swagger-gradle-plugin/src/main/java/io/swagger/v3/plugins/gradle/SwaggerPlugin.java @@ -16,7 +16,7 @@ public void apply(Project project) { config.defaultDependencies(new Action() { public void execute(DependencySet dependencies) { dependencies.add(project.getDependencies().create("org.apache.commons:commons-lang3:3.12.0")); - dependencies.add(project.getDependencies().create("io.swagger.core.v3:swagger-jaxrs2:2.2.25-SNAPSHOT")); + dependencies.add(project.getDependencies().create("io.swagger.core.v3:swagger-jaxrs2:2.2.25")); dependencies.add(project.getDependencies().create("javax.ws.rs:javax.ws.rs-api:2.1")); dependencies.add(project.getDependencies().create("javax.servlet:javax.servlet-api:3.1.0")); } diff --git a/modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/SwaggerResolveTest.java b/modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/SwaggerResolveTest.java index b08cd781bd..1bd968c265 100644 --- a/modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/SwaggerResolveTest.java +++ b/modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/SwaggerResolveTest.java @@ -81,7 +81,7 @@ public void testSwaggerResolveTask() throws IOException { " mavenCentral()\n" + "}\n" + "dependencies { \n" + - " implementation 'io.swagger.core.v3:swagger-jaxrs2:2.2.25-SNAPSHOT'\n" + + " implementation 'io.swagger.core.v3:swagger-jaxrs2:2.2.25'\n" + " implementation 'javax.ws.rs:javax.ws.rs-api:2.1'\n" + " implementation 'javax.servlet:javax.servlet-api:3.1.0'\n" + " testImplementation 'com.github.tomakehurst:wiremock:2.27.2'\n" + @@ -154,7 +154,7 @@ public void testSwaggerResolveWithOAS31OptionTask() throws IOException { " mavenCentral()\n" + "}\n" + "dependencies { \n" + - " implementation 'io.swagger.core.v3:swagger-jaxrs2:2.2.25-SNAPSHOT'\n" + + " implementation 'io.swagger.core.v3:swagger-jaxrs2:2.2.25'\n" + " implementation 'javax.ws.rs:javax.ws.rs-api:2.1'\n" + " implementation 'javax.servlet:javax.servlet-api:3.1.0'\n" + " testImplementation 'com.github.tomakehurst:wiremock:2.27.2'\n" + diff --git a/modules/swagger-integration/pom.xml b/modules/swagger-integration/pom.xml index 2f09522c04..eebcff1f4b 100644 --- a/modules/swagger-integration/pom.xml +++ b/modules/swagger-integration/pom.xml @@ -6,7 +6,7 @@ io.swagger.core.v3 swagger-project - 2.2.25-SNAPSHOT + 2.2.25 ../.. swagger-integration diff --git a/modules/swagger-jaxrs2-servlet-initializer-v2/pom.xml b/modules/swagger-jaxrs2-servlet-initializer-v2/pom.xml index 13e2782106..b0202896b3 100644 --- a/modules/swagger-jaxrs2-servlet-initializer-v2/pom.xml +++ b/modules/swagger-jaxrs2-servlet-initializer-v2/pom.xml @@ -5,7 +5,7 @@ swagger-project io.swagger.core.v3 - 2.2.25-SNAPSHOT + 2.2.25 ../../ 4.0.0 diff --git a/modules/swagger-jaxrs2-servlet-initializer/pom.xml b/modules/swagger-jaxrs2-servlet-initializer/pom.xml index f539b91a88..234d89cb6c 100644 --- a/modules/swagger-jaxrs2-servlet-initializer/pom.xml +++ b/modules/swagger-jaxrs2-servlet-initializer/pom.xml @@ -5,7 +5,7 @@ swagger-project io.swagger.core.v3 - 2.2.25-SNAPSHOT + 2.2.25 ../../ 4.0.0 diff --git a/modules/swagger-jaxrs2/pom.xml b/modules/swagger-jaxrs2/pom.xml index 985108505b..80ecbb351e 100644 --- a/modules/swagger-jaxrs2/pom.xml +++ b/modules/swagger-jaxrs2/pom.xml @@ -5,7 +5,7 @@ swagger-project io.swagger.core.v3 - 2.2.25-SNAPSHOT + 2.2.25 ../../ 4.0.0 diff --git a/modules/swagger-maven-plugin/README.md b/modules/swagger-maven-plugin/README.md index 81ec2fdb07..fc6c0fc244 100644 --- a/modules/swagger-maven-plugin/README.md +++ b/modules/swagger-maven-plugin/README.md @@ -22,7 +22,7 @@ Both `javax` and `jakarta` examples are provided below io.swagger.core.v3 swagger-maven-plugin - 2.2.24 + 2.2.25 openapi ${project.build.directory}/generatedtest @@ -47,7 +47,7 @@ Both `javax` and `jakarta` examples are provided below io.swagger.core.v3 swagger-jaxrs2 - 2.2.24 + 2.2.25 @@ -73,7 +73,7 @@ Both `javax` and `jakarta` examples are provided below io.swagger.core.v3 swagger-maven-plugin-jakarta - 2.2.24 + 2.2.25 openapi ${project.build.directory}/generatedtest @@ -98,7 +98,7 @@ Both `javax` and `jakarta` examples are provided below io.swagger.core.v3 swagger-jaxrs2-jakarta - 2.2.24 + 2.2.25 @@ -126,7 +126,7 @@ Both `javax` and `jakarta` examples are provided below io.swagger.core.v3 swagger-maven-plugin - 2.2.24 + 2.2.25 openapi ${project.build.directory}/generatedtest @@ -155,7 +155,7 @@ Both `javax` and `jakarta` examples are provided below io.swagger.core.v3 swagger-maven-plugin-jakarta - 2.2.24 + 2.2.25 openapi ${project.build.directory}/generatedtest diff --git a/modules/swagger-maven-plugin/pom.xml b/modules/swagger-maven-plugin/pom.xml index c8a4ab7d9b..3b3e5fb27d 100644 --- a/modules/swagger-maven-plugin/pom.xml +++ b/modules/swagger-maven-plugin/pom.xml @@ -4,7 +4,7 @@ io.swagger.core.v3 swagger-project - 2.2.25-SNAPSHOT + 2.2.25 ../.. 4.0.0 diff --git a/modules/swagger-models/pom.xml b/modules/swagger-models/pom.xml index 6c26b3cb84..51ed7aba4d 100644 --- a/modules/swagger-models/pom.xml +++ b/modules/swagger-models/pom.xml @@ -4,7 +4,7 @@ io.swagger.core.v3 swagger-project - 2.2.25-SNAPSHOT + 2.2.25 ../.. 4.0.0 diff --git a/modules/swagger-project-jakarta/modules/swagger-annotations-jakarta/pom.xml b/modules/swagger-project-jakarta/modules/swagger-annotations-jakarta/pom.xml index 119ff9a8b0..648968430b 100644 --- a/modules/swagger-project-jakarta/modules/swagger-annotations-jakarta/pom.xml +++ b/modules/swagger-project-jakarta/modules/swagger-annotations-jakarta/pom.xml @@ -4,7 +4,7 @@ io.swagger.core.v3 swagger-project-jakarta - 2.2.25-SNAPSHOT + 2.2.25 ../.. 4.0.0 diff --git a/modules/swagger-project-jakarta/modules/swagger-core-jakarta/pom.xml b/modules/swagger-project-jakarta/modules/swagger-core-jakarta/pom.xml index 44d028fd66..fcc6c0ad6a 100644 --- a/modules/swagger-project-jakarta/modules/swagger-core-jakarta/pom.xml +++ b/modules/swagger-project-jakarta/modules/swagger-core-jakarta/pom.xml @@ -4,7 +4,7 @@ io.swagger.core.v3 swagger-project-jakarta - 2.2.25-SNAPSHOT + 2.2.25 ../.. 4.0.0 diff --git a/modules/swagger-project-jakarta/modules/swagger-integration-jakarta/pom.xml b/modules/swagger-project-jakarta/modules/swagger-integration-jakarta/pom.xml index 8a0698762a..9a99ff5641 100644 --- a/modules/swagger-project-jakarta/modules/swagger-integration-jakarta/pom.xml +++ b/modules/swagger-project-jakarta/modules/swagger-integration-jakarta/pom.xml @@ -4,7 +4,7 @@ io.swagger.core.v3 swagger-project-jakarta - 2.2.25-SNAPSHOT + 2.2.25 ../.. 4.0.0 diff --git a/modules/swagger-project-jakarta/modules/swagger-jaxrs2-jakarta/pom.xml b/modules/swagger-project-jakarta/modules/swagger-jaxrs2-jakarta/pom.xml index e1c14fac70..c955494b05 100644 --- a/modules/swagger-project-jakarta/modules/swagger-jaxrs2-jakarta/pom.xml +++ b/modules/swagger-project-jakarta/modules/swagger-jaxrs2-jakarta/pom.xml @@ -4,7 +4,7 @@ io.swagger.core.v3 swagger-project-jakarta - 2.2.25-SNAPSHOT + 2.2.25 ../.. 4.0.0 diff --git a/modules/swagger-project-jakarta/modules/swagger-jaxrs2-servlet-initializer-jakarta/pom.xml b/modules/swagger-project-jakarta/modules/swagger-jaxrs2-servlet-initializer-jakarta/pom.xml index c0c0e1f361..75b961ca8d 100644 --- a/modules/swagger-project-jakarta/modules/swagger-jaxrs2-servlet-initializer-jakarta/pom.xml +++ b/modules/swagger-project-jakarta/modules/swagger-jaxrs2-servlet-initializer-jakarta/pom.xml @@ -4,7 +4,7 @@ io.swagger.core.v3 swagger-project-jakarta - 2.2.25-SNAPSHOT + 2.2.25 ../.. 4.0.0 diff --git a/modules/swagger-project-jakarta/modules/swagger-jaxrs2-servlet-initializer-v2-jakarta/pom.xml b/modules/swagger-project-jakarta/modules/swagger-jaxrs2-servlet-initializer-v2-jakarta/pom.xml index f50ce23682..b2b1861a15 100644 --- a/modules/swagger-project-jakarta/modules/swagger-jaxrs2-servlet-initializer-v2-jakarta/pom.xml +++ b/modules/swagger-project-jakarta/modules/swagger-jaxrs2-servlet-initializer-v2-jakarta/pom.xml @@ -4,7 +4,7 @@ io.swagger.core.v3 swagger-project-jakarta - 2.2.25-SNAPSHOT + 2.2.25 ../.. 4.0.0 diff --git a/modules/swagger-project-jakarta/modules/swagger-maven-plugin-jakarta/pom.xml b/modules/swagger-project-jakarta/modules/swagger-maven-plugin-jakarta/pom.xml index 6bf09650e5..d51d2f107d 100644 --- a/modules/swagger-project-jakarta/modules/swagger-maven-plugin-jakarta/pom.xml +++ b/modules/swagger-project-jakarta/modules/swagger-maven-plugin-jakarta/pom.xml @@ -4,7 +4,7 @@ io.swagger.core.v3 swagger-project-jakarta - 2.2.25-SNAPSHOT + 2.2.25 ../.. 4.0.0 diff --git a/modules/swagger-project-jakarta/modules/swagger-models-jakarta/pom.xml b/modules/swagger-project-jakarta/modules/swagger-models-jakarta/pom.xml index 6edc084255..e8a82a6911 100644 --- a/modules/swagger-project-jakarta/modules/swagger-models-jakarta/pom.xml +++ b/modules/swagger-project-jakarta/modules/swagger-models-jakarta/pom.xml @@ -4,7 +4,7 @@ io.swagger.core.v3 swagger-project-jakarta - 2.2.25-SNAPSHOT + 2.2.25 ../.. 4.0.0 diff --git a/modules/swagger-project-jakarta/pom.xml b/modules/swagger-project-jakarta/pom.xml index 78178d194e..d3e8ab32fc 100644 --- a/modules/swagger-project-jakarta/pom.xml +++ b/modules/swagger-project-jakarta/pom.xml @@ -6,7 +6,7 @@ pom swagger-project-jakarta swagger-project-jakarta - 2.2.25-SNAPSHOT + 2.2.25 https://github.com/swagger-api/swagger-core scm:git:git@github.com:swagger-api/swagger-core.git diff --git a/pom.xml b/pom.xml index c04f364181..cbe16cda3d 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ pom swagger-project swagger-project - 2.2.25-SNAPSHOT + 2.2.25 https://github.com/swagger-api/swagger-core scm:git:git@github.com:swagger-api/swagger-core.git From 6c14ceb262d019bc4eec170b30d163c81f1b51b5 Mon Sep 17 00:00:00 2001 From: frantuma Date: Wed, 2 Oct 2024 12:25:38 +0000 Subject: [PATCH 20/25] bump snapshot 2.2.26-SNAPSHOT --- modules/swagger-annotations/pom.xml | 2 +- modules/swagger-core/pom.xml | 2 +- modules/swagger-eclipse-transformer-maven-plugin/pom.xml | 2 +- modules/swagger-gradle-plugin/gradle.properties | 2 +- .../main/java/io/swagger/v3/plugins/gradle/SwaggerPlugin.java | 2 +- .../java/io/swagger/v3/plugins/gradle/SwaggerResolveTest.java | 4 ++-- modules/swagger-integration/pom.xml | 2 +- modules/swagger-jaxrs2-servlet-initializer-v2/pom.xml | 2 +- modules/swagger-jaxrs2-servlet-initializer/pom.xml | 2 +- modules/swagger-jaxrs2/pom.xml | 2 +- modules/swagger-maven-plugin/pom.xml | 2 +- modules/swagger-models/pom.xml | 2 +- .../modules/swagger-annotations-jakarta/pom.xml | 2 +- .../modules/swagger-core-jakarta/pom.xml | 2 +- .../modules/swagger-integration-jakarta/pom.xml | 2 +- .../modules/swagger-jaxrs2-jakarta/pom.xml | 2 +- .../swagger-jaxrs2-servlet-initializer-jakarta/pom.xml | 2 +- .../swagger-jaxrs2-servlet-initializer-v2-jakarta/pom.xml | 2 +- .../modules/swagger-maven-plugin-jakarta/pom.xml | 2 +- .../modules/swagger-models-jakarta/pom.xml | 2 +- modules/swagger-project-jakarta/pom.xml | 2 +- pom.xml | 2 +- 22 files changed, 23 insertions(+), 23 deletions(-) diff --git a/modules/swagger-annotations/pom.xml b/modules/swagger-annotations/pom.xml index 44257e582b..774aa1967f 100644 --- a/modules/swagger-annotations/pom.xml +++ b/modules/swagger-annotations/pom.xml @@ -3,7 +3,7 @@ io.swagger.core.v3 swagger-project - 2.2.25 + 2.2.26-SNAPSHOT ../.. 4.0.0 diff --git a/modules/swagger-core/pom.xml b/modules/swagger-core/pom.xml index b19f9a2c5d..5c64e4204f 100644 --- a/modules/swagger-core/pom.xml +++ b/modules/swagger-core/pom.xml @@ -3,7 +3,7 @@ io.swagger.core.v3 swagger-project - 2.2.25 + 2.2.26-SNAPSHOT ../.. 4.0.0 diff --git a/modules/swagger-eclipse-transformer-maven-plugin/pom.xml b/modules/swagger-eclipse-transformer-maven-plugin/pom.xml index 0794af493e..b9d5a61509 100644 --- a/modules/swagger-eclipse-transformer-maven-plugin/pom.xml +++ b/modules/swagger-eclipse-transformer-maven-plugin/pom.xml @@ -4,7 +4,7 @@ io.swagger.core.v3 swagger-project - 2.2.25 + 2.2.26-SNAPSHOT ../.. 4.0.0 diff --git a/modules/swagger-gradle-plugin/gradle.properties b/modules/swagger-gradle-plugin/gradle.properties index 3deccbb95f..51973e53a2 100644 --- a/modules/swagger-gradle-plugin/gradle.properties +++ b/modules/swagger-gradle-plugin/gradle.properties @@ -1,2 +1,2 @@ -version=2.2.25 +version=2.2.26-SNAPSHOT jettyVersion=9.4.53.v20231009 diff --git a/modules/swagger-gradle-plugin/src/main/java/io/swagger/v3/plugins/gradle/SwaggerPlugin.java b/modules/swagger-gradle-plugin/src/main/java/io/swagger/v3/plugins/gradle/SwaggerPlugin.java index 36bd941aaa..824e56c294 100644 --- a/modules/swagger-gradle-plugin/src/main/java/io/swagger/v3/plugins/gradle/SwaggerPlugin.java +++ b/modules/swagger-gradle-plugin/src/main/java/io/swagger/v3/plugins/gradle/SwaggerPlugin.java @@ -16,7 +16,7 @@ public void apply(Project project) { config.defaultDependencies(new Action() { public void execute(DependencySet dependencies) { dependencies.add(project.getDependencies().create("org.apache.commons:commons-lang3:3.12.0")); - dependencies.add(project.getDependencies().create("io.swagger.core.v3:swagger-jaxrs2:2.2.25")); + dependencies.add(project.getDependencies().create("io.swagger.core.v3:swagger-jaxrs2:2.2.26-SNAPSHOT")); dependencies.add(project.getDependencies().create("javax.ws.rs:javax.ws.rs-api:2.1")); dependencies.add(project.getDependencies().create("javax.servlet:javax.servlet-api:3.1.0")); } diff --git a/modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/SwaggerResolveTest.java b/modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/SwaggerResolveTest.java index 1bd968c265..a0b6c294e7 100644 --- a/modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/SwaggerResolveTest.java +++ b/modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/SwaggerResolveTest.java @@ -81,7 +81,7 @@ public void testSwaggerResolveTask() throws IOException { " mavenCentral()\n" + "}\n" + "dependencies { \n" + - " implementation 'io.swagger.core.v3:swagger-jaxrs2:2.2.25'\n" + + " implementation 'io.swagger.core.v3:swagger-jaxrs2:2.2.26-SNAPSHOT'\n" + " implementation 'javax.ws.rs:javax.ws.rs-api:2.1'\n" + " implementation 'javax.servlet:javax.servlet-api:3.1.0'\n" + " testImplementation 'com.github.tomakehurst:wiremock:2.27.2'\n" + @@ -154,7 +154,7 @@ public void testSwaggerResolveWithOAS31OptionTask() throws IOException { " mavenCentral()\n" + "}\n" + "dependencies { \n" + - " implementation 'io.swagger.core.v3:swagger-jaxrs2:2.2.25'\n" + + " implementation 'io.swagger.core.v3:swagger-jaxrs2:2.2.26-SNAPSHOT'\n" + " implementation 'javax.ws.rs:javax.ws.rs-api:2.1'\n" + " implementation 'javax.servlet:javax.servlet-api:3.1.0'\n" + " testImplementation 'com.github.tomakehurst:wiremock:2.27.2'\n" + diff --git a/modules/swagger-integration/pom.xml b/modules/swagger-integration/pom.xml index eebcff1f4b..e6be0c4e13 100644 --- a/modules/swagger-integration/pom.xml +++ b/modules/swagger-integration/pom.xml @@ -6,7 +6,7 @@ io.swagger.core.v3 swagger-project - 2.2.25 + 2.2.26-SNAPSHOT ../.. swagger-integration diff --git a/modules/swagger-jaxrs2-servlet-initializer-v2/pom.xml b/modules/swagger-jaxrs2-servlet-initializer-v2/pom.xml index b0202896b3..7331302c9b 100644 --- a/modules/swagger-jaxrs2-servlet-initializer-v2/pom.xml +++ b/modules/swagger-jaxrs2-servlet-initializer-v2/pom.xml @@ -5,7 +5,7 @@ swagger-project io.swagger.core.v3 - 2.2.25 + 2.2.26-SNAPSHOT ../../ 4.0.0 diff --git a/modules/swagger-jaxrs2-servlet-initializer/pom.xml b/modules/swagger-jaxrs2-servlet-initializer/pom.xml index 234d89cb6c..3dde3b4945 100644 --- a/modules/swagger-jaxrs2-servlet-initializer/pom.xml +++ b/modules/swagger-jaxrs2-servlet-initializer/pom.xml @@ -5,7 +5,7 @@ swagger-project io.swagger.core.v3 - 2.2.25 + 2.2.26-SNAPSHOT ../../ 4.0.0 diff --git a/modules/swagger-jaxrs2/pom.xml b/modules/swagger-jaxrs2/pom.xml index 80ecbb351e..13423677f0 100644 --- a/modules/swagger-jaxrs2/pom.xml +++ b/modules/swagger-jaxrs2/pom.xml @@ -5,7 +5,7 @@ swagger-project io.swagger.core.v3 - 2.2.25 + 2.2.26-SNAPSHOT ../../ 4.0.0 diff --git a/modules/swagger-maven-plugin/pom.xml b/modules/swagger-maven-plugin/pom.xml index 3b3e5fb27d..866a95e2b4 100644 --- a/modules/swagger-maven-plugin/pom.xml +++ b/modules/swagger-maven-plugin/pom.xml @@ -4,7 +4,7 @@ io.swagger.core.v3 swagger-project - 2.2.25 + 2.2.26-SNAPSHOT ../.. 4.0.0 diff --git a/modules/swagger-models/pom.xml b/modules/swagger-models/pom.xml index 51ed7aba4d..82a1ad0b4c 100644 --- a/modules/swagger-models/pom.xml +++ b/modules/swagger-models/pom.xml @@ -4,7 +4,7 @@ io.swagger.core.v3 swagger-project - 2.2.25 + 2.2.26-SNAPSHOT ../.. 4.0.0 diff --git a/modules/swagger-project-jakarta/modules/swagger-annotations-jakarta/pom.xml b/modules/swagger-project-jakarta/modules/swagger-annotations-jakarta/pom.xml index 648968430b..c5abf8bd9e 100644 --- a/modules/swagger-project-jakarta/modules/swagger-annotations-jakarta/pom.xml +++ b/modules/swagger-project-jakarta/modules/swagger-annotations-jakarta/pom.xml @@ -4,7 +4,7 @@ io.swagger.core.v3 swagger-project-jakarta - 2.2.25 + 2.2.26-SNAPSHOT ../.. 4.0.0 diff --git a/modules/swagger-project-jakarta/modules/swagger-core-jakarta/pom.xml b/modules/swagger-project-jakarta/modules/swagger-core-jakarta/pom.xml index fcc6c0ad6a..0ca2bcc767 100644 --- a/modules/swagger-project-jakarta/modules/swagger-core-jakarta/pom.xml +++ b/modules/swagger-project-jakarta/modules/swagger-core-jakarta/pom.xml @@ -4,7 +4,7 @@ io.swagger.core.v3 swagger-project-jakarta - 2.2.25 + 2.2.26-SNAPSHOT ../.. 4.0.0 diff --git a/modules/swagger-project-jakarta/modules/swagger-integration-jakarta/pom.xml b/modules/swagger-project-jakarta/modules/swagger-integration-jakarta/pom.xml index 9a99ff5641..7f41dae87d 100644 --- a/modules/swagger-project-jakarta/modules/swagger-integration-jakarta/pom.xml +++ b/modules/swagger-project-jakarta/modules/swagger-integration-jakarta/pom.xml @@ -4,7 +4,7 @@ io.swagger.core.v3 swagger-project-jakarta - 2.2.25 + 2.2.26-SNAPSHOT ../.. 4.0.0 diff --git a/modules/swagger-project-jakarta/modules/swagger-jaxrs2-jakarta/pom.xml b/modules/swagger-project-jakarta/modules/swagger-jaxrs2-jakarta/pom.xml index c955494b05..f3322ba40b 100644 --- a/modules/swagger-project-jakarta/modules/swagger-jaxrs2-jakarta/pom.xml +++ b/modules/swagger-project-jakarta/modules/swagger-jaxrs2-jakarta/pom.xml @@ -4,7 +4,7 @@ io.swagger.core.v3 swagger-project-jakarta - 2.2.25 + 2.2.26-SNAPSHOT ../.. 4.0.0 diff --git a/modules/swagger-project-jakarta/modules/swagger-jaxrs2-servlet-initializer-jakarta/pom.xml b/modules/swagger-project-jakarta/modules/swagger-jaxrs2-servlet-initializer-jakarta/pom.xml index 75b961ca8d..141d80b286 100644 --- a/modules/swagger-project-jakarta/modules/swagger-jaxrs2-servlet-initializer-jakarta/pom.xml +++ b/modules/swagger-project-jakarta/modules/swagger-jaxrs2-servlet-initializer-jakarta/pom.xml @@ -4,7 +4,7 @@ io.swagger.core.v3 swagger-project-jakarta - 2.2.25 + 2.2.26-SNAPSHOT ../.. 4.0.0 diff --git a/modules/swagger-project-jakarta/modules/swagger-jaxrs2-servlet-initializer-v2-jakarta/pom.xml b/modules/swagger-project-jakarta/modules/swagger-jaxrs2-servlet-initializer-v2-jakarta/pom.xml index b2b1861a15..9d2f9eec0f 100644 --- a/modules/swagger-project-jakarta/modules/swagger-jaxrs2-servlet-initializer-v2-jakarta/pom.xml +++ b/modules/swagger-project-jakarta/modules/swagger-jaxrs2-servlet-initializer-v2-jakarta/pom.xml @@ -4,7 +4,7 @@ io.swagger.core.v3 swagger-project-jakarta - 2.2.25 + 2.2.26-SNAPSHOT ../.. 4.0.0 diff --git a/modules/swagger-project-jakarta/modules/swagger-maven-plugin-jakarta/pom.xml b/modules/swagger-project-jakarta/modules/swagger-maven-plugin-jakarta/pom.xml index d51d2f107d..a38eca28fb 100644 --- a/modules/swagger-project-jakarta/modules/swagger-maven-plugin-jakarta/pom.xml +++ b/modules/swagger-project-jakarta/modules/swagger-maven-plugin-jakarta/pom.xml @@ -4,7 +4,7 @@ io.swagger.core.v3 swagger-project-jakarta - 2.2.25 + 2.2.26-SNAPSHOT ../.. 4.0.0 diff --git a/modules/swagger-project-jakarta/modules/swagger-models-jakarta/pom.xml b/modules/swagger-project-jakarta/modules/swagger-models-jakarta/pom.xml index e8a82a6911..438b2f4594 100644 --- a/modules/swagger-project-jakarta/modules/swagger-models-jakarta/pom.xml +++ b/modules/swagger-project-jakarta/modules/swagger-models-jakarta/pom.xml @@ -4,7 +4,7 @@ io.swagger.core.v3 swagger-project-jakarta - 2.2.25 + 2.2.26-SNAPSHOT ../.. 4.0.0 diff --git a/modules/swagger-project-jakarta/pom.xml b/modules/swagger-project-jakarta/pom.xml index d3e8ab32fc..7cf53f93fc 100644 --- a/modules/swagger-project-jakarta/pom.xml +++ b/modules/swagger-project-jakarta/pom.xml @@ -6,7 +6,7 @@ pom swagger-project-jakarta swagger-project-jakarta - 2.2.25 + 2.2.26-SNAPSHOT https://github.com/swagger-api/swagger-core scm:git:git@github.com:swagger-api/swagger-core.git diff --git a/pom.xml b/pom.xml index cbe16cda3d..ce715acaf7 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ pom swagger-project swagger-project - 2.2.25 + 2.2.26-SNAPSHOT https://github.com/swagger-api/swagger-core scm:git:git@github.com:swagger-api/swagger-core.git From a36f8b5e530a0bcddb719b52f580e9d22148ffd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Rychel?= <121518786+micryc@users.noreply.github.com> Date: Mon, 7 Oct 2024 14:26:49 +0200 Subject: [PATCH 21/25] Implement Tests to check basic Java Record processing result (#4749) Implement series of tests in separate module for Java Record support --- CI/post-release.sh | 3 + CI/prepare-release.sh | 4 + modules/swagger-java17-support/pom.xml | 91 +++++ .../swagger/v3/java17/Reader/ReaderTest.java | 108 +++++ .../Reader/SchemaResolutionRecordsTest.java | 383 ++++++++++++++++++ .../matchers/SerializationMatchers.java | 88 ++++ .../v3/java17/resolving/JavaRecordTest.java | 83 ++++ .../v3/java17/resolving/SwaggerTestBase.java | 34 ++ .../resolving/v31/ModelResolverOAS31Test.java | 79 ++++ .../java17/resources/JavaRecordResource.java | 9 + .../resources/JavaRecordWithPathResource.java | 24 ++ .../OtherJavaRecordWithPathsResource.java | 30 ++ ...emaResolutionWithRecordSimpleResource.java | 39 ++ .../SchemaResolutionWithRecordsResource.java | 68 ++++ .../TestControllerWithRecordResource.java | 25 ++ modules/swagger-maven-plugin/pom.xml | 2 +- pom.xml | 10 + 17 files changed, 1079 insertions(+), 1 deletion(-) create mode 100644 modules/swagger-java17-support/pom.xml create mode 100644 modules/swagger-java17-support/src/test/java/io/swagger/v3/java17/Reader/ReaderTest.java create mode 100644 modules/swagger-java17-support/src/test/java/io/swagger/v3/java17/Reader/SchemaResolutionRecordsTest.java create mode 100644 modules/swagger-java17-support/src/test/java/io/swagger/v3/java17/matchers/SerializationMatchers.java create mode 100644 modules/swagger-java17-support/src/test/java/io/swagger/v3/java17/resolving/JavaRecordTest.java create mode 100644 modules/swagger-java17-support/src/test/java/io/swagger/v3/java17/resolving/SwaggerTestBase.java create mode 100644 modules/swagger-java17-support/src/test/java/io/swagger/v3/java17/resolving/v31/ModelResolverOAS31Test.java create mode 100644 modules/swagger-java17-support/src/test/java/io/swagger/v3/java17/resources/JavaRecordResource.java create mode 100644 modules/swagger-java17-support/src/test/java/io/swagger/v3/java17/resources/JavaRecordWithPathResource.java create mode 100644 modules/swagger-java17-support/src/test/java/io/swagger/v3/java17/resources/OtherJavaRecordWithPathsResource.java create mode 100644 modules/swagger-java17-support/src/test/java/io/swagger/v3/java17/resources/SchemaResolutionWithRecordSimpleResource.java create mode 100644 modules/swagger-java17-support/src/test/java/io/swagger/v3/java17/resources/SchemaResolutionWithRecordsResource.java create mode 100644 modules/swagger-java17-support/src/test/java/io/swagger/v3/java17/resources/TestControllerWithRecordResource.java diff --git a/CI/post-release.sh b/CI/post-release.sh index 9936615799..99f4b658d2 100755 --- a/CI/post-release.sh +++ b/CI/post-release.sh @@ -44,6 +44,9 @@ sc_find="io.swagger.core.v3:swagger-jaxrs2:$SC_VERSION" sc_replace="io.swagger.core.v3:swagger-jaxrs2:$SC_NEXT_VERSION-SNAPSHOT" sed -i -e "s/$sc_find/$sc_replace/g" $CUR/modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/SwaggerResolveTest.java +sc_find="$SC_VERSION<\/version>" +sc_replace="$SC_NEXT_VERSION-SNAPSHOT<\/version>" +sed -i -e "s/$sc_find/$sc_replace/g" $CUR/modules/swagger-java17-support/pom.xml ##################### ### Copy scripts to temp folder, as they are not available when checking out different branch or repo diff --git a/CI/prepare-release.sh b/CI/prepare-release.sh index 691526e724..8c8106a501 100755 --- a/CI/prepare-release.sh +++ b/CI/prepare-release.sh @@ -73,6 +73,10 @@ sc_find="$SC_LAST_RELEASE<\/version>" sc_replace="$SC_VERSION<\/version>" sed -i -e "s/$sc_find/$sc_replace/g" $CUR/modules/swagger-maven-plugin/README.md +sc_find="$SC_LAST_RELEASE<\/version>" +sc_replace="$SC_VERSION<\/version>" +sed -i -e "s/$sc_find/$sc_replace/g" $CUR/modules/swaggerjava17-support/pom.xml + ##################### ### build and test maven ### ##################### diff --git a/modules/swagger-java17-support/pom.xml b/modules/swagger-java17-support/pom.xml new file mode 100644 index 0000000000..6bbd74ab9c --- /dev/null +++ b/modules/swagger-java17-support/pom.xml @@ -0,0 +1,91 @@ + + 4.0.0 + + io.swagger.core.v3 + swagger-project + 2.2.26-SNAPSHOT + ../../pom.xml + + swagger-java17-support + jar + swagger-java17-support + Module for Java 17 specific tests + + + org.testng + testng + test + + + io.swagger.core.v3 + swagger-jaxrs2 + ${project.version} + + + io.swagger.core.v3 + swagger-core + ${project.version} + + + io.swagger.core.v3 + swagger-annotations + ${project.version} + + + io.swagger.core.v3 + swagger-models + ${project.version} + + + org.glassfish.jersey.media + jersey-media-multipart + ${jersey2-version} + test + + + javax.annotation + javax.annotation-api + + + org.javassist + javassist + + + + + org.glassfish.jersey.inject + jersey-hk2 + ${jersey2-version} + test + + + javax.annotation + javax.annotation-api + + + org.javassist + javassist + + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.11.0 + + 17 + + + + + + 17 + + + diff --git a/modules/swagger-java17-support/src/test/java/io/swagger/v3/java17/Reader/ReaderTest.java b/modules/swagger-java17-support/src/test/java/io/swagger/v3/java17/Reader/ReaderTest.java new file mode 100644 index 0000000000..bd4ff8d8c1 --- /dev/null +++ b/modules/swagger-java17-support/src/test/java/io/swagger/v3/java17/Reader/ReaderTest.java @@ -0,0 +1,108 @@ +package io.swagger.v3.java17.Reader; + +import io.swagger.v3.java17.matchers.SerializationMatchers; +import io.swagger.v3.java17.resources.JavaRecordWithPathResource; +import io.swagger.v3.java17.resources.OtherJavaRecordWithPathsResource; +import io.swagger.v3.java17.resources.TestControllerWithRecordResource; +import io.swagger.v3.jaxrs2.Reader; +import io.swagger.v3.oas.integration.SwaggerConfiguration; +import io.swagger.v3.oas.models.OpenAPI; +import org.testng.annotations.Test; + +import java.util.HashSet; +import java.util.Set; + +public class ReaderTest { + + @Test + public void TestJavaRecordRef(){ + Reader reader = new Reader(new SwaggerConfiguration().openAPI(new OpenAPI()).openAPI31(true)); + + OpenAPI openAPI = reader.read(TestControllerWithRecordResource.class); + String yaml = "openapi: 3.1.0\n" + + "paths:\n" + + " /v17:\n" + + " post:\n" + + " operationId: opsRecordID\n" + + " responses:\n" + + " default:\n" + + " description: Successful operation\n" + + " content:\n" + + " application/json:\n" + + " schema:\n" + + " $ref: '#/components/schemas/JavaRecordResource'\n" + + "components:\n" + + " schemas:\n" + + " JavaRecordResource:\n" + + " type: object\n" + + " properties:\n" + + " test:\n" + + " type: string\n" + + " description: Testing of Java Record Processing\n" + + " isLatest:\n" + + " type: boolean\n" + + " id:\n" + + " type: string\n" + + " age:\n" + + " type: integer\n" + + " format: int32"; + SerializationMatchers.assertEqualsToYaml31(openAPI, yaml); + } + + @Test + public void TestSetOfRecords(){ + Set> classes = new HashSet<>(); + classes.add(JavaRecordWithPathResource.class); + classes.add(OtherJavaRecordWithPathsResource.class); + + Reader reader = new Reader(new OpenAPI()); + OpenAPI openAPI = reader.read(classes); + String yaml = "openapi: 3.0.1\n" + + "paths:\n" + + " /sample/1:\n" + + " post:\n" + + " description: description 1\n" + + " operationId: id 1\n" + + " responses:\n" + + " default:\n" + + " description: default response\n" + + " content:\n" + + " '*/*': {}\n" + + " /sample/2:\n" + + " post:\n" + + " description: description 2\n" + + " operationId: id 2\n" + + " responses:\n" + + " default:\n" + + " description: default response\n" + + " content:\n" + + " '*/*': {}\n" + + " /sample2:\n" + + " get:\n" + + " description: description\n" + + " operationId: Operation Id\n" + + " responses:\n" + + " default:\n" + + " description: default response\n" + + " content:\n" + + " '*/*': {}\n" + + " security:\n" + + " - security_key:\n" + + " - write:pets\n" + + " - read:pets\n" + + " /sample2/2:\n" + + " get:\n" + + " description: description 2\n" + + " operationId: Operation Id 2\n" + + " responses:\n" + + " default:\n" + + " description: default response\n" + + " content:\n" + + " '*/*': {}\n" + + " security:\n" + + " - security_key2:\n" + + " - write:pets\n" + + " - read:pets"; + SerializationMatchers.assertEqualsToYaml(openAPI, yaml); + } +} diff --git a/modules/swagger-java17-support/src/test/java/io/swagger/v3/java17/Reader/SchemaResolutionRecordsTest.java b/modules/swagger-java17-support/src/test/java/io/swagger/v3/java17/Reader/SchemaResolutionRecordsTest.java new file mode 100644 index 0000000000..e7fc559933 --- /dev/null +++ b/modules/swagger-java17-support/src/test/java/io/swagger/v3/java17/Reader/SchemaResolutionRecordsTest.java @@ -0,0 +1,383 @@ +package io.swagger.v3.java17.Reader; + +import io.swagger.v3.core.converter.ModelConverters; +import io.swagger.v3.java17.matchers.SerializationMatchers; +import io.swagger.v3.java17.resources.SchemaResolutionWithRecordSimpleResource; +import io.swagger.v3.java17.resources.SchemaResolutionWithRecordsResource; +import io.swagger.v3.jaxrs2.Reader; +import io.swagger.v3.oas.integration.SwaggerConfiguration; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.media.Schema; +import org.testng.annotations.Test; + +public class SchemaResolutionRecordsTest { + + @Test + public void testSchemaResolutionInlineWithRecords(){ + ModelConverters.reset(); + Reader reader = new Reader(new SwaggerConfiguration().openAPI(new OpenAPI()).schemaResolution(Schema.SchemaResolution.INLINE)); + OpenAPI openAPI = reader.read(SchemaResolutionWithRecordsResource.class); + String yaml = "openapi: 3.0.1\n" + + "paths:\n" + + " /test/inlineSchemaFirst:\n" + + " get:\n" + + " operationId: inlineSchemaFirst\n" + + " responses:\n" + + " default:\n" + + " description: default response\n" + + " content:\n" + + " '*/*':\n" + + " schema:\n" + + " type: object\n" + + " properties:\n" + + " property1:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: property\n" + + " example: example\n" + + " property2:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: property\n" + + " example: example\n" + + " /test/inlineSchemaSecond:\n" + + " get:\n" + + " operationId: inlineSchemaSecond\n" + + " requestBody:\n" + + " content:\n" + + " '*/*':\n" + + " schema:\n" + + " type: object\n" + + " properties:\n" + + " foo:\n" + + " type: string\n" + + " propertySecond1:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: object\n" + + " properties:\n" + + " property1:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: property 1\n" + + " property2:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: property 2\n" + + " example: example\n" + + " description: InlineSchemaSecond property 1\n" + + " nullable: true\n" + + " example: exampleSecond\n" + + " property2:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: InlineSchemaSecond property 2\n" + + " nullable: true\n" + + " example: example\n" + + " description: InlineSchemaSecond API\n" + + " responses:\n" + + " default:\n" + + " description: default response\n" + + " content:\n" + + " '*/*':\n" + + " schema:\n" + + " type: object\n" + + " properties:\n" + + " foo:\n" + + " type: string\n" + + " propertySecond1:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: object\n" + + " properties:\n" + + " property1:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: property 1\n" + + " property2:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: property 2\n" + + " example: example\n" + + " description: InlineSchemaSecond property 1\n" + + " nullable: true\n" + + " example: exampleSecond\n" + + " property2:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: InlineSchemaSecond property 2\n" + + " nullable: true\n" + + " example: example\n" + + "components:\n" + + " schemas:\n" + + " InlineSchemaPropertyFirst:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: property\n" + + " nullable: true\n" + + " example: example\n" + + " InlineSchemaRecordFirst:\n" + + " type: object\n" + + " properties:\n" + + " property1:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: property\n" + + " example: example\n" + + " property2:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: property\n" + + " example: example\n" + + " InlineSchemaPropertySecond:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: object\n" + + " properties:\n" + + " property1:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: property 1\n" + + " property2:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: property 2\n" + + " example: example\n" + + " description: propertySecond\n" + + " nullable: true\n" + + " example: exampleSecond\n" + + " InlineSchemaPropertySimple:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: property\n" + + " example: example\n" + + " InlineSchemaRecordSecond:\n" + + " type: object\n" + + " properties:\n" + + " foo:\n" + + " type: string\n" + + " propertySecond1:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: object\n" + + " properties:\n" + + " property1:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: property 1\n" + + " property2:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: property 2\n" + + " example: example\n" + + " description: InlineSchemaSecond property 1\n" + + " nullable: true\n" + + " example: exampleSecond\n" + + " property2:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: InlineSchemaSecond property 2\n" + + " nullable: true\n" + + " example: example\n" + + " description: InlineSchemaSecond API\n" + + " InlineSchemaSimple:\n" + + " type: object\n" + + " properties:\n" + + " property1:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: property 1\n" + + " property2:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: property 2\n" + + " example: example\n"; + SerializationMatchers.assertEqualsToYaml(openAPI, yaml); + ModelConverters.reset(); + } + + @Test + public void testSchemaResolutionAllOfWithRecordTest(){ + ModelConverters.reset(); + Reader reader = new Reader(new SwaggerConfiguration().openAPI(new OpenAPI()).schemaResolution(Schema.SchemaResolution.ALL_OF)); + OpenAPI openAPI = reader.read(SchemaResolutionWithRecordSimpleResource.class); + String yaml = "openapi: 3.0.1\n" + + "paths:\n" + + " /test/inlineSchemaFirst:\n" + + " get:\n" + + " operationId: inlineSchemaFirst\n" + + " responses:\n" + + " default:\n" + + " description: InlineSchemaFirst Response API\n" + + " content:\n" + + " '*/*':\n" + + " schema:\n" + + " $ref: '#/components/schemas/SchemaRecordFirst'\n" + + " /test/inlineSchemaSecond:\n" + + " get:\n" + + " operationId: inlineSchemaFirst_1\n" + + " requestBody:\n" + + " content:\n" + + " '*/*':\n" + + " schema:\n" + + " allOf:\n" + + " - description: InlineSchemaSecond API\n" + + " - $ref: '#/components/schemas/SchemaRecordFirst'\n" + + " responses:\n" + + " default:\n" + + " description: default response\n" + + " content:\n" + + " '*/*': {}\n" + + "components:\n" + + " schemas:\n" + + " InlineSchemaPropertyFirst:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: property\n" + + " nullable: true\n" + + " example: example\n" + + " SchemaRecordFirst:\n" + + " type: object\n" + + " properties:\n" + + " property1:\n" + + " $ref: '#/components/schemas/InlineSchemaPropertyFirst'\n"; + SerializationMatchers.assertEqualsToYaml(openAPI, yaml); + ModelConverters.reset(); + } + + @Test + public void testSchemaResolutionAllOfRefWithRecordsTest(){ + Reader reader = new Reader(new SwaggerConfiguration().openAPI(new OpenAPI()).schemaResolution(Schema.SchemaResolution.ALL_OF_REF)); + OpenAPI openAPI = reader.read(SchemaResolutionWithRecordsResource.class); + String yaml = "openapi: 3.0.1\n" + + "paths:\n" + + " /test/inlineSchemaFirst:\n" + + " get:\n" + + " operationId: inlineSchemaFirst\n" + + " responses:\n" + + " default:\n" + + " description: default response\n" + + " content:\n" + + " '*/*':\n" + + " schema:\n" + + " $ref: '#/components/schemas/InlineSchemaRecordFirst'\n" + + " /test/inlineSchemaSecond:\n" + + " get:\n" + + " operationId: inlineSchemaSecond\n" + + " requestBody:\n" + + " content:\n" + + " '*/*':\n" + + " schema:\n" + + " description: InlineSchemaSecond API\n" + + " allOf:\n" + + " - $ref: '#/components/schemas/InlineSchemaRecordSecond'\n" + + " responses:\n" + + " default:\n" + + " description: default response\n" + + " content:\n" + + " '*/*':\n" + + " schema:\n" + + " $ref: '#/components/schemas/InlineSchemaRecordSecond'\n" + + "components:\n" + + " schemas:\n" + + " InlineSchemaPropertyFirst:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: property\n" + + " example: example\n" + + " InlineSchemaRecordFirst:\n" + + " type: object\n" + + " properties:\n" + + " property1:\n" + + " $ref: '#/components/schemas/InlineSchemaPropertyFirst'\n" + + " property2:\n" + + " $ref: '#/components/schemas/InlineSchemaPropertyFirst'\n" + + " InlineSchemaPropertySecond:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " $ref: '#/components/schemas/InlineSchemaSimple'\n" + + " description: propertySecond\n" + + " example: exampleSecond\n" + + " InlineSchemaPropertySimple:\n" + + " type: object\n" + + " properties:\n" + + " bar:\n" + + " type: string\n" + + " description: property\n" + + " InlineSchemaRecordSecond:\n" + + " type: object\n" + + " properties:\n" + + " foo:\n" + + " type: string\n" + + " propertySecond1:\n" + + " description: InlineSchemaSecond property 1\n" + + " nullable: true\n" + + " allOf:\n" + + " - $ref: '#/components/schemas/InlineSchemaPropertySecond'\n" + + " property2:\n" + + " description: InlineSchemaSecond property 2\n" + + " nullable: true\n" + + " allOf:\n" + + " - $ref: '#/components/schemas/InlineSchemaPropertyFirst'\n" + + " InlineSchemaSimple:\n" + + " type: object\n" + + " properties:\n" + + " property1:\n" + + " description: property 1\n" + + " allOf:\n" + + " - $ref: '#/components/schemas/InlineSchemaPropertySimple'\n" + + " property2:\n" + + " description: property 2\n" + + " example: example\n" + + " allOf:\n" + + " - $ref: '#/components/schemas/InlineSchemaPropertySimple'\n"; + SerializationMatchers.assertEqualsToYaml(openAPI, yaml); + } +} diff --git a/modules/swagger-java17-support/src/test/java/io/swagger/v3/java17/matchers/SerializationMatchers.java b/modules/swagger-java17-support/src/test/java/io/swagger/v3/java17/matchers/SerializationMatchers.java new file mode 100644 index 0000000000..01e5c00de2 --- /dev/null +++ b/modules/swagger-java17-support/src/test/java/io/swagger/v3/java17/matchers/SerializationMatchers.java @@ -0,0 +1,88 @@ +package io.swagger.v3.java17.matchers; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.NumericNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import io.swagger.v3.core.util.Json; +import io.swagger.v3.core.util.Json31; +import io.swagger.v3.core.util.Yaml; +import io.swagger.v3.core.util.Yaml31; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.util.Comparator; + +import static org.testng.Assert.assertEquals; + +public class SerializationMatchers { + private static final Logger LOGGER = LoggerFactory.getLogger(SerializationMatchers.class); + + public static void assertEqualsToYaml(Object objectToSerialize, String yamlStr) { + apply(objectToSerialize, yamlStr, Yaml.mapper(), false); + } + + public static void assertEqualsToYamlExact(Object objectToSerialize, String yamlStr) { + apply(objectToSerialize, yamlStr, Yaml.mapper(), true); + } + + public static void assertEqualsToJson(Object objectToSerialize, String jsonStr) { + apply(objectToSerialize, jsonStr, Json.mapper(), false); + } + + public static void assertEqualsToYaml31(Object objectToSerialize, String yamlStr) { + apply31(objectToSerialize, yamlStr, Yaml31.mapper()); + } + + public static void assertEqualsToJson31(Object objectToSerialize, String jsonStr) { + apply31(objectToSerialize, jsonStr, Json31.mapper()); + } + + private static void apply(Object objectToSerialize, String str, ObjectMapper mapper, boolean exactMatch) { + final ObjectNode lhs = mapper.convertValue(objectToSerialize, ObjectNode.class); + ObjectNode rhs = null; + try { + rhs = mapper.readValue(str, ObjectNode.class); + } catch (IOException e) { + LOGGER.error("Failed to read value", e); + } + if (exactMatch || !lhs.equals(new ObjectNodeComparator(), rhs)) { + assertEquals(Yaml.pretty(lhs), Yaml.pretty(rhs)); + //fail(String.format("Serialized object:\n%s\ndoes not equal to expected serialized string:\n%s", lhs, rhs)); + } + } + + private static void apply31(Object objectToSerialize, String str, ObjectMapper mapper) { + final ObjectNode lhs = mapper.convertValue(objectToSerialize, ObjectNode.class); + ObjectNode rhs = null; + try { + rhs = mapper.readValue(str, ObjectNode.class); + } catch (IOException e) { + LOGGER.error("Failed to read value", e); + } + if (!lhs.equals(new ObjectNodeComparator(), rhs)) { + assertEquals(Yaml31.pretty(lhs), Yaml31.pretty(rhs)); + } + } + + static final class ObjectNodeComparator implements Comparator { + @Override + public int compare(JsonNode o1, JsonNode o2) { + if (o1.equals(o2)) { + return 0; + } + if ((o1 instanceof NumericNode) && (o2 instanceof NumericNode)) { + double d1 = ((NumericNode) o1).asDouble(); + double d2 = ((NumericNode) o2).asDouble(); + return Double.compare(d1, d2); + } + int comp = o1.asText().compareTo(o2.asText()); + if (comp == 0) { + return Integer.compare(o1.hashCode(), o2.hashCode()); + } + return comp; + } + } + +} diff --git a/modules/swagger-java17-support/src/test/java/io/swagger/v3/java17/resolving/JavaRecordTest.java b/modules/swagger-java17-support/src/test/java/io/swagger/v3/java17/resolving/JavaRecordTest.java new file mode 100644 index 0000000000..5e483a1f94 --- /dev/null +++ b/modules/swagger-java17-support/src/test/java/io/swagger/v3/java17/resolving/JavaRecordTest.java @@ -0,0 +1,83 @@ +package io.swagger.v3.java17.resolving; + +import io.swagger.v3.core.converter.ModelConverters; +import io.swagger.v3.oas.models.media.Schema; +import io.swagger.v3.java17.matchers.SerializationMatchers; +import org.testng.annotations.Test; + +import javax.validation.constraints.*; +import java.util.List; +import java.util.Map; + +public class JavaRecordTest { + + @Test + public void testJavaRecordWithSchema() { + String expectedYaml = "JavaRecordClassWithSchema:\n" + + " type: object\n" + + " description: Java Record with Schema Test\n" + + " properties:\n" + + " test:\n" + + " type: string\n" + + " description: Testing of Schema on fields processing in Java Records\n" + + " isLatest:\n" + + " type: boolean"; + + Map stringSchemaMap = ModelConverters.getInstance(false).readAll(JavaRecordClassWithSchema.class); + SerializationMatchers.assertEqualsToYaml(stringSchemaMap, expectedYaml); + } + + @Test + public void testJavaRecordWithBeanValidation() { + String expectedYaml = "JavaRecordClassWithBeanValidation:\n" + + " type: object\n" + + " description: Java Record with Bean Validation Test\n" + + " properties:\n" + + " test:\n" + + " maxLength: 100\n" + + " minLength: 1\n" + + " type: string\n" + + " isLatest:\n" + + " type: boolean\n" + + " randomList:\n" + + " maxItems: 101\n" + + " minItems: 2\n" + + " type: array\n" + + " items:\n" + + " type: string\n" + + " myField:\n" + + " maximum: 100\n" + + " exclusiveMaximum: false\n" + + " minimum: 1\n" + + " exclusiveMinimum: false\n" + + " type: number\n" + + " email:\n" + + " pattern: (.+?)@(.+?)\n" + + " type: string"; + + Map stringSchemaMap = ModelConverters.getInstance(false).readAll(JavaRecordClassWithBeanValidation.class); + SerializationMatchers.assertEqualsToYaml(stringSchemaMap, expectedYaml); + } + + @io.swagger.v3.oas.annotations.media.Schema(description = "Java Record with Schema Test") + public record JavaRecordClassWithSchema( + @io.swagger.v3.oas.annotations.media.Schema(description = "Testing of Schema on fields processing in Java Records") String test, + boolean isLatest + ){ + } + + @io.swagger.v3.oas.annotations.media.Schema(description = "Java Record with Bean Validation Test") + public record JavaRecordClassWithBeanValidation( + @Size(min = 1, max = 100) String test, + boolean isLatest, + @Size(min = 2, max = 101) + List randomList, + @DecimalMin("1") + @DecimalMax("100") + Number myField, + @Pattern(regexp = "(.+?)@(.+?)") + String email + ){ + } + +} diff --git a/modules/swagger-java17-support/src/test/java/io/swagger/v3/java17/resolving/SwaggerTestBase.java b/modules/swagger-java17-support/src/test/java/io/swagger/v3/java17/resolving/SwaggerTestBase.java new file mode 100644 index 0000000000..2735cb788a --- /dev/null +++ b/modules/swagger-java17-support/src/test/java/io/swagger/v3/java17/resolving/SwaggerTestBase.java @@ -0,0 +1,34 @@ +package io.swagger.v3.java17.resolving; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import io.swagger.v3.core.jackson.ModelResolver; + +public abstract class SwaggerTestBase { + static ObjectMapper mapper; + + public static ObjectMapper mapper() { + if (mapper == null) { + mapper = new ObjectMapper(); + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + } + return mapper; + } + + protected ModelResolver modelResolver() { + return new ModelResolver(new ObjectMapper()); + } + + protected void prettyPrint(Object o) { + try { + System.out.println(mapper().writer(new DefaultPrettyPrinter()).writeValueAsString(o)); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/modules/swagger-java17-support/src/test/java/io/swagger/v3/java17/resolving/v31/ModelResolverOAS31Test.java b/modules/swagger-java17-support/src/test/java/io/swagger/v3/java17/resolving/v31/ModelResolverOAS31Test.java new file mode 100644 index 0000000000..902f4336da --- /dev/null +++ b/modules/swagger-java17-support/src/test/java/io/swagger/v3/java17/resolving/v31/ModelResolverOAS31Test.java @@ -0,0 +1,79 @@ +package io.swagger.v3.java17.resolving.v31; + +import io.swagger.v3.core.converter.ModelConverters; +import io.swagger.v3.java17.resolving.SwaggerTestBase; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.models.media.Schema; +import org.testng.annotations.Test; +import io.swagger.v3.java17.matchers.SerializationMatchers; +import java.util.List; +import java.util.Map; + +public class ModelResolverOAS31Test extends SwaggerTestBase { + + @Test + public void testOAS31JavaRecord() { + String expectedYaml = "JavaRecordWithOAS31Fields:\n" + + " type: object\n" + + " $comment: Random comment at schema level\n" + + " $id: http://yourdomain.com/schemas/myschema.json\n" + + " description: this is model for testing OAS 3.1 Java Record resolving\n" + + " properties:\n" + + " test:\n" + + " type: string\n" + + " isLatest:\n" + + " type: boolean\n" + + " randomList:\n" + + " type: array\n" + + " contains:\n" + + " type: string\n" + + " items:\n" + + " type: string\n" + + " maxContains: 10\n" + + " minContains: 1\n" + + " prefixItems:\n" + + " - type: string\n" + + " unevaluatedItems:\n" + + " type: number\n" + + " Status:\n" + + " type:\n" + + " - string\n" + + " - number\n"; + + Map stringSchemaMap = ModelConverters.getInstance(true).readAll(JavaRecordWithOAS31Fields.class); + SerializationMatchers.assertEqualsToYaml31(stringSchemaMap, expectedYaml); + } + + @io.swagger.v3.oas.annotations.media.Schema( + $id = "http://yourdomain.com/schemas/myschema.json", + description = "this is model for testing OAS 3.1 Java Record resolving", + $comment = "Random comment at schema level", + types = "object" + ) + private record JavaRecordWithOAS31Fields( + String test, + boolean isLatest, + @ArraySchema( + maxContains = 10, + minContains = 1, + contains = @io.swagger.v3.oas.annotations.media.Schema( + types = "string" + ), + unevaluatedItems = @io.swagger.v3.oas.annotations.media.Schema( + types = "number" + ), + prefixItems = { + @io.swagger.v3.oas.annotations.media.Schema( + types = "string" + ) + } + ) + List randomList, + @io.swagger.v3.oas.annotations.media.Schema(types = { + "string", + "number" + }) + Object Status + ){ + } +} diff --git a/modules/swagger-java17-support/src/test/java/io/swagger/v3/java17/resources/JavaRecordResource.java b/modules/swagger-java17-support/src/test/java/io/swagger/v3/java17/resources/JavaRecordResource.java new file mode 100644 index 0000000000..eb1d392e40 --- /dev/null +++ b/modules/swagger-java17-support/src/test/java/io/swagger/v3/java17/resources/JavaRecordResource.java @@ -0,0 +1,9 @@ +package io.swagger.v3.java17.resources; + +public record JavaRecordResource( + @io.swagger.v3.oas.annotations.media.Schema(description = "Testing of Java Record Processing") String test, + boolean isLatest, + String id, + Integer age +) { +} diff --git a/modules/swagger-java17-support/src/test/java/io/swagger/v3/java17/resources/JavaRecordWithPathResource.java b/modules/swagger-java17-support/src/test/java/io/swagger/v3/java17/resources/JavaRecordWithPathResource.java new file mode 100644 index 0000000000..45b0af2967 --- /dev/null +++ b/modules/swagger-java17-support/src/test/java/io/swagger/v3/java17/resources/JavaRecordWithPathResource.java @@ -0,0 +1,24 @@ +package io.swagger.v3.java17.resources; + +import io.swagger.v3.oas.annotations.Operation; + +import javax.ws.rs.POST; +import javax.ws.rs.Path; + +@Path("sample") +public record JavaRecordWithPathResource() { + + @POST + @Path("/1") + @Operation(description = "description 1", operationId = "id 1") + public void postExample(){ + + } + + @POST + @Path("/2") + @Operation(description = "description 2", operationId = "id 2") + public void postExample2(){ + + } +} diff --git a/modules/swagger-java17-support/src/test/java/io/swagger/v3/java17/resources/OtherJavaRecordWithPathsResource.java b/modules/swagger-java17-support/src/test/java/io/swagger/v3/java17/resources/OtherJavaRecordWithPathsResource.java new file mode 100644 index 0000000000..e4a5437f54 --- /dev/null +++ b/modules/swagger-java17-support/src/test/java/io/swagger/v3/java17/resources/OtherJavaRecordWithPathsResource.java @@ -0,0 +1,30 @@ +package io.swagger.v3.java17.resources; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.security.*; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; + +@Path("sample2") +public record OtherJavaRecordWithPathsResource() { + @GET + @Path("/") + @Operation(operationId = "Operation Id", + description = "description") + @SecurityRequirement(name = "security_key", + scopes = {"write:pets", "read:pets"} + ) + public void getSecurity() { + } + + @GET + @Path("/2") + @Operation(operationId = "Operation Id 2", + description = "description 2") + @SecurityRequirement(name = "security_key2", + scopes = {"write:pets", "read:pets"} + ) + public void getSecurity2() { + } +} diff --git a/modules/swagger-java17-support/src/test/java/io/swagger/v3/java17/resources/SchemaResolutionWithRecordSimpleResource.java b/modules/swagger-java17-support/src/test/java/io/swagger/v3/java17/resources/SchemaResolutionWithRecordSimpleResource.java new file mode 100644 index 0000000000..a2952bbe4d --- /dev/null +++ b/modules/swagger-java17-support/src/test/java/io/swagger/v3/java17/resources/SchemaResolutionWithRecordSimpleResource.java @@ -0,0 +1,39 @@ +package io.swagger.v3.java17.resources; + +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.core.Response; + +@Path("test") +public class SchemaResolutionWithRecordSimpleResource{ + + + @GET + @Path("/inlineSchemaFirst") + @ApiResponse(description = "InlineSchemaFirst Response API", content = @Content(schema = @Schema(implementation = SchemaRecordFirst.class))) + public Response inlineSchemaFirst() { + return null; + } + + + @GET + @Path("/inlineSchemaSecond") + public void inlineSchemaFirst(@Schema(description = "InlineSchemaSecond API") SchemaRecordFirst inlineSchemaFirst) { + } + + + + public record SchemaRecordFirst ( + @Schema(description = "InlineSchemaFirst property 1", nullable = true) InlineSchemaPropertyFirst property1 + ){ + } + + @Schema(description = "property", example = "example") + static class InlineSchemaPropertyFirst { + public String bar; + } +} diff --git a/modules/swagger-java17-support/src/test/java/io/swagger/v3/java17/resources/SchemaResolutionWithRecordsResource.java b/modules/swagger-java17-support/src/test/java/io/swagger/v3/java17/resources/SchemaResolutionWithRecordsResource.java new file mode 100644 index 0000000000..0271762a58 --- /dev/null +++ b/modules/swagger-java17-support/src/test/java/io/swagger/v3/java17/resources/SchemaResolutionWithRecordsResource.java @@ -0,0 +1,68 @@ +package io.swagger.v3.java17.resources; + + +import io.swagger.v3.oas.annotations.media.Schema; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; + +@Path("test") +public class SchemaResolutionWithRecordsResource { + + @GET + @Path("/inlineSchemaSecond") + public InlineSchemaRecordSecond inlineSchemaSecond(@Schema(description = "InlineSchemaSecond API") InlineSchemaRecordSecond inlineSchemaSecond) { + return null; + } + + @GET + @Path("/inlineSchemaFirst") + public InlineSchemaRecordFirst inlineSchemaFirst() { + return null; + } + + + public record InlineSchemaRecordFirst( + InlineSchemaPropertyFirst property1, + InlineSchemaPropertyFirst property2 + ){ + } + + public record InlineSchemaRecordSecond ( + String foo, + @Schema(description = "InlineSchemaSecond property 1", nullable = true) + InlineSchemaPropertySecond propertySecond1, + @Schema(description = "InlineSchemaSecond property 2", nullable = true) + InlineSchemaPropertyFirst property2 + ){ + } + + @Schema(description = "property", example = "example") + static class InlineSchemaPropertyFirst { + public String bar; + } + + @Schema(description = "propertySecond", example = "exampleSecond") + static class InlineSchemaPropertySecond { + public InlineSchemaSimple bar; + } + + static class InlineSchemaSimple { + + @Schema(description = "property 1") + public InlineSchemaPropertySimple property1; + + + private InlineSchemaPropertySimple property2; + + @Schema(description = "property 2", example = "example") + public InlineSchemaPropertySimple getProperty2() { + return null; + } + } + + @Schema(description = "property") + static class InlineSchemaPropertySimple { + public String bar; + } +} diff --git a/modules/swagger-java17-support/src/test/java/io/swagger/v3/java17/resources/TestControllerWithRecordResource.java b/modules/swagger-java17-support/src/test/java/io/swagger/v3/java17/resources/TestControllerWithRecordResource.java new file mode 100644 index 0000000000..3ba8205b51 --- /dev/null +++ b/modules/swagger-java17-support/src/test/java/io/swagger/v3/java17/resources/TestControllerWithRecordResource.java @@ -0,0 +1,25 @@ +package io.swagger.v3.java17.resources; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.responses.ApiResponse; + +import javax.ws.rs.Consumes; +import javax.ws.rs.POST; +import javax.ws.rs.Path; + +@Path("/v17") +public class TestControllerWithRecordResource { + + @POST + @Operation( + operationId = "opsRecordID", + responses = @ApiResponse(description = "Successful operation", + content = @Content(mediaType = "application/json",schema = @io.swagger.v3.oas.annotations.media.Schema(implementation = JavaRecordResource.class)) + ) + ) + @Consumes({"application/json", "application/xml"}) + public void postRecord(){} + +} + diff --git a/modules/swagger-maven-plugin/pom.xml b/modules/swagger-maven-plugin/pom.xml index 866a95e2b4..a21fa1d680 100644 --- a/modules/swagger-maven-plugin/pom.xml +++ b/modules/swagger-maven-plugin/pom.xml @@ -17,7 +17,7 @@ org.codehaus.plexus plexus-component-metadata - 2.0.0 + 2.1.1 diff --git a/pom.xml b/pom.xml index ce715acaf7..6cc5ff775a 100644 --- a/pom.xml +++ b/pom.xml @@ -395,6 +395,16 @@ + + java-17-modules + + [17,) + + + modules/swagger-java17-support + + + modules/swagger-annotations From 03fcbccbd8908f9910bc24108459768b0507431f Mon Sep 17 00:00:00 2001 From: MicRyc Date: Tue, 8 Oct 2024 13:38:01 +0200 Subject: [PATCH 22/25] Update findJsonValueType method to provide better support for Jackson < 2.9 --- .../v3/core/jackson/ModelResolver.java | 31 ++++++++++++------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/ModelResolver.java b/modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/ModelResolver.java index 011a6d3676..6b1e6c84e3 100644 --- a/modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/ModelResolver.java +++ b/modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/ModelResolver.java @@ -1116,18 +1116,18 @@ protected Type findJsonValueType(final BeanDescription beanDesc) { // use recursion to check for method findJsonValueAccessor existence (Jackson 2.9+) // if not found use previous deprecated method which could lead to inaccurate result - try { - Method m = BeanDescription.class.getMethod("findJsonValueAccessor"); - AnnotatedMember jsonValueMember = (AnnotatedMember)m.invoke(beanDesc); - if (jsonValueMember != null) { - return jsonValueMember.getType(); - } - } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { + AnnotatedMember jsonValueMember = invokeMethod(beanDesc, "findJsonValueAccessor"); + if (jsonValueMember != null) { + return jsonValueMember.getType(); + } else { LOGGER.warn("jackson BeanDescription.findJsonValueAccessor not found, this could lead to inaccurate result, please update jackson to 2.9+"); - final AnnotatedMethod jsonValueMethod = beanDesc.findJsonValueMethod(); - if (jsonValueMethod != null) { - return jsonValueMethod.getType(); - } + } + + jsonValueMember = invokeMethod(beanDesc, "findJsonValueMethod"); + if (jsonValueMember != null) { + return jsonValueMember.getType(); + } else { + LOGGER.error("Neither 'findJsonValueMethod' nor 'findJsonValueAccessor' found in jackson BeanDescription. Please verify your Jackson version."); } return null; } @@ -3057,6 +3057,15 @@ protected boolean isNumberSchema(Schema schema){ return "number".equals(schema.getType()) || (schema.getTypes() != null && schema.getTypes().contains("number")) || "integer".equals(schema.getType()) || (schema.getTypes() != null && schema.getTypes().contains("integer")); } + private AnnotatedMember invokeMethod(final BeanDescription beanDesc, String methodName) { + try { + Method m = BeanDescription.class.getMethod(methodName); + return (AnnotatedMember) m.invoke(beanDesc); + } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { + return null; + } + } + protected Schema buildRefSchemaIfObject(Schema schema, ModelConverterContext context) { if (schema == null) { return null; From affcb1de49a6527804df03063c813e5b97ca1ace Mon Sep 17 00:00:00 2001 From: frantuma Date: Tue, 15 Oct 2024 10:41:10 +0200 Subject: [PATCH 23/25] bump jetty to 9.4.56.v20240826 --- modules/swagger-project-jakarta/pom.xml | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/swagger-project-jakarta/pom.xml b/modules/swagger-project-jakarta/pom.xml index 7cf53f93fc..005a70316a 100644 --- a/modules/swagger-project-jakarta/pom.xml +++ b/modules/swagger-project-jakarta/pom.xml @@ -494,7 +494,7 @@ 3.17.0 2.17.0 2.0.9 - 9.4.53.v20231009 + 9.4.56.v20240826g 7.9.0 2.28.2 4.5.1 diff --git a/pom.xml b/pom.xml index 6cc5ff775a..22979c7f2f 100644 --- a/pom.xml +++ b/pom.xml @@ -657,7 +657,7 @@ 3.17.0 2.17.0 2.0.9 - 9.4.53.v20231009 + 9.4.56.v20240826 7.8.0 2.28.2 4.5.1 From 7d5ec6185771f6f3508d7791c94cffd718637bfd Mon Sep 17 00:00:00 2001 From: frantuma Date: Thu, 24 Oct 2024 08:50:37 +0200 Subject: [PATCH 24/25] fix findJsonValueType --- .../v3/core/jackson/ModelResolver.java | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/ModelResolver.java b/modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/ModelResolver.java index 6b1e6c84e3..58181bcdd7 100644 --- a/modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/ModelResolver.java +++ b/modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/ModelResolver.java @@ -1116,17 +1116,21 @@ protected Type findJsonValueType(final BeanDescription beanDesc) { // use recursion to check for method findJsonValueAccessor existence (Jackson 2.9+) // if not found use previous deprecated method which could lead to inaccurate result - AnnotatedMember jsonValueMember = invokeMethod(beanDesc, "findJsonValueAccessor"); - if (jsonValueMember != null) { - return jsonValueMember.getType(); - } else { + try { + AnnotatedMember jsonValueMember = invokeMethod(beanDesc, "findJsonValueAccessor"); + if (jsonValueMember != null) { + return jsonValueMember.getType(); + } + } catch (Exception e) { LOGGER.warn("jackson BeanDescription.findJsonValueAccessor not found, this could lead to inaccurate result, please update jackson to 2.9+"); } - jsonValueMember = invokeMethod(beanDesc, "findJsonValueMethod"); - if (jsonValueMember != null) { - return jsonValueMember.getType(); - } else { + try { + AnnotatedMember jsonValueMember = invokeMethod(beanDesc, "findJsonValueMethod"); + if (jsonValueMember != null) { + return jsonValueMember.getType(); + } + } catch (Exception e) { LOGGER.error("Neither 'findJsonValueMethod' nor 'findJsonValueAccessor' found in jackson BeanDescription. Please verify your Jackson version."); } return null; @@ -3057,13 +3061,9 @@ protected boolean isNumberSchema(Schema schema){ return "number".equals(schema.getType()) || (schema.getTypes() != null && schema.getTypes().contains("number")) || "integer".equals(schema.getType()) || (schema.getTypes() != null && schema.getTypes().contains("integer")); } - private AnnotatedMember invokeMethod(final BeanDescription beanDesc, String methodName) { - try { - Method m = BeanDescription.class.getMethod(methodName); - return (AnnotatedMember) m.invoke(beanDesc); - } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { - return null; - } + private AnnotatedMember invokeMethod(final BeanDescription beanDesc, String methodName) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException{ + Method m = BeanDescription.class.getMethod(methodName); + return (AnnotatedMember) m.invoke(beanDesc); } protected Schema buildRefSchemaIfObject(Schema schema, ModelConverterContext context) { From 5402f1cf6edd337fa542d2c1153db8b514149b9b Mon Sep 17 00:00:00 2001 From: MicRyc Date: Fri, 18 Oct 2024 15:06:42 +0200 Subject: [PATCH 25/25] refs-#4737 add scanning for other OAS elements besides paths --- .../io/swagger/v3/core/filter/SpecFilter.java | 98 ++++++++++++-- .../v3/core/filter/SpecFilterTest.java | 38 ++++++ .../specFiles/3.1.0/issue-4737-3.1.yaml | 29 ++++ .../3.1.0/specWithReferredSchemas-3.1.yaml | 124 ++++++++++++++++++ 4 files changed, 275 insertions(+), 14 deletions(-) create mode 100644 modules/swagger-core/src/test/resources/specFiles/3.1.0/issue-4737-3.1.yaml create mode 100644 modules/swagger-core/src/test/resources/specFiles/3.1.0/specWithReferredSchemas-3.1.yaml diff --git a/modules/swagger-core/src/main/java/io/swagger/v3/core/filter/SpecFilter.java b/modules/swagger-core/src/main/java/io/swagger/v3/core/filter/SpecFilter.java index aef8b69384..e0f15c8679 100755 --- a/modules/swagger-core/src/main/java/io/swagger/v3/core/filter/SpecFilter.java +++ b/modules/swagger-core/src/main/java/io/swagger/v3/core/filter/SpecFilter.java @@ -350,38 +350,98 @@ private void addPathItemSchemaRef(PathItem pathItem, Set referencedDefin Map ops = pathItem.readOperationsMap(); for (Operation op : ops.values()) { if (op.getRequestBody() != null) { - addContentSchemaRef(op.getRequestBody().getContent(), referencedDefinitions); + addRequestBodySchemaRef(op.getRequestBody(), referencedDefinitions); } if (op.getResponses() != null) { for (String keyResponses : op.getResponses().keySet()) { ApiResponse response = op.getResponses().get(keyResponses); - if (response.getHeaders() != null) { - for (String keyHeaders : response.getHeaders().keySet()) { - Header header = response.getHeaders().get(keyHeaders); - addSchemaRef(header.getSchema(), referencedDefinitions); - addContentSchemaRef(header.getContent(), referencedDefinitions); - } - } - addContentSchemaRef(response.getContent(), referencedDefinitions); + addApiResponseSchemaRef(response, referencedDefinitions); } } if (op.getParameters() != null) { for (Parameter parameter : op.getParameters()) { - addSchemaRef(parameter.getSchema(), referencedDefinitions); - addContentSchemaRef(parameter.getContent(), referencedDefinitions); + addParameterSchemaRef(parameter, referencedDefinitions); } } if (op.getCallbacks() != null) { for (String keyCallback : op.getCallbacks().keySet()) { Callback callback = op.getCallbacks().get(keyCallback); - for (PathItem callbackPathItem : callback.values()) { - addPathItemSchemaRef(callbackPathItem, referencedDefinitions); - } + addCallbackSchemaRef(callback, referencedDefinitions); } } } } + private void addApiResponseSchemaRef(ApiResponse response, Set referencedDefinitions) { + if (response.getHeaders() != null) { + for (String keyHeaders : response.getHeaders().keySet()) { + Header header = response.getHeaders().get(keyHeaders); + addHeaderSchemaRef(header, referencedDefinitions); + } + } + addContentSchemaRef(response.getContent(), referencedDefinitions); + } + + private void addRequestBodySchemaRef(RequestBody requestBody, Set referencedDefinitions) { + addContentSchemaRef(requestBody.getContent(), referencedDefinitions); + } + + private void addParameterSchemaRef(Parameter parameter, Set referencedDefinitions) { + addSchemaRef(parameter.getSchema(), referencedDefinitions); + addContentSchemaRef(parameter.getContent(), referencedDefinitions); + } + + private void addHeaderSchemaRef(Header header, Set referencedDefinitions) { + addSchemaRef(header.getSchema(), referencedDefinitions); + addContentSchemaRef(header.getContent(), referencedDefinitions); + } + + private void addCallbackSchemaRef(Callback callback, Set referencedDefinitions){ + for (PathItem callbackPathItem : callback.values()) { + addPathItemSchemaRef(callbackPathItem, referencedDefinitions); + } + } + + private void addComponentsSchemaRef(Components components, Set referencedDefinitions){ + + if (components.getResponses() != null){ + for (String resourcePath : components.getResponses().keySet()) { + ApiResponse apiResponse = components.getResponses().get(resourcePath); + addApiResponseSchemaRef(apiResponse, referencedDefinitions); + } + } + if (components.getRequestBodies() != null){ + for (String requestBody : components.getRequestBodies().keySet()) { + RequestBody requestBody1 = components.getRequestBodies().get(requestBody); + addRequestBodySchemaRef(requestBody1, referencedDefinitions); + } + } + if (components.getParameters() != null){ + for (String parameter : components.getParameters().keySet()) { + Parameter resourceParam = components.getParameters().get(parameter); + addParameterSchemaRef(resourceParam, referencedDefinitions); + } + } + if (components.getHeaders() != null){ + for (String header : components.getHeaders().keySet()) { + Header resourceHeader = components.getHeaders().get(header); + addHeaderSchemaRef(resourceHeader, referencedDefinitions); + } + } + if (components.getCallbacks() != null){ + for (String callback : components.getCallbacks().keySet()){ + Callback resourceCallback = components.getCallbacks().get(callback); + addCallbackSchemaRef(resourceCallback, referencedDefinitions); + } + } + if (components.getPathItems() != null){ + for (String resourcePath : components.getPathItems().keySet()){ + PathItem pathItem = components.getPathItems().get(resourcePath); + addPathItemSchemaRef(pathItem, referencedDefinitions); + } + } + } + protected OpenAPI removeBrokenReferenceDefinitions(OpenAPI openApi) { if (openApi == null || openApi.getComponents() == null || openApi.getComponents().getSchemas() == null) { @@ -395,6 +455,16 @@ protected OpenAPI removeBrokenReferenceDefinitions(OpenAPI openApi) { addPathItemSchemaRef(pathItem, referencedDefinitions); } } + if (openApi.getWebhooks() != null){ + for (String resourcePath : openApi.getWebhooks().keySet()) { + PathItem pathItem = openApi.getWebhooks().get(resourcePath); + addPathItemSchemaRef(pathItem, referencedDefinitions); + } + } + if (openApi.getComponents() != null){ + Components components = openApi.getComponents(); + addComponentsSchemaRef(components, referencedDefinitions); + } referencedDefinitions.addAll(resolveAllNestedRefs(referencedDefinitions, referencedDefinitions, openApi)); openApi.getComponents() diff --git a/modules/swagger-core/src/test/java/io/swagger/v3/core/filter/SpecFilterTest.java b/modules/swagger-core/src/test/java/io/swagger/v3/core/filter/SpecFilterTest.java index f04c9b56e7..355d4722e2 100644 --- a/modules/swagger-core/src/test/java/io/swagger/v3/core/filter/SpecFilterTest.java +++ b/modules/swagger-core/src/test/java/io/swagger/v3/core/filter/SpecFilterTest.java @@ -16,6 +16,8 @@ import io.swagger.v3.core.matchers.SerializationMatchers; import io.swagger.v3.core.util.Json; import io.swagger.v3.core.util.Json31; +import io.swagger.v3.core.util.Yaml; +import io.swagger.v3.core.util.Yaml31; import io.swagger.v3.core.util.ResourceUtils; import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.OpenAPI; @@ -46,6 +48,8 @@ public class SpecFilterTest { private static final String RESOURCE_RECURSIVE_MODELS = "specFiles/recursivemodels.json"; private static final String RESOURCE_PATH = "specFiles/petstore-3.0-v2.json"; private static final String RESOURCE_PATH_3303 = "specFiles/petstore-3.0-v2-ticket-3303.json"; + private static final String RESOURCE_WITH_REF_DEFINITION_4737 = "specFiles/3.1.0/issue-4737-3.1.yaml"; + private static final String RESOURCE_WITH_REFERRED_DEFINITIONS= "specFiles/3.1.0/specWithReferredSchemas-3.1.yaml"; private static final String RESOURCE_PATH_LIST = "specFiles/3.1.0/list-3.1.json"; private static final String RESOURCE_PATH_COMPOSED_SCHEMA = "specFiles/3.1.0/composed-schema-3.1.json"; private static final String RESOURCE_REFERRED_SCHEMAS = "specFiles/petstore-3.0-referred-schemas.json"; @@ -450,6 +454,30 @@ public void filterWithNullDefinitions() throws IOException { assertNotNull(filtered); } + @Test(description = "RemoveUnreferencedDefinitionsFilter should not remove schema definition if ref used in Webhook") + public void testTicket4737() throws IOException { + final OpenAPI openAPI = getOpenAPIYaml31(RESOURCE_WITH_REF_DEFINITION_4737); + final RemoveUnreferencedDefinitionsFilter remover = new RemoveUnreferencedDefinitionsFilter(); + final OpenAPI filtered = new SpecFilter().filter(openAPI, remover, null, null, null); + assertNotNull(filtered.getComponents().getSchemas().get("RequestDto")); + } + + @Test + public void shouldNotRemoveUsedDefinitions() throws IOException { + final OpenAPI openAPI = getOpenAPIYaml31(RESOURCE_WITH_REFERRED_DEFINITIONS); + final RemoveUnreferencedDefinitionsFilter remover = new RemoveUnreferencedDefinitionsFilter(); + final OpenAPI filtered = new SpecFilter().filter(openAPI, remover, null, null, null); + assertNotNull(filtered.getComponents().getSchemas().get("ResponseDefinition")); + assertNotNull(filtered.getComponents().getSchemas().get("WebhookResponseDefinition")); + assertNotNull(filtered.getComponents().getSchemas().get("WebhookOperationDefinition")); + assertNotNull(filtered.getComponents().getSchemas().get("RequestBodyDefinition")); + assertNotNull(filtered.getComponents().getSchemas().get("ParameterDefinition")); + assertNotNull(filtered.getComponents().getSchemas().get("HeaderDefinition")); + assertNotNull(filtered.getComponents().getSchemas().get("CallbackDefinition")); + assertNotNull(filtered.getComponents().getSchemas().get("PathItemDefinition")); + assertNull(filtered.getComponents().getSchemas().get("UnusedDefinition")); + } + private Set getTagNames(OpenAPI openAPI) { Set result = new HashSet<>(); if (openAPI.getTags() != null) { @@ -469,4 +497,14 @@ private OpenAPI getOpenAPI31(String path) throws IOException { final String json = ResourceUtils.loadClassResource(getClass(), path); return Json31.mapper().readValue(json, OpenAPI.class); } + + private OpenAPI getOpenAPIYaml(String path) throws IOException { + final String yaml = ResourceUtils.loadClassResource(getClass(), path); + return Yaml.mapper().readValue(yaml, OpenAPI.class); + } + + private OpenAPI getOpenAPIYaml31(String path) throws IOException { + final String yaml = ResourceUtils.loadClassResource(getClass(), path); + return Yaml31.mapper().readValue(yaml, OpenAPI.class); + } } diff --git a/modules/swagger-core/src/test/resources/specFiles/3.1.0/issue-4737-3.1.yaml b/modules/swagger-core/src/test/resources/specFiles/3.1.0/issue-4737-3.1.yaml new file mode 100644 index 0000000000..1e1615a4f2 --- /dev/null +++ b/modules/swagger-core/src/test/resources/specFiles/3.1.0/issue-4737-3.1.yaml @@ -0,0 +1,29 @@ +openapi: 3.1.0 +info: + title: OpenAPI definition + version: v0 +servers: + - url: http://localhost + description: Generated server url +paths: {} +components: + schemas: + RequestDto: + properties: + personalNumber: + type: string +webhooks: + newPet: + post: + requestBody: + description: Information about a new pet in the system + content: + application/json: + schema: + $ref: '#/components/schemas/RequestDto' + description: Webhook Pet + responses: + '200': + description: >- + Return a 200 status to indicate that the data was received + successfully \ No newline at end of file diff --git a/modules/swagger-core/src/test/resources/specFiles/3.1.0/specWithReferredSchemas-3.1.yaml b/modules/swagger-core/src/test/resources/specFiles/3.1.0/specWithReferredSchemas-3.1.yaml new file mode 100644 index 0000000000..bfc9e05cf4 --- /dev/null +++ b/modules/swagger-core/src/test/resources/specFiles/3.1.0/specWithReferredSchemas-3.1.yaml @@ -0,0 +1,124 @@ +openapi: 3.1.0 +info: + title: OpenAPI definition + version: v0 +servers: + - url: http://localhost + description: Generated server url +paths: + /users: + get: + summary: Get list of all users + operationId: usersList + responses: + 200: + description: OK + content: + application/json: + schema: + type: string + maxLength: 100 + minLength: 1 +components: + schemas: + ResponseDefinition: + properties: + personalNumber: + type: string + WebhookResponseDefinition: + properties: + personalNumber: + type: integer + WebhookOperationDefinition: + properties: + personalNumber: + type: number + RequestBodyDefinition: + properties: + personalNumber: + type: string + ParameterDefinition: + properties: + parameterName: + type: string + HeaderDefinition: + type: string + description: header ref + CallbackDefinition: + description: callback ref + type: string + PathItemDefinition: + description: pathItem ref + type: string + UnusedDefinition: + description: unused definition + type: string + minLength: 1 + maxLength: 100 + responses: + OK: + description: OK + content: + application/json: + schema: + $ref: "#/components/schemas/ResponseDefinition" + requestBodies: + requestBody1: + description: request body + content: + application/json: + schema: + $ref: "#/components/schemas/RequestBodyDefinition" + parameters: + parameter1: + description: request body + name: parameter + in: query + content: + application/json: + schema: + $ref: "#/components/schemas/ParameterDefinition" + headers: + header1: + content: + application/json: + schema: + $ref: "#/components/schemas/HeaderDefinition" + callbacks: + myEvent: # Event name + "{$request.body#/callbackUrl}": + post: + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/CallbackDefinition" + pathItems: + pathItem1: + get: + summary: Get list of all users + operationId: usersList + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: "#/components/schemas/PathItemDefinition" +webhooks: + newPet: + post: + requestBody: + description: Information about a new pet in the system + content: + application/json: + schema: + $ref: '#/components/schemas/WebhookOperationDefinition' + description: Webhook Pet + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/WebhookResponseDefinition'