diff --git a/modules/openapi-generator/src/main/resources/kotlin-spring/libraries/spring-declarative-http-interface/apiInterface.mustache b/modules/openapi-generator/src/main/resources/kotlin-spring/libraries/spring-declarative-http-interface/apiInterface.mustache index 2e7a59289cb4..10c6a9b5c8b4 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-spring/libraries/spring-declarative-http-interface/apiInterface.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-spring/libraries/spring-declarative-http-interface/apiInterface.mustache @@ -61,6 +61,9 @@ interface {{classname}} { {{#operation}}{{! }}{{^useResponseEntity}} @ResponseStatus({{#springHttpStatus}}{{#responses.0}}{{{code}}}{{/responses.0}}{{/springHttpStatus}}) {{/useResponseEntity}}{{! +}}{{#vendorExtensions.x-operation-extra-annotation}} + {{{.}}} +{{/vendorExtensions.x-operation-extra-annotation}}{{! }}{{#httpMethod}} @HttpExchange( // "{{#lambdaEscapeInNormalString}}{{{path}}}{{/lambdaEscapeInNormalString}}" url = PATH_{{#lambda.uppercase}}{{#lambda.snakecase}}{{{operationId}}}{{/lambda.snakecase}}{{/lambda.uppercase}}, diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/spring/KotlinSpringServerCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/spring/KotlinSpringServerCodegenTest.java index e8d9e69d1468..53a86d7b5501 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/spring/KotlinSpringServerCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/spring/KotlinSpringServerCodegenTest.java @@ -5,6 +5,7 @@ import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.info.Info; import io.swagger.v3.oas.models.servers.Server; +import io.swagger.v3.oas.models.Operation; import io.swagger.v3.parser.core.models.ParseOptions; import org.apache.commons.io.FileUtils; import org.assertj.core.api.Assertions; @@ -1456,6 +1457,49 @@ public void generateHttpInterfaceReactiveWithReactorResponseEntity() throws Exce ); } + @Test(description = "x-operation-extra-annotation should be rendered for spring-declarative-http-interface library (issue: extension unavailable in declarative interface mode)") + public void generateHttpInterfaceRendersOperationExtraAnnotation() throws Exception { + File output = Files.createTempDirectory("test").toFile().getCanonicalFile(); + output.deleteOnExit(); + String outputPath = output.getAbsolutePath().replace('\\', '/'); + + OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_0/kotlin/petstore.yaml"); + Operation getInventory = openAPI.getPaths().get("/store/inventory").getGet(); + getInventory.addExtension("x-operation-extra-annotation", "@Secured(\"ROLE_ADMIN\")"); + + KotlinSpringServerCodegen codegen = new KotlinSpringServerCodegen(); + codegen.setOutputDir(output.getAbsolutePath()); + codegen.additionalProperties().put(CodegenConstants.LIBRARY, "spring-declarative-http-interface"); + codegen.additionalProperties().put(REACTIVE, false); + codegen.additionalProperties().put(USE_RESPONSE_ENTITY, true); + codegen.additionalProperties().put(USE_FLOW_FOR_ARRAY_RETURN_TYPE, false); + + ClientOptInput input = new ClientOptInput() + .openAPI(openAPI) + .config(codegen); + DefaultGenerator generator = new DefaultGenerator(); + + generator.setGeneratorPropertyDefault(CodegenConstants.MODELS, "true"); + generator.setGeneratorPropertyDefault(CodegenConstants.MODEL_TESTS, "false"); + generator.setGeneratorPropertyDefault(CodegenConstants.MODEL_DOCS, "false"); + generator.setGeneratorPropertyDefault(CodegenConstants.APIS, "true"); + generator.setGeneratorPropertyDefault(CodegenConstants.SUPPORTING_FILES, "false"); + + generator.opts(input).generate(); + + Path path = Paths.get(outputPath + "/src/main/kotlin/org/openapitools/api/StoreApi.kt"); + assertFileContains( + path, + " @Secured(\"ROLE_ADMIN\")\n" + + " @HttpExchange(\n" + + " // \"/store/inventory\"\n" + + " url = PATH_GET_INVENTORY,\n" + + " method = \"GET\"\n" + + " )\n" + + " fun getInventory(" + ); + } + @Test public void generateHttpInterfaceReactiveWithCoroutinesResponseEntity() throws Exception { File output = Files.createTempDirectory("test").toFile().getCanonicalFile();