From 50319e2ec56d8365fb5780052591e40728318ac5 Mon Sep 17 00:00:00 2001 From: Jared Gentner Date: Wed, 28 Apr 2021 10:20:56 -0400 Subject: [PATCH 1/3] modify ResponseSupportConverter to resolve inner type --- .../core/converters/ResponseSupportConverter.java | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/springdoc-openapi-common/src/main/java/org/springdoc/core/converters/ResponseSupportConverter.java b/springdoc-openapi-common/src/main/java/org/springdoc/core/converters/ResponseSupportConverter.java index f5d758901..43daa8aac 100644 --- a/springdoc-openapi-common/src/main/java/org/springdoc/core/converters/ResponseSupportConverter.java +++ b/springdoc-openapi-common/src/main/java/org/springdoc/core/converters/ResponseSupportConverter.java @@ -49,12 +49,10 @@ public Schema resolve(AnnotatedType type, ModelConverterContext context, Iterato JavaType innerType = javaType.getBindings().getBoundType(0); if (innerType == null) return new StringSchema(); - else if (innerType.getBindings() != null && isResponseTypeWrapper(innerType.getRawClass())) { - type = new AnnotatedType(innerType).jsonViewAnnotation(type.getJsonViewAnnotation()).ctxAnnotations(type.getCtxAnnotations()).resolveAsRef(true); - return this.resolve(type, context, chain); - } - else - type = new AnnotatedType(innerType).jsonViewAnnotation(type.getJsonViewAnnotation()).ctxAnnotations((type.getCtxAnnotations())).resolveAsRef(true); + return context.resolve(new AnnotatedType(innerType) + .jsonViewAnnotation(type.getJsonViewAnnotation()) + .ctxAnnotations((type.getCtxAnnotations())) + .resolveAsRef(true)); } else if (isResponseTypeToIgnore(cls)) return null; @@ -62,4 +60,4 @@ else if (isResponseTypeToIgnore(cls)) return (chain.hasNext()) ? chain.next().resolve(type, context, chain) : null; } -} \ No newline at end of file +} From 0942572afd482caab507536deb86e543de2533d8 Mon Sep 17 00:00:00 2001 From: Jared Gentner Date: Thu, 29 Apr 2021 14:35:27 -0400 Subject: [PATCH 2/3] add test to demonstrate --- .../test/org/springdoc/api/app157/Bar.java | 12 +++++ .../test/org/springdoc/api/app157/Foo.java | 12 +++++ .../springdoc/api/app157/HelloController.java | 44 +++++++++++++++++++ .../api/app157/SpringDocApp157Test.java | 39 ++++++++++++++++ .../api/app157/StringyConverter.java | 25 +++++++++++ 5 files changed, 132 insertions(+) create mode 100644 springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app157/Bar.java create mode 100644 springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app157/Foo.java create mode 100644 springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app157/HelloController.java create mode 100644 springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app157/SpringDocApp157Test.java create mode 100644 springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app157/StringyConverter.java diff --git a/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app157/Bar.java b/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app157/Bar.java new file mode 100644 index 000000000..8c9ea08d4 --- /dev/null +++ b/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app157/Bar.java @@ -0,0 +1,12 @@ +package test.org.springdoc.api.app157; + +/** + * A class without a String in it + */ +public class Bar { + private Object child; + + public Object getChild() { + return this.child; + } +} diff --git a/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app157/Foo.java b/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app157/Foo.java new file mode 100644 index 000000000..c139567b2 --- /dev/null +++ b/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app157/Foo.java @@ -0,0 +1,12 @@ +package test.org.springdoc.api.app157; + +/** + * A class with a String in it + */ +public class Foo { + private String child; + + public String getChild() { + return this.child; + } +} diff --git a/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app157/HelloController.java b/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app157/HelloController.java new file mode 100644 index 000000000..10a514ba1 --- /dev/null +++ b/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app157/HelloController.java @@ -0,0 +1,44 @@ +/* + * + * * Copyright 2019-2020 the original author or authors. + * * + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * https://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * + */ + +package test.org.springdoc.api.app157; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * Put Foo and Bar in the schema's components, make sure there is an ignored wrapper + * ({@code ResponseEntity}). + */ +@RestController +public class HelloController { + + @GetMapping( "/foo") + public ResponseEntity getFoo() { + return new ResponseEntity(HttpStatus.OK); + } + + @GetMapping( "/bar") + public ResponseEntity getBar() { + return new ResponseEntity(HttpStatus.OK); + } + + +} \ No newline at end of file diff --git a/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app157/SpringDocApp157Test.java b/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app157/SpringDocApp157Test.java new file mode 100644 index 000000000..957af06ce --- /dev/null +++ b/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app157/SpringDocApp157Test.java @@ -0,0 +1,39 @@ +package test.org.springdoc.api.app157; + +import io.swagger.v3.core.converter.ModelConverters; +import io.swagger.v3.core.util.Json; +import org.junit.jupiter.api.Test; +import org.springdoc.core.Constants; +import org.springdoc.core.converters.ModelConverterRegistrar; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.test.web.servlet.MvcResult; +import test.org.springdoc.api.AbstractSpringDocTest; + +import java.util.List; + +import static org.hamcrest.Matchers.*; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +/** + * This test is to make sure that a new model converter can access the parent of a type, even if + * the type is enclosed in an ignored wrapper. We test this by setting up a model converter which + * adds "stringy" to the "required" property of a schema's parent, when the sub schema is a String. + */ +public class SpringDocApp157Test extends AbstractSpringDocTest { + + @SpringBootApplication + static class SpringBootApp {} + + @Test + public void testApp() throws Exception { + // Not sure why the converter isn't registered automatically. Register it here. + new ModelConverterRegistrar(List.of(new StringyConverter())); + mockMvc.perform(get(Constants.DEFAULT_API_DOCS_URL)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.openapi", is("3.0.1"))) + .andExpect(jsonPath("$.components.schemas.Foo.required", is(List.of("stringy")))) + .andExpect(jsonPath("$.components.schemas.Bar", not(hasProperty("required")))); + } +} diff --git a/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app157/StringyConverter.java b/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app157/StringyConverter.java new file mode 100644 index 000000000..ccc5c18db --- /dev/null +++ b/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app157/StringyConverter.java @@ -0,0 +1,25 @@ +package test.org.springdoc.api.app157; + +import com.fasterxml.jackson.databind.JavaType; +import io.swagger.v3.core.converter.AnnotatedType; +import io.swagger.v3.core.converter.ModelConverter; +import io.swagger.v3.core.converter.ModelConverterContext; +import io.swagger.v3.core.util.Json; +import io.swagger.v3.oas.models.media.Schema; + +import java.util.Iterator; + +public class StringyConverter implements ModelConverter { + + @Override + public Schema resolve(AnnotatedType type, ModelConverterContext context, + Iterator chain) { + + JavaType javaType = Json.mapper().constructType(type.getType()); + + if (javaType.getRawClass().equals(String.class)) { + type.getParent().addRequiredItem("stringy"); + } + return chain.next().resolve(type, context, chain); + } +} From aaacec68eca5cd98fbd692d227ac4fd7755eaaf5 Mon Sep 17 00:00:00 2001 From: Jared Gentner Date: Thu, 29 Apr 2021 15:09:31 -0400 Subject: [PATCH 3/3] setup and teardown for test --- .../api/app157/SpringDocApp157Test.java | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app157/SpringDocApp157Test.java b/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app157/SpringDocApp157Test.java index 957af06ce..34e02df6a 100644 --- a/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app157/SpringDocApp157Test.java +++ b/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app157/SpringDocApp157Test.java @@ -2,6 +2,10 @@ import io.swagger.v3.core.converter.ModelConverters; import io.swagger.v3.core.util.Json; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springdoc.core.Constants; import org.springdoc.core.converters.ModelConverterRegistrar; @@ -26,10 +30,21 @@ public class SpringDocApp157Test extends AbstractSpringDocTest { @SpringBootApplication static class SpringBootApp {} + private StringyConverter myConverter = new StringyConverter(); + private ModelConverters converters = ModelConverters.getInstance(); + + @BeforeEach + public void registerConverter() { + converters.addConverter(myConverter); + } + + @AfterEach + public void unregisterConverter() { + converters.removeConverter(myConverter); + } + @Test public void testApp() throws Exception { - // Not sure why the converter isn't registered automatically. Register it here. - new ModelConverterRegistrar(List.of(new StringyConverter())); mockMvc.perform(get(Constants.DEFAULT_API_DOCS_URL)) .andExpect(status().isOk()) .andExpect(jsonPath("$.openapi", is("3.0.1")))