From 2c78ff78ed57bb0f7dba0cf8cd6abd298b2805df Mon Sep 17 00:00:00 2001 From: Rodrigo de Almeida - RMA3 Date: Thu, 20 Apr 2023 12:35:09 -0300 Subject: [PATCH] Fix issue 15264 - Replace @Controller with @RestController when using useSpringController (#15266) * fix issue 15264 * If useResponseEntity true then keep @Controller if not @RestController --------- Co-authored-by: Rodrigo Maciel de Almeida --- .../main/resources/JavaSpring/api.mustache | 10 +++ .../JavaSpring/apiController.mustache | 10 ++- .../java/spring/SpringCodegenTest.java | 72 +++++++++++++++++++ .../src/test/resources/2_0/issue15264.yaml | 51 +++++++++++++ .../openapitools/api/PetApiController.java | 4 +- .../openapitools/api/StoreApiController.java | 4 +- .../openapitools/api/UserApiController.java | 4 +- 7 files changed, 148 insertions(+), 7 deletions(-) create mode 100644 modules/openapi-generator/src/test/resources/2_0/issue15264.yaml diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/api.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/api.mustache index dac0d161bba..51908e42544 100644 --- a/modules/openapi-generator/src/main/resources/JavaSpring/api.mustache +++ b/modules/openapi-generator/src/main/resources/JavaSpring/api.mustache @@ -41,7 +41,12 @@ import org.springframework.http.ResponseEntity; import org.springframework.validation.annotation.Validated; {{/useBeanValidation}} {{#useSpringController}} +{{#useResponseEntity}} import org.springframework.stereotype.Controller; +{{/useResponseEntity}} +{{^useResponseEntity}} +import org.springframework.web.bind.annotation.RestController; +{{/useResponseEntity}} {{/useSpringController}} import org.springframework.web.bind.annotation.*; {{#jdk8-no-delegate}} @@ -81,7 +86,12 @@ import {{javaxPackage}}.annotation.Generated; @Validated {{/useBeanValidation}} {{#useSpringController}} +{{#useResponseEntity}} @Controller +{{/useResponseEntity}} +{{^useResponseEntity}} +@RestController +{{/useResponseEntity}} {{/useSpringController}} {{#swagger2AnnotationLibrary}} @Tag(name = "{{{tagName}}}", description = {{#tagDescription}}"{{{.}}}"{{/tagDescription}}{{^tagDescription}}"the {{{tagName}}} API"{{/tagDescription}}) diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/apiController.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/apiController.mustache index 2078b4a7960..15b1f27c19a 100644 --- a/modules/openapi-generator/src/main/resources/JavaSpring/apiController.mustache +++ b/modules/openapi-generator/src/main/resources/JavaSpring/apiController.mustache @@ -23,8 +23,11 @@ import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; {{#useResponseEntity}} import org.springframework.http.ResponseEntity; -{{/useResponseEntity}} import org.springframework.stereotype.Controller; +{{/useResponseEntity}} +{{^useResponseEntity}} +import org.springframework.web.bind.annotation.RestController; +{{/useResponseEntity}} import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestHeader; @@ -48,7 +51,12 @@ import java.util.Optional; import {{javaxPackage}}.annotation.Generated; {{>generatedAnnotation}} +{{#useResponseEntity}} @Controller +{{/useResponseEntity}} +{{^useResponseEntity}} +@RestController +{{/useResponseEntity}} {{#useRequestMappingOnController}} {{=<% %>=}} @RequestMapping("${openapi.<%title%>.base-path:<%>defaultBasePath%>}") diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/spring/SpringCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/spring/SpringCodegenTest.java index e16511e3cc7..f00ac3e293a 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/spring/SpringCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/spring/SpringCodegenTest.java @@ -2442,4 +2442,76 @@ public class SpringCodegenTest { .bodyContainsLines("throw new IllegalArgumentException(\"Not implemented\");"); } + @Test + public void testHasRestControllerDoesNotHaveController_issue15264() throws IOException { + File output = Files.createTempDirectory("test").toFile().getCanonicalFile(); + output.deleteOnExit(); + + final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/2_0/issue15264.yaml"); + final SpringCodegen codegen = new SpringCodegen(); + codegen.setOpenAPI(openAPI); + codegen.setOutputDir(output.getAbsolutePath()); + + codegen.additionalProperties().put(SpringCodegen.DATE_LIBRARY, "java8-localdatetime"); + codegen.additionalProperties().put(INTERFACE_ONLY, "true"); + codegen.additionalProperties().put(USE_RESPONSE_ENTITY, "false"); + codegen.additionalProperties().put(DELEGATE_PATTERN, "true"); + codegen.additionalProperties().put(REQUEST_MAPPING_OPTION, "api_interface"); + codegen.additionalProperties().put(SPRING_CONTROLLER, "true"); + + ClientOptInput input = new ClientOptInput(); + input.openAPI(openAPI); + input.config(codegen); + + DefaultGenerator generator = new DefaultGenerator(); + + Map files = generator.opts(input).generate().stream() + .collect(Collectors.toMap(File::getName, Function.identity())); + + JavaFileAssert javaFileAssert = JavaFileAssert.assertThat(files.get("TestApi.java")); + javaFileAssert + .isInterface() + .hasImports("org.springframework.web.bind.annotation.RestController") + .hasNoImports("org.springframework.stereotype.Controller") + .assertTypeAnnotations() + .containsWithName("RestController") + .doesNotContainsWithName("Controller"); + } + + @Test + public void testDoesNotHasRestControllerHaveController_issue15264() throws IOException { + File output = Files.createTempDirectory("test").toFile().getCanonicalFile(); + output.deleteOnExit(); + + final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/2_0/issue15264.yaml"); + final SpringCodegen codegen = new SpringCodegen(); + codegen.setOpenAPI(openAPI); + codegen.setOutputDir(output.getAbsolutePath()); + + codegen.additionalProperties().put(SpringCodegen.DATE_LIBRARY, "java8-localdatetime"); + codegen.additionalProperties().put(INTERFACE_ONLY, "true"); + codegen.additionalProperties().put(USE_RESPONSE_ENTITY, "true"); + codegen.additionalProperties().put(DELEGATE_PATTERN, "true"); + codegen.additionalProperties().put(REQUEST_MAPPING_OPTION, "api_interface"); + codegen.additionalProperties().put(SPRING_CONTROLLER, "true"); + + ClientOptInput input = new ClientOptInput(); + input.openAPI(openAPI); + input.config(codegen); + + DefaultGenerator generator = new DefaultGenerator(); + + Map files = generator.opts(input).generate().stream() + .collect(Collectors.toMap(File::getName, Function.identity())); + + JavaFileAssert javaFileAssert = JavaFileAssert.assertThat(files.get("TestApi.java")); + javaFileAssert + .isInterface() + .hasImports("org.springframework.stereotype.Controller") + .hasNoImports("org.springframework.web.bind.annotation.RestController") + .assertTypeAnnotations() + .containsWithName("Controller") + .doesNotContainsWithName("RestController"); + } + } diff --git a/modules/openapi-generator/src/test/resources/2_0/issue15264.yaml b/modules/openapi-generator/src/test/resources/2_0/issue15264.yaml new file mode 100644 index 00000000000..627f4e3b586 --- /dev/null +++ b/modules/openapi-generator/src/test/resources/2_0/issue15264.yaml @@ -0,0 +1,51 @@ +swagger: '2.0' +info: + description: 'blah' + version: 1.0.0 + title: sample spec +host: fake.site.com +tags: + - name: Test +schemes: + - https +paths: + /test: + post: + summary: Post to test + description: '' + operationId: postToTest + consumes: + - application/json + produces: + - application/json + parameters: + - in: body + name: Obj to test + schema: + $ref: '#/definitions/ObjTest' + responses: + '201': + description: successful operation + schema: + $ref: '#/definitions/ObjTest' + put: + summary: Put to test + operationId: putToTest + parameters: + - in: body + name: Obj to test + schema: + $ref: '#/definitions/ObjTest' + responses: + '204': + description: successful operation +definitions: + ObjTest: + description: A model to return + type: object + properties: + field1: + type: integer + format: int64 + field2: + type: string diff --git a/samples/server/petstore/springboot-delegate-no-response-entity/src/main/java/org/openapitools/api/PetApiController.java b/samples/server/petstore/springboot-delegate-no-response-entity/src/main/java/org/openapitools/api/PetApiController.java index 6c1fa31b180..1b41bd9b833 100644 --- a/samples/server/petstore/springboot-delegate-no-response-entity/src/main/java/org/openapitools/api/PetApiController.java +++ b/samples/server/petstore/springboot-delegate-no-response-entity/src/main/java/org/openapitools/api/PetApiController.java @@ -7,7 +7,7 @@ import org.openapitools.model.Pet; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; -import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestHeader; @@ -26,7 +26,7 @@ import java.util.Optional; import javax.annotation.Generated; @Generated(value = "org.openapitools.codegen.languages.SpringCodegen") -@Controller +@RestController @RequestMapping("${openapi.openAPIPetstore.base-path:/v2}") public class PetApiController implements PetApi { diff --git a/samples/server/petstore/springboot-delegate-no-response-entity/src/main/java/org/openapitools/api/StoreApiController.java b/samples/server/petstore/springboot-delegate-no-response-entity/src/main/java/org/openapitools/api/StoreApiController.java index c2133b27e23..fd910a279d6 100644 --- a/samples/server/petstore/springboot-delegate-no-response-entity/src/main/java/org/openapitools/api/StoreApiController.java +++ b/samples/server/petstore/springboot-delegate-no-response-entity/src/main/java/org/openapitools/api/StoreApiController.java @@ -7,7 +7,7 @@ import org.openapitools.model.Order; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; -import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestHeader; @@ -26,7 +26,7 @@ import java.util.Optional; import javax.annotation.Generated; @Generated(value = "org.openapitools.codegen.languages.SpringCodegen") -@Controller +@RestController @RequestMapping("${openapi.openAPIPetstore.base-path:/v2}") public class StoreApiController implements StoreApi { diff --git a/samples/server/petstore/springboot-delegate-no-response-entity/src/main/java/org/openapitools/api/UserApiController.java b/samples/server/petstore/springboot-delegate-no-response-entity/src/main/java/org/openapitools/api/UserApiController.java index 5c854245036..90fafe3572e 100644 --- a/samples/server/petstore/springboot-delegate-no-response-entity/src/main/java/org/openapitools/api/UserApiController.java +++ b/samples/server/petstore/springboot-delegate-no-response-entity/src/main/java/org/openapitools/api/UserApiController.java @@ -8,7 +8,7 @@ import org.openapitools.model.User; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; -import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestHeader; @@ -27,7 +27,7 @@ import java.util.Optional; import javax.annotation.Generated; @Generated(value = "org.openapitools.codegen.languages.SpringCodegen") -@Controller +@RestController @RequestMapping("${openapi.openAPIPetstore.base-path:/v2}") public class UserApiController implements UserApi {