From 1f001bf226dc319ec2a49af7a36c794f2689adf4 Mon Sep 17 00:00:00 2001 From: feczkob Date: Sun, 29 Mar 2026 18:12:15 +0200 Subject: [PATCH 1/6] Remove dead Swagger 2.0 annotation support (`useSwaggerAnnotations`) from Kotlin Server JAX-RS templates --- .../kotlin-server/libraries/jaxrs-spec/api.mustache | 6 +----- .../libraries/jaxrs-spec/apiInterface.mustache | 10 +--------- .../libraries/jaxrs-spec/apiMethod.mustache | 11 +---------- .../libraries/jaxrs-spec/cookieParams.mustache | 2 +- .../libraries/jaxrs-spec/headerParams.mustache | 2 +- .../libraries/jaxrs-spec/pathParams.mustache | 2 +- .../libraries/jaxrs-spec/queryParams.mustache | 2 +- 7 files changed, 7 insertions(+), 28 deletions(-) diff --git a/modules/openapi-generator/src/main/resources/kotlin-server/libraries/jaxrs-spec/api.mustache b/modules/openapi-generator/src/main/resources/kotlin-server/libraries/jaxrs-spec/api.mustache index f2ccb1a41dc9..9e8dcfafc28d 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-server/libraries/jaxrs-spec/api.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-server/libraries/jaxrs-spec/api.mustache @@ -6,16 +6,12 @@ package {{package}}; import {{javaxPackage}}.ws.rs.* import {{javaxPackage}}.ws.rs.core.Response -{{#useSwaggerAnnotations}} -import io.swagger.annotations.* -{{/useSwaggerAnnotations}} import java.io.InputStream {{#useBeanValidation}}import {{javaxPackage}}.validation.constraints.* import {{javaxPackage}}.validation.Valid{{/useBeanValidation}} -{{#useSwaggerAnnotations}} -@Api(description = "the {{{baseName}}} API"){{/useSwaggerAnnotations}}{{#hasConsumes}} +{{#hasConsumes}} @Consumes({ {{#consumes}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/consumes}} }){{/hasConsumes}}{{#hasProduces}} @Produces({ {{#produces}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/produces}} }){{/hasProduces}} @Path("{{commonPath}}") diff --git a/modules/openapi-generator/src/main/resources/kotlin-server/libraries/jaxrs-spec/apiInterface.mustache b/modules/openapi-generator/src/main/resources/kotlin-server/libraries/jaxrs-spec/apiInterface.mustache index 7994ec111f21..e5f33141a3ba 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-server/libraries/jaxrs-spec/apiInterface.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-server/libraries/jaxrs-spec/apiInterface.mustache @@ -1,13 +1,5 @@ @{{httpMethod}} @Path("{{{path}}}"){{#hasConsumes}} @Consumes({{#consumes}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/consumes}}){{/hasConsumes}}{{#hasProduces}} - @Produces({{#produces}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/produces}}){{/hasProduces}}{{#useSwaggerAnnotations}} - @ApiOperation(value = "{{{summary}}}", notes = "{{{notes}}}"{{#hasAuthMethods}}, authorizations = { - {{#authMethods}}{{#isOAuth}}@Authorization(value = "{{name}}", scopes = { - {{#scopes}}@AuthorizationScope(scope = "{{scope}}", description = "{{description}}"){{^-last}}, - {{/-last}}{{/scopes}} }){{^-last}},{{/-last}}{{/isOAuth}} - {{^isOAuth}}@Authorization(value = "{{name}}"){{^-last}},{{/-last}} - {{/isOAuth}}{{/authMethods}} }{{/hasAuthMethods}}, tags={ {{#vendorExtensions.x-tags}}"{{tag}}"{{^-last}}, {{/-last}}{{/vendorExtensions.x-tags}} }) - @ApiResponses(value = { {{#responses}} - @ApiResponse(code = {{{code}}}, message = "{{{message}}}", response = {{{baseType}}}.class{{#returnContainer}}, responseContainer = "{{{.}}}"{{/returnContainer}}){{^-last}},{{/-last}}{{/responses}} }){{/useSwaggerAnnotations}} + @Produces({{#produces}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/produces}}){{/hasProduces}} {{#useCoroutines}}suspend {{/useCoroutines}}fun {{nickname}}({{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}}{{^-last}},{{/-last}}{{/allParams}}){{#returnResponse}}: {{#useMutiny}}io.smallrye.mutiny.Uni<{{/useMutiny}}Response{{#useMutiny}}>{{/useMutiny}}{{/returnResponse}}{{^returnResponse}}{{#returnType}}: {{#useMutiny}}io.smallrye.mutiny.Uni<{{/useMutiny}}{{{returnType}}}{{#useMutiny}}>{{/useMutiny}}{{/returnType}}{{/returnResponse}}{{^returnResponse}}{{^returnType}}{{#useMutiny}}: io.smallrye.mutiny.Uni{{/useMutiny}}{{/returnType}}{{/returnResponse}} \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/kotlin-server/libraries/jaxrs-spec/apiMethod.mustache b/modules/openapi-generator/src/main/resources/kotlin-server/libraries/jaxrs-spec/apiMethod.mustache index bfe70607f176..fbec264b3658 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-server/libraries/jaxrs-spec/apiMethod.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-server/libraries/jaxrs-spec/apiMethod.mustache @@ -1,16 +1,7 @@ @{{httpMethod}}{{#subresourceOperation}} @Path("{{{path}}}"){{/subresourceOperation}}{{#hasConsumes}} @Consumes({{#consumes}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/consumes}}){{/hasConsumes}}{{#hasProduces}} - @Produces({{#produces}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/produces}}){{/hasProduces}}{{#useSwaggerAnnotations}} - @ApiOperation(value = "{{{summary}}}", notes = "{{{notes}}}", response = {{{returnBaseType}}}.class{{#returnContainer}}, responseContainer = "{{{.}}}"{{/returnContainer}}{{#hasAuthMethods}}, authorizations = { - {{#authMethods}}{{#isOAuth}}@Authorization(value = "{{name}}", scopes = { - {{#scopes}}@AuthorizationScope(scope = "{{scope}}", description = "{{description}}"){{^-last}}, - {{/-last}}{{/scopes}} }){{^-last}},{{/-last}}{{/isOAuth}} - {{^isOAuth}}@Authorization(value = "{{name}}"){{^-last}},{{/-last}} - {{/isOAuth}}{{/authMethods}} }{{/hasAuthMethods}}, tags={ {{#vendorExtensions.x-tags}}"{{tag}}"{{^-last}}, {{/-last}}{{/vendorExtensions.x-tags}} }) - @ApiResponses(value = { {{#responses}} - @ApiResponse(code = {{{code}}}, message = "{{{message}}}", response = {{{baseType}}}.class{{#containerType}}, responseContainer = "{{{.}}}"{{/containerType}}){{^-last}},{{/-last}}{{/responses}} - }){{/useSwaggerAnnotations}} + @Produces({{#produces}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/produces}}){{/hasProduces}} {{#useCoroutines}}suspend {{/useCoroutines}}fun {{nickname}}({{#allParams}}{{>queryParams}}{{>pathParams}}{{>cookieParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}}{{^-last}},{{/-last}}{{/allParams}}): Response { return Response.ok().entity("magic!").build(); } \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/kotlin-server/libraries/jaxrs-spec/cookieParams.mustache b/modules/openapi-generator/src/main/resources/kotlin-server/libraries/jaxrs-spec/cookieParams.mustache index a2d0343c1730..929a3218703d 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-server/libraries/jaxrs-spec/cookieParams.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-server/libraries/jaxrs-spec/cookieParams.mustache @@ -1 +1 @@ -{{#isCookieParam}}@CookieParam("{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"){{#useBeanValidation}}{{>beanValidationQueryParams}}{{/useBeanValidation}}{{^isContainer}}{{#defaultValue}} @DefaultValue({{#lambda.doublequote}}{{{.}}}{{/lambda.doublequote}}){{/defaultValue}}{{/isContainer}} {{#useSwaggerAnnotations}}{{#description}} @ApiParam("{{.}}"){{/description}}{{/useSwaggerAnnotations}} {{paramName}}: {{{dataType}}}{{#isNullable}}?{{/isNullable}}{{^isNullable}}{{^defaultValue}}{{^required}}?{{/required}}{{/defaultValue}}{{/isNullable}}{{/isCookieParam}} \ No newline at end of file +{{#isCookieParam}}@CookieParam("{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"){{#useBeanValidation}}{{>beanValidationQueryParams}}{{/useBeanValidation}}{{^isContainer}}{{#defaultValue}} @DefaultValue({{#lambda.doublequote}}{{{.}}}{{/lambda.doublequote}}){{/defaultValue}}{{/isContainer}} {{paramName}}: {{{dataType}}}{{#isNullable}}?{{/isNullable}}{{^isNullable}}{{^defaultValue}}{{^required}}?{{/required}}{{/defaultValue}}{{/isNullable}}{{/isCookieParam}} \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/kotlin-server/libraries/jaxrs-spec/headerParams.mustache b/modules/openapi-generator/src/main/resources/kotlin-server/libraries/jaxrs-spec/headerParams.mustache index b637f85e0501..cc1ce2f3ea90 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-server/libraries/jaxrs-spec/headerParams.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-server/libraries/jaxrs-spec/headerParams.mustache @@ -1 +1 @@ -{{#isHeaderParam}}@HeaderParam("{{baseName}}"){{#useBeanValidation}}{{>beanValidationHeaderParams}}{{/useBeanValidation}} {{#defaultValue}} @DefaultValue({{#lambda.doublequote}}{{{.}}}{{/lambda.doublequote}}){{/defaultValue}} {{#useSwaggerAnnotations}}{{#description}} @ApiParam("{{.}}"){{/description}}{{/useSwaggerAnnotations}} {{paramName}}: {{{dataType}}}{{#isNullable}}?{{/isNullable}}{{^isNullable}}{{^defaultValue}}{{^required}}?{{/required}}{{/defaultValue}}{{/isNullable}}{{/isHeaderParam}} \ No newline at end of file +{{#isHeaderParam}}@HeaderParam("{{baseName}}"){{#useBeanValidation}}{{>beanValidationHeaderParams}}{{/useBeanValidation}} {{#defaultValue}} @DefaultValue({{#lambda.doublequote}}{{{.}}}{{/lambda.doublequote}}){{/defaultValue}} {{paramName}}: {{{dataType}}}{{#isNullable}}?{{/isNullable}}{{^isNullable}}{{^defaultValue}}{{^required}}?{{/required}}{{/defaultValue}}{{/isNullable}}{{/isHeaderParam}} \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/kotlin-server/libraries/jaxrs-spec/pathParams.mustache b/modules/openapi-generator/src/main/resources/kotlin-server/libraries/jaxrs-spec/pathParams.mustache index b148f41beac6..ac9cc4860acb 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-server/libraries/jaxrs-spec/pathParams.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-server/libraries/jaxrs-spec/pathParams.mustache @@ -1 +1 @@ -{{#isPathParam}}@PathParam("{{#lambda.escapeDollar}}{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}{{/lambda.escapeDollar}}"){{#useBeanValidation}}{{>beanValidationPathParams}}{{/useBeanValidation}}{{#useSwaggerAnnotations}}{{#description}} @ApiParam("{{.}}"){{/description}}{{/useSwaggerAnnotations}} {{paramName}}: {{{dataType}}}{{#isNullable}}?{{/isNullable}}{{^isNullable}}{{^defaultValue}}{{^required}}?{{/required}}{{/defaultValue}}{{/isNullable}}{{/isPathParam}} \ No newline at end of file +{{#isPathParam}}@PathParam("{{#lambda.escapeDollar}}{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}{{/lambda.escapeDollar}}"){{#useBeanValidation}}{{>beanValidationPathParams}}{{/useBeanValidation}} {{paramName}}: {{{dataType}}}{{#isNullable}}?{{/isNullable}}{{^isNullable}}{{^defaultValue}}{{^required}}?{{/required}}{{/defaultValue}}{{/isNullable}}{{/isPathParam}} \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/kotlin-server/libraries/jaxrs-spec/queryParams.mustache b/modules/openapi-generator/src/main/resources/kotlin-server/libraries/jaxrs-spec/queryParams.mustache index 690cef49eb48..a0155cf4b59d 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-server/libraries/jaxrs-spec/queryParams.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-server/libraries/jaxrs-spec/queryParams.mustache @@ -1 +1 @@ -{{#isQueryParam}}@QueryParam("{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"){{#useBeanValidation}}{{>beanValidationQueryParams}}{{/useBeanValidation}}{{^isContainer}}{{#defaultValue}} @DefaultValue({{#lambda.doublequote}}{{{.}}}{{/lambda.doublequote}}){{/defaultValue}}{{/isContainer}} {{#useSwaggerAnnotations}}{{#description}} @ApiParam("{{.}}"){{/description}}{{/useSwaggerAnnotations}} {{paramName}}: {{{dataType}}}{{#isNullable}}?{{/isNullable}}{{^isNullable}}{{^defaultValue}}{{^required}}?{{/required}}{{/defaultValue}}{{/isNullable}}{{/isQueryParam}} \ No newline at end of file +{{#isQueryParam}}@QueryParam("{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"){{#useBeanValidation}}{{>beanValidationQueryParams}}{{/useBeanValidation}}{{^isContainer}}{{#defaultValue}} @DefaultValue({{#lambda.doublequote}}{{{.}}}{{/lambda.doublequote}}){{/defaultValue}}{{/isContainer}} {{paramName}}: {{{dataType}}}{{#isNullable}}?{{/isNullable}}{{^isNullable}}{{^defaultValue}}{{^required}}?{{/required}}{{/defaultValue}}{{/isNullable}}{{/isQueryParam}} \ No newline at end of file From 58e05ce4c2d1414bed49286915162d3f549da844 Mon Sep 17 00:00:00 2001 From: feczkob Date: Mon, 30 Mar 2026 21:41:10 +0200 Subject: [PATCH 2/6] Add implicit headers to AbstractKotlinCodegen --- .../languages/AbstractKotlinCodegen.java | 53 ++++++++++++++++--- 1 file changed, 45 insertions(+), 8 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractKotlinCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractKotlinCodegen.java index 545278224b99..734dae1971f3 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractKotlinCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractKotlinCodegen.java @@ -30,6 +30,7 @@ import org.openapitools.codegen.*; import org.openapitools.codegen.model.ModelMap; import org.openapitools.codegen.model.ModelsMap; +import org.openapitools.codegen.model.OperationsMap; import org.openapitools.codegen.templating.mustache.EscapeChar; import org.openapitools.codegen.utils.ModelUtils; import org.slf4j.Logger; @@ -66,6 +67,7 @@ public abstract class AbstractKotlinCodegen extends DefaultCodegen implements Co public static final String SCHEMA_IMPLEMENTS_FIELDS = "schemaImplementsFields"; public static final String X_KOTLIN_IMPLEMENTS_SKIP = "xKotlinImplementsSkip"; public static final String X_KOTLIN_IMPLEMENTS_FIELDS_SKIP = "xKotlinImplementsFieldsSkip"; + public static final String IMPLICIT_HEADERS = "implicitHeaders"; private final Logger LOGGER = LoggerFactory.getLogger(AbstractKotlinCodegen.class); @@ -81,6 +83,7 @@ public abstract class AbstractKotlinCodegen extends DefaultCodegen implements Co protected String apiDocPath = "docs/"; protected String modelDocPath = "docs/"; + @Setter protected boolean parcelizeModels = false; @Getter @Setter protected boolean serializableModel = false; @@ -111,6 +114,8 @@ public abstract class AbstractKotlinCodegen extends DefaultCodegen implements Co @Getter @Setter protected Map> xKotlinImplementsFieldsSkip = new HashMap<>(); + @Setter + protected boolean implicitHeaders = false; public AbstractKotlinCodegen() { super(); @@ -294,6 +299,7 @@ public AbstractKotlinCodegen() { cliOptions.add(CliOption.newBoolean(MODEL_MUTABLE, MODEL_MUTABLE_DESC, false)); cliOptions.add(CliOption.newString(ADDITIONAL_MODEL_TYPE_ANNOTATIONS, "Additional annotations for model type(class level annotations). List separated by semicolon(;) or new line (Linux or Windows)")); + cliOptions.add(CliOption.newBoolean(IMPLICIT_HEADERS, "Skip header parameters in the generated API methods.", implicitHeaders)); } @Override @@ -451,6 +457,43 @@ public ModelsMap postProcessModels(ModelsMap objs) { return postProcessModelsEnum(objs); } + @Override + public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List allModels) { + handleImplicitHeaders(objs); + return objs; + } + + protected void handleImplicitHeaders(OperationsMap objs) { + if (!implicitHeaders) { + return; + } + + objs.getOperations().getOperation().forEach(this::handleImplicitHeaders); + } + + /** + * This method removes all implicit header parameters from the list of parameters + * + * @param operation - operation to be processed + */ + private void handleImplicitHeaders(CodegenOperation operation) { + if (operation.allParams.isEmpty()) { + return; + } + final ArrayList copy = new ArrayList<>(operation.allParams); + operation.allParams.clear(); + + for (CodegenParameter p : copy) { + if (p.isHeaderParam) { + operation.implicitHeadersParams.add(p); + operation.headerParams.removeIf(header -> header.baseName.equals(p.baseName)); + LOGGER.debug("Update operation [{}]. Remove header [{}] because it's marked to be implicit", operation.operationId, p.baseName); + } else { + operation.allParams.add(p); + } + } + } + @Override public void processOpts() { super.processOpts(); @@ -587,20 +630,14 @@ public void processOpts() { } else { applyJackson2Package(); } + + convertPropertyToBooleanAndWriteBack(IMPLICIT_HEADERS, this::setImplicitHeaders); } protected boolean isModelMutable() { return Boolean.TRUE.equals(additionalProperties.get(MODEL_MUTABLE)); } - public Boolean getParcelizeModels() { - return parcelizeModels; - } - - public void setParcelizeModels(Boolean parcelizeModels) { - this.parcelizeModels = parcelizeModels; - } - public boolean nonPublicApi() { return nonPublicApi; } From 22c1439db8a7033a8e1c1e080a368315f7f1eacf Mon Sep 17 00:00:00 2001 From: feczkob Date: Mon, 30 Mar 2026 21:41:41 +0200 Subject: [PATCH 3/6] Handle implicit headers KotlinMiskServerCodegen, KotlinSpringServerCodegen and KotlinServerCodegen --- .../codegen/languages/KotlinMiskServerCodegen.java | 5 +++-- .../openapitools/codegen/languages/KotlinServerCodegen.java | 2 ++ .../codegen/languages/KotlinSpringServerCodegen.java | 6 ++---- .../kotlin/misk/KotlinMiskServerCodegenOptionsTest.java | 1 + .../options/KotlinMiskServerCodegenOptionsProvider.java | 2 ++ 5 files changed, 10 insertions(+), 6 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinMiskServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinMiskServerCodegen.java index f873d7061362..b9f67ab9942b 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinMiskServerCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinMiskServerCodegen.java @@ -258,7 +258,6 @@ public void processOpts() { public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List allModels) { OperationMap objectMap = objs.getOperations(); List operations = objectMap.getOperation(); - for (CodegenOperation operation : operations) { if (operation.hasConsumes) { @@ -277,6 +276,8 @@ public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List getMappings() { return result; } -} \ No newline at end of file +} diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinServerCodegen.java index a95763ad030b..f8b0cb2c224b 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinServerCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinServerCodegen.java @@ -786,6 +786,8 @@ public void setReturnContainer(final String returnContainer) { }); } + handleImplicitHeaders(objs); + return objs; } diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinSpringServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinSpringServerCodegen.java index 6730dd636649..5dc081bbd3ab 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinSpringServerCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinSpringServerCodegen.java @@ -1317,10 +1317,6 @@ public void setReturnContainer(final String returnContainer) { } } } - -// if(implicitHeaders){ -// removeHeadersFromAllParams(operation.allParams); -// } }); // Add imports for sealed interfaces if feature is enabled @@ -1345,6 +1341,8 @@ public void setReturnContainer(final String returnContainer) { } } + handleImplicitHeaders(objs); + return objs; } diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/misk/KotlinMiskServerCodegenOptionsTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/misk/KotlinMiskServerCodegenOptionsTest.java index 08c33550e4de..724626266f24 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/misk/KotlinMiskServerCodegenOptionsTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/misk/KotlinMiskServerCodegenOptionsTest.java @@ -46,5 +46,6 @@ protected void verifyOptions() { verify(codegen).setActionRequestContentTypePrefix(KotlinMiskServerCodegenOptionsProvider.ACTION_REQUEST_CONTENT_TYPE_PREFIX); verify(codegen).setGenerateStubImplClasses(Boolean.valueOf(KotlinMiskServerCodegenOptionsProvider.GENERATE_STUB_IMPL_CLASSES)); verify(codegen).setAddModelMoshiJsonAnnotation(Boolean.valueOf(KotlinMiskServerCodegenOptionsProvider.ADD_MODEL_MOSHI_JSON_ANNOTATION)); + verify(codegen).setImplicitHeaders(Boolean.valueOf(KotlinMiskServerCodegenOptionsProvider.IMPLICIT_HEADERS_VALUE)); } } diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/KotlinMiskServerCodegenOptionsProvider.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/KotlinMiskServerCodegenOptionsProvider.java index 9c83f51b05f6..04d3783b19f5 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/KotlinMiskServerCodegenOptionsProvider.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/KotlinMiskServerCodegenOptionsProvider.java @@ -33,6 +33,7 @@ public class KotlinMiskServerCodegenOptionsProvider implements OptionsProvider { public static final String ACTION_REQUEST_CONTENT_TYPE = "contentType<"; public static final String ACTION_REQUEST_CONTENT_TYPE_PREFIX = "contentTypePrefix<"; public static final String TESTING_MODULE = "testingModule"; + public static final String IMPLICIT_HEADERS_VALUE = "false"; @Override public String getLanguage() { @@ -69,6 +70,7 @@ public Map createOptions() { .put(KotlinMiskServerCodegen.ADD_MODEL_MOSHI_JSON_ANNOTATION, ADD_MODEL_MOSHI_JSON_ANNOTATION) .put(KotlinMiskServerCodegen.GENERATE_STUB_IMPL_CLASSES, GENERATE_STUB_IMPL_CLASSES) .put(KotlinMiskServerCodegen.TESTING_MODULE, TESTING_MODULE) + .put(AbstractKotlinCodegen.IMPLICIT_HEADERS, IMPLICIT_HEADERS_VALUE) .build(); } From 88286e2739f0840445c609bb1ae2b7dfee8b8b12 Mon Sep 17 00:00:00 2001 From: feczkob Date: Tue, 31 Mar 2026 22:03:59 +0200 Subject: [PATCH 4/6] Update mustache files for Kotlin Spring --- .../main/resources/kotlin-spring/api.mustache | 7 ++ .../kotlin-spring/apiInterface.mustache | 7 ++ .../kotlin-spring/implicitHeaders.mustache | 14 ++++ .../spring/KotlinSpringServerCodegenTest.java | 69 +++++++++++++++---- 4 files changed, 84 insertions(+), 13 deletions(-) create mode 100644 modules/openapi-generator/src/main/resources/kotlin-spring/implicitHeaders.mustache diff --git a/modules/openapi-generator/src/main/resources/kotlin-spring/api.mustache b/modules/openapi-generator/src/main/resources/kotlin-spring/api.mustache index 3356f988d838..253cd1719766 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-spring/api.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-spring/api.mustache @@ -11,6 +11,10 @@ import io.swagger.v3.oas.annotations.security.* {{/swagger2AnnotationLibrary}} {{#swagger1AnnotationLibrary}} import io.swagger.annotations.Api +{{#implicitHeaders}} +import io.swagger.annotations.ApiImplicitParam +import io.swagger.annotations.ApiImplicitParams +{{/implicitHeaders}} import io.swagger.annotations.ApiOperation import io.swagger.annotations.ApiParam import io.swagger.annotations.ApiResponse @@ -84,6 +88,9 @@ class {{classname}}Controller({{#serviceInterface}}@Autowired(required = true) v authorizations = [{{#authMethods}}Authorization(value = "{{name}}"{{#isOAuth}}, scopes = [{{#scopes}}AuthorizationScope(scope = "{{scope}}", description = "{{description}}"){{^-last}}, {{/-last}}{{/scopes}}]{{/isOAuth}}){{^-last}}, {{/-last}}{{/authMethods}}]{{/hasAuthMethods}}) @ApiResponses( value = [{{#responses}}ApiResponse(code = {{{code}}}, message = "{{{message}}}"{{#baseType}}, response = {{{.}}}::class{{/baseType}}{{#containerType}}, responseContainer = "{{{.}}}"{{/containerType}}){{^-last}},{{/-last}}{{/responses}}]){{/swagger1AnnotationLibrary}} +{{#implicitHeadersParams.0}} +{{>implicitHeaders}} +{{/implicitHeadersParams.0}} {{#vendorExtensions.x-operation-extra-annotation}} {{{.}}} {{/vendorExtensions.x-operation-extra-annotation}} diff --git a/modules/openapi-generator/src/main/resources/kotlin-spring/apiInterface.mustache b/modules/openapi-generator/src/main/resources/kotlin-spring/apiInterface.mustache index f3bacfe43727..04232e570533 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-spring/apiInterface.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-spring/apiInterface.mustache @@ -16,6 +16,10 @@ import io.swagger.v3.oas.annotations.security.* {{/swagger2AnnotationLibrary}} {{#swagger1AnnotationLibrary}} import io.swagger.annotations.Api +{{#implicitHeaders}} +import io.swagger.annotations.ApiImplicitParam +import io.swagger.annotations.ApiImplicitParams +{{/implicitHeaders}} import io.swagger.annotations.ApiOperation import io.swagger.annotations.ApiParam import io.swagger.annotations.ApiResponse @@ -99,6 +103,9 @@ interface {{classname}} { @ApiResponses( value = [{{#responses}}ApiResponse(code = {{{code}}}, message = "{{{message}}}"{{#baseType}}, response = {{{.}}}::class{{/baseType}}{{#containerType}}, responseContainer = "{{{.}}}"{{/containerType}}){{^-last}}, {{/-last}}{{/responses}}] ){{/swagger1AnnotationLibrary}} +{{#implicitHeadersParams.0}} +{{>implicitHeaders}} +{{/implicitHeadersParams.0}} {{#vendorExtensions.x-operation-extra-annotation}} {{{.}}} {{/vendorExtensions.x-operation-extra-annotation}} diff --git a/modules/openapi-generator/src/main/resources/kotlin-spring/implicitHeaders.mustache b/modules/openapi-generator/src/main/resources/kotlin-spring/implicitHeaders.mustache new file mode 100644 index 000000000000..c7b37059e2d9 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/kotlin-spring/implicitHeaders.mustache @@ -0,0 +1,14 @@ +{{#swagger2AnnotationLibrary}} + @Parameters(value = [ + {{#implicitHeadersParams}} + Parameter(name = "{{{baseName}}}"{{#isDeprecated}}, deprecated = true{{/isDeprecated}}, description = "{{{description}}}"{{#required}}, required = true{{/required}}, `in` = ParameterIn.HEADER){{^-last}},{{/-last}} + {{/implicitHeadersParams}} + ]) +{{/swagger2AnnotationLibrary}} +{{#swagger1AnnotationLibrary}} + @ApiImplicitParams(value = [ + {{#implicitHeadersParams}} + ApiImplicitParam(name = "{{{baseName}}}", value = "{{{description}}}", {{#required}}required = true,{{/required}} dataType = "{{{dataType}}}", paramType = "header"){{^-last}},{{/-last}} + {{/implicitHeadersParams}} + ]) +{{/swagger1AnnotationLibrary}} \ No newline at end of file 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 6ddddea15b42..504583c759dd 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 @@ -39,6 +39,8 @@ import java.util.Map; import java.util.function.Consumer; import java.util.function.Function; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -3831,7 +3833,7 @@ public void customPageableSchemaNotOverridden_issue13052() throws Exception { additionalProperties.put(DOCUMENTATION_PROVIDER, "springdoc"); additionalProperties.put(INTERFACE_ONLY, "true"); additionalProperties.put(SKIP_DEFAULT_INTERFACE, "true"); - + Map files = generateFromContract("src/test/resources/bugs/issue_13052.yaml", additionalProperties); // Custom Pageable model should be used instead of Spring's Pageable @@ -3849,7 +3851,7 @@ public void springPaginatedWithNoDocumentationProvider() throws Exception { additionalProperties.put(DOCUMENTATION_PROVIDER, "none"); additionalProperties.put(INTERFACE_ONLY, "true"); additionalProperties.put(SKIP_DEFAULT_INTERFACE, "true"); - + Map files = generateFromContract("src/test/resources/3_0/spring/petstore-with-spring-pageable.yaml", additionalProperties); // Pageable should be added but no annotation imports @@ -3912,7 +3914,7 @@ public void springPaginatedNoParamsNoContext() throws Exception { additionalProperties.put(DOCUMENTATION_PROVIDER, "springdoc"); additionalProperties.put(INTERFACE_ONLY, "true"); additionalProperties.put(SKIP_DEFAULT_INTERFACE, "true"); - + Map files = generateFromContract("src/test/resources/3_0/spring/petstore-with-spring-pageable.yaml", additionalProperties); // Test operation listAllPets which has no parameters except pageable @@ -4018,15 +4020,15 @@ public void springPaginatedMixedOperations() throws Exception { additionalProperties.put(DOCUMENTATION_PROVIDER, "springdoc"); additionalProperties.put(INTERFACE_ONLY, "true"); additionalProperties.put(SKIP_DEFAULT_INTERFACE, "true"); - + Map files = generateFromContract("src/test/resources/3_0/spring/petstore-with-spring-pageable.yaml", additionalProperties); File petApi = files.get("PetApi.kt"); - + // Operation with x-spring-paginated should have Pageable assertFileContains(petApi.toPath(), "fun findPetsByStatus("); assertFileContains(petApi.toPath(), "pageable: Pageable"); - + // Operation without x-spring-paginated should NOT have Pageable assertFileContains(petApi.toPath(), "fun addPet("); // Verify addPet doesn't have pageable (it has body param only) @@ -4035,7 +4037,7 @@ public void springPaginatedMixedOperations() throws Exception { content.indexOf("fun addPet("), content.indexOf(")", content.indexOf("fun addPet(")) + 1 ); - Assert.assertFalse(addPetMethod.contains("pageable"), + Assert.assertFalse(addPetMethod.contains("pageable"), "addPet should not have pageable parameter"); } @@ -4045,7 +4047,7 @@ public void springPaginatedWithServiceInterface() throws Exception { additionalProperties.put(USE_TAGS, "true"); additionalProperties.put(DOCUMENTATION_PROVIDER, "springdoc"); additionalProperties.put(SERVICE_INTERFACE, "true"); - + Map files = generateFromContract("src/test/resources/3_0/spring/petstore-with-spring-pageable.yaml", additionalProperties); // Test that pageable is in service interface @@ -4064,7 +4066,7 @@ public void springPaginatedParameterOrdering() throws Exception { additionalProperties.put(INTERFACE_ONLY, "true"); additionalProperties.put(SKIP_DEFAULT_INTERFACE, "true"); additionalProperties.put(INCLUDE_HTTP_REQUEST_CONTEXT, "true"); - + Map files = generateFromContract("src/test/resources/3_0/spring/petstore-with-spring-pageable.yaml", additionalProperties); // Verify exact parameter ordering: allParams -> request -> pageable @@ -4075,12 +4077,12 @@ public void springPaginatedParameterOrdering() throws Exception { int methodStart = content.indexOf("fun findPetsByStatus("); int methodEnd = content.indexOf("): ResponseEntity", methodStart); String methodSignature = content.substring(methodStart, methodEnd); - + // Verify order: status param comes before request, request comes before pageable int statusPos = methodSignature.indexOf("status:"); int requestPos = methodSignature.indexOf("request:"); int pageablePos = methodSignature.indexOf("pageable:"); - + Assert.assertTrue(statusPos > 0, "status parameter should exist"); Assert.assertTrue(requestPos > statusPos, "request should come after status"); Assert.assertTrue(pageablePos > requestPos, "pageable should come after request"); @@ -4093,7 +4095,7 @@ public void springPaginatedDelegateCallPassesPageable() throws Exception { additionalProperties.put(DOCUMENTATION_PROVIDER, "springdoc"); additionalProperties.put(DELEGATE_PATTERN, "true"); additionalProperties.put(INTERFACE_ONLY, "false"); - + Map files = generateFromContract("src/test/resources/3_0/spring/petstore-with-spring-pageable.yaml", additionalProperties); // Verify that interface method calls delegate with pageable parameter @@ -5009,6 +5011,47 @@ public void shouldDefaultToJackson3WhenSpringBoot4EnabledViaSetter() throws IOEx assertFileNotContains(pomPath, "com.fasterxml.jackson.module"); assertFileNotContains(pomPath, "jackson-datatype-jsr310"); } -} + @Test + public void shouldAddParameterWithInHeaderWhenImplicitHeadersIsTrue() throws IOException { + File output = Files.createTempDirectory("test").toFile().getCanonicalFile(); + output.deleteOnExit(); + OpenAPI openAPI = new OpenAPIParser() + .readLocation("src/test/resources/bugs/issue_14418.yaml", null, new ParseOptions()).getOpenAPI(); + + KotlinSpringServerCodegen codegen = new KotlinSpringServerCodegen(); + codegen.setLibrary(SPRING_BOOT); + codegen.setOutputDir(output.getAbsolutePath()); + codegen.additionalProperties().put(KotlinSpringServerCodegen.INTERFACE_ONLY, "true"); + codegen.additionalProperties().put(CodegenConstants.MODEL_PACKAGE, "xyz.model"); + codegen.additionalProperties().put(CodegenConstants.API_PACKAGE, "xyz.controller"); + codegen.additionalProperties().put(AbstractKotlinCodegen.IMPLICIT_HEADERS, "true"); + + ClientOptInput input = new ClientOptInput() + .openAPI(openAPI) + .config(codegen); + + DefaultGenerator generator = new DefaultGenerator(); + generator.setGenerateMetadata(false); + Map files = generator.opts(input).generate().stream() + .collect(Collectors.toMap(File::getName, Function.identity())); + + File testApi = files.get("TestApi.kt"); + String content = Files.readString(testApi.toPath()); + String methodPattern = "fun test\\s*\\(.*?\\)"; + Pattern pattern = Pattern.compile(methodPattern); + + Matcher matcher = pattern.matcher(content); + Assert.assertTrue(matcher.find(), "Method 'test' should be found in generated file"); + + String methodSignature = matcher.group(); + Assert.assertFalse(methodSignature.contains("testHeader"), + "Header param 'testHeader' should NOT be in method signature when implicitHeaders=true"); + + Assert.assertTrue(content.contains("@Parameters"), + "@Parameters annotation should be present"); + Assert.assertTrue(content.contains("testHeader"), + "Header name 'testHeader' should appear in the annotation"); + } +} From a4e564d148a6a6b1a77efd82509bbf1d9bdc4854 Mon Sep 17 00:00:00 2001 From: feczkob Date: Wed, 1 Apr 2026 15:42:41 +0200 Subject: [PATCH 5/6] Update configs and regenerate samples --- bin/configs/kotlin-server-jaxrs-spec.yaml | 1 + bin/configs/kotlin-spring-boot-source-swagger1.yaml | 1 + bin/configs/kotlin-spring-boot-source-swagger2.yaml | 1 + .../kotlin/org/openapitools/server/apis/DefaultApi.kt | 2 +- .../main/kotlin/org/openapitools/server/apis/PetApi.kt | 6 +++--- .../kotlin/org/openapitools/server/apis/UserApi.kt | 2 +- .../main/kotlin/org/openapitools/server/apis/PetApi.kt | 6 +++--- .../kotlin/org/openapitools/server/apis/UserApi.kt | 2 +- .../kotlin/org/openapitools/api/PetApiController.kt | 10 +++++++--- .../main/kotlin/org/openapitools/api/PetApiService.kt | 3 +-- .../kotlin/org/openapitools/api/PetApiServiceImpl.kt | 2 +- .../kotlin/org/openapitools/api/StoreApiController.kt | 2 ++ .../kotlin/org/openapitools/api/UserApiController.kt | 2 ++ .../kotlin/org/openapitools/api/PetApiController.kt | 8 +++++--- .../main/kotlin/org/openapitools/api/PetApiService.kt | 3 +-- .../kotlin/org/openapitools/api/PetApiServiceImpl.kt | 2 +- 16 files changed, 32 insertions(+), 21 deletions(-) diff --git a/bin/configs/kotlin-server-jaxrs-spec.yaml b/bin/configs/kotlin-server-jaxrs-spec.yaml index 14afd5eb5fb9..3ffc6a51f1d5 100644 --- a/bin/configs/kotlin-server-jaxrs-spec.yaml +++ b/bin/configs/kotlin-server-jaxrs-spec.yaml @@ -6,3 +6,4 @@ templateDir: modules/openapi-generator/src/main/resources/kotlin-server additionalProperties: useCoroutines: "true" useTags: "true" + implicitHeaders: "true" diff --git a/bin/configs/kotlin-spring-boot-source-swagger1.yaml b/bin/configs/kotlin-spring-boot-source-swagger1.yaml index 5f877b6c9a1c..4c6ce15fda44 100644 --- a/bin/configs/kotlin-spring-boot-source-swagger1.yaml +++ b/bin/configs/kotlin-spring-boot-source-swagger1.yaml @@ -10,3 +10,4 @@ additionalProperties: serviceImplementation: "true" serializableModel: "true" beanValidations: "true" + implicitHeaders: "true" diff --git a/bin/configs/kotlin-spring-boot-source-swagger2.yaml b/bin/configs/kotlin-spring-boot-source-swagger2.yaml index bd08d444d471..aab768cb39c2 100644 --- a/bin/configs/kotlin-spring-boot-source-swagger2.yaml +++ b/bin/configs/kotlin-spring-boot-source-swagger2.yaml @@ -10,3 +10,4 @@ additionalProperties: serviceImplementation: "true" serializableModel: "true" beanValidations: "true" + implicitHeaders: "true" diff --git a/samples/server/others/kotlin-server/jaxrs-spec/src/main/kotlin/org/openapitools/server/apis/DefaultApi.kt b/samples/server/others/kotlin-server/jaxrs-spec/src/main/kotlin/org/openapitools/server/apis/DefaultApi.kt index 41c6db269aad..516e7ef25dfb 100644 --- a/samples/server/others/kotlin-server/jaxrs-spec/src/main/kotlin/org/openapitools/server/apis/DefaultApi.kt +++ b/samples/server/others/kotlin-server/jaxrs-spec/src/main/kotlin/org/openapitools/server/apis/DefaultApi.kt @@ -15,7 +15,7 @@ class DefaultApi { @GET @Path("/test/parameters/{path_default}/{path_nullable}") - suspend fun findPetsByStatus(@PathParam("path_default") pathDefault: kotlin.String,@PathParam("path_nullable") pathNullable: kotlin.String,@QueryParam("query_default") @DefaultValue("available") queryDefault: kotlin.String,@QueryParam("query_default_enum") @DefaultValue("B") queryDefaultEnum: kotlin.String,@QueryParam("query_default_int") @DefaultValue("3") queryDefaultInt: java.math.BigDecimal,@HeaderParam("header_default") @DefaultValue("available") headerDefault: kotlin.String,@HeaderParam("header_default_enum") @DefaultValue("B") headerDefaultEnum: kotlin.String,@HeaderParam("header_default_int") @DefaultValue("3") headerDefaultInt: java.math.BigDecimal,@CookieParam("cookie_default") @DefaultValue("available") cookieDefault: kotlin.String,@CookieParam("cookie_default_enum") @DefaultValue("B") cookieDefaultEnum: kotlin.String,@CookieParam("cookie_default_int") @DefaultValue("3") cookieDefaultInt: java.math.BigDecimal,@QueryParam("query_nullable") queryNullable: kotlin.String?,@HeaderParam("header_nullable") headerNullable: kotlin.String?,@CookieParam("cookie_nullable") cookieNullable: kotlin.String?,@QueryParam("\$query-\$dollar-sign") dollarQueryDollarDollarSign: kotlin.String?): Response { + suspend fun findPetsByStatus(@PathParam("path_default") pathDefault: kotlin.String,@PathParam("path_nullable") pathNullable: kotlin.String,@QueryParam("query_default") @DefaultValue("available") queryDefault: kotlin.String,@QueryParam("query_default_enum") @DefaultValue("B") queryDefaultEnum: kotlin.String,@QueryParam("query_default_int") @DefaultValue("3") queryDefaultInt: java.math.BigDecimal,@HeaderParam("header_default") @DefaultValue("available") headerDefault: kotlin.String,@HeaderParam("header_default_enum") @DefaultValue("B") headerDefaultEnum: kotlin.String,@HeaderParam("header_default_int") @DefaultValue("3") headerDefaultInt: java.math.BigDecimal,@CookieParam("cookie_default") @DefaultValue("available") cookieDefault: kotlin.String,@CookieParam("cookie_default_enum") @DefaultValue("B") cookieDefaultEnum: kotlin.String,@CookieParam("cookie_default_int") @DefaultValue("3") cookieDefaultInt: java.math.BigDecimal,@QueryParam("query_nullable") queryNullable: kotlin.String?,@HeaderParam("header_nullable") headerNullable: kotlin.String?,@CookieParam("cookie_nullable") cookieNullable: kotlin.String?,@QueryParam("\$query-\$dollar-sign") dollarQueryDollarDollarSign: kotlin.String?): Response { return Response.ok().entity("magic!").build(); } } diff --git a/samples/server/petstore/kotlin-server/jaxrs-spec-mutiny/src/main/kotlin/org/openapitools/server/apis/PetApi.kt b/samples/server/petstore/kotlin-server/jaxrs-spec-mutiny/src/main/kotlin/org/openapitools/server/apis/PetApi.kt index 8e118929ab6a..c5991e639955 100644 --- a/samples/server/petstore/kotlin-server/jaxrs-spec-mutiny/src/main/kotlin/org/openapitools/server/apis/PetApi.kt +++ b/samples/server/petstore/kotlin-server/jaxrs-spec-mutiny/src/main/kotlin/org/openapitools/server/apis/PetApi.kt @@ -22,17 +22,17 @@ interface PetApi { @DELETE @Path("/pet/{petId}") - fun deletePet(@PathParam("petId") petId: kotlin.Long,@HeaderParam("api_key") apiKey: kotlin.String?): io.smallrye.mutiny.Uni + fun deletePet(@PathParam("petId") petId: kotlin.Long,@HeaderParam("api_key") apiKey: kotlin.String?): io.smallrye.mutiny.Uni @GET @Path("/pet/findByStatus") @Produces("application/xml", "application/json") - fun findPetsByStatus(@QueryParam("status") status: kotlin.collections.List): io.smallrye.mutiny.Uni + fun findPetsByStatus(@QueryParam("status") status: kotlin.collections.List): io.smallrye.mutiny.Uni @GET @Path("/pet/findByTags") @Produces("application/xml", "application/json") - fun findPetsByTags(@QueryParam("tags") tags: kotlin.collections.List): io.smallrye.mutiny.Uni + fun findPetsByTags(@QueryParam("tags") tags: kotlin.collections.List): io.smallrye.mutiny.Uni @GET @Path("/pet/{petId}") diff --git a/samples/server/petstore/kotlin-server/jaxrs-spec-mutiny/src/main/kotlin/org/openapitools/server/apis/UserApi.kt b/samples/server/petstore/kotlin-server/jaxrs-spec-mutiny/src/main/kotlin/org/openapitools/server/apis/UserApi.kt index 2583090dd999..d8c542088541 100644 --- a/samples/server/petstore/kotlin-server/jaxrs-spec-mutiny/src/main/kotlin/org/openapitools/server/apis/UserApi.kt +++ b/samples/server/petstore/kotlin-server/jaxrs-spec-mutiny/src/main/kotlin/org/openapitools/server/apis/UserApi.kt @@ -38,7 +38,7 @@ interface UserApi { @GET @Path("/user/login") @Produces("application/xml", "application/json") - fun loginUser(@QueryParam("username") username: kotlin.String,@QueryParam("password") password: kotlin.String): io.smallrye.mutiny.Uni + fun loginUser(@QueryParam("username") username: kotlin.String,@QueryParam("password") password: kotlin.String): io.smallrye.mutiny.Uni @GET @Path("/user/logout") diff --git a/samples/server/petstore/kotlin-server/jaxrs-spec/src/main/kotlin/org/openapitools/server/apis/PetApi.kt b/samples/server/petstore/kotlin-server/jaxrs-spec/src/main/kotlin/org/openapitools/server/apis/PetApi.kt index 1dde8ab1ae90..79bc6a5e8617 100644 --- a/samples/server/petstore/kotlin-server/jaxrs-spec/src/main/kotlin/org/openapitools/server/apis/PetApi.kt +++ b/samples/server/petstore/kotlin-server/jaxrs-spec/src/main/kotlin/org/openapitools/server/apis/PetApi.kt @@ -23,21 +23,21 @@ class PetApi { @DELETE @Path("/{petId}") - suspend fun deletePet(@PathParam("petId") petId: kotlin.Long,@HeaderParam("api_key") apiKey: kotlin.String?): Response { + suspend fun deletePet(@PathParam("petId") petId: kotlin.Long): Response { return Response.ok().entity("magic!").build(); } @GET @Path("/findByStatus") @Produces("application/xml", "application/json") - suspend fun findPetsByStatus(@QueryParam("status") status: kotlin.collections.List): Response { + suspend fun findPetsByStatus(@QueryParam("status") status: kotlin.collections.List): Response { return Response.ok().entity("magic!").build(); } @GET @Path("/findByTags") @Produces("application/xml", "application/json") - suspend fun findPetsByTags(@QueryParam("tags") tags: kotlin.collections.List): Response { + suspend fun findPetsByTags(@QueryParam("tags") tags: kotlin.collections.List): Response { return Response.ok().entity("magic!").build(); } diff --git a/samples/server/petstore/kotlin-server/jaxrs-spec/src/main/kotlin/org/openapitools/server/apis/UserApi.kt b/samples/server/petstore/kotlin-server/jaxrs-spec/src/main/kotlin/org/openapitools/server/apis/UserApi.kt index 583e655d4819..40abc46c200d 100644 --- a/samples/server/petstore/kotlin-server/jaxrs-spec/src/main/kotlin/org/openapitools/server/apis/UserApi.kt +++ b/samples/server/petstore/kotlin-server/jaxrs-spec/src/main/kotlin/org/openapitools/server/apis/UserApi.kt @@ -47,7 +47,7 @@ class UserApi { @GET @Path("/login") @Produces("application/xml", "application/json") - suspend fun loginUser(@QueryParam("username") username: kotlin.String,@QueryParam("password") password: kotlin.String): Response { + suspend fun loginUser(@QueryParam("username") username: kotlin.String,@QueryParam("password") password: kotlin.String): Response { return Response.ok().entity("magic!").build(); } diff --git a/samples/server/petstore/kotlin-springboot-source-swagger1/src/main/kotlin/org/openapitools/api/PetApiController.kt b/samples/server/petstore/kotlin-springboot-source-swagger1/src/main/kotlin/org/openapitools/api/PetApiController.kt index 528e299c7357..0b693d6d6091 100644 --- a/samples/server/petstore/kotlin-springboot-source-swagger1/src/main/kotlin/org/openapitools/api/PetApiController.kt +++ b/samples/server/petstore/kotlin-springboot-source-swagger1/src/main/kotlin/org/openapitools/api/PetApiController.kt @@ -3,6 +3,8 @@ package org.openapitools.api import org.openapitools.model.ModelApiResponse import org.openapitools.model.Pet import io.swagger.annotations.Api +import io.swagger.annotations.ApiImplicitParam +import io.swagger.annotations.ApiImplicitParams import io.swagger.annotations.ApiOperation import io.swagger.annotations.ApiParam import io.swagger.annotations.ApiResponse @@ -65,16 +67,18 @@ class PetApiController(@Autowired(required = true) val service: PetApiService) { authorizations = [Authorization(value = "petstore_auth", scopes = [AuthorizationScope(scope = "write:pets", description = "modify pets in your account"), AuthorizationScope(scope = "read:pets", description = "read your pets")])]) @ApiResponses( value = [ApiResponse(code = 400, message = "Invalid pet value")]) + @ApiImplicitParams(value = [ + ApiImplicitParam(name = "api_key", value = "", dataType = "kotlin.String", paramType = "header") + ]) @RequestMapping( method = [RequestMethod.DELETE], // "/pet/{petId}" value = [PATH_DELETE_PET] ) fun deletePet( - @ApiParam(value = "Pet id to delete", required = true) @PathVariable("petId") petId: kotlin.Long, - @ApiParam(value = "") @RequestHeader(value = "api_key", required = false) apiKey: kotlin.String? + @ApiParam(value = "Pet id to delete", required = true) @PathVariable("petId") petId: kotlin.Long ): ResponseEntity { - return ResponseEntity(service.deletePet(petId, apiKey), HttpStatus.valueOf(400)) + return ResponseEntity(service.deletePet(petId), HttpStatus.valueOf(400)) } diff --git a/samples/server/petstore/kotlin-springboot-source-swagger1/src/main/kotlin/org/openapitools/api/PetApiService.kt b/samples/server/petstore/kotlin-springboot-source-swagger1/src/main/kotlin/org/openapitools/api/PetApiService.kt index 566196d1e86d..2fe7b38c0682 100644 --- a/samples/server/petstore/kotlin-springboot-source-swagger1/src/main/kotlin/org/openapitools/api/PetApiService.kt +++ b/samples/server/petstore/kotlin-springboot-source-swagger1/src/main/kotlin/org/openapitools/api/PetApiService.kt @@ -18,11 +18,10 @@ interface PetApiService { * DELETE /pet/{petId} : Deletes a pet * * @param petId Pet id to delete (required) - * @param apiKey (optional) * @return Invalid pet value (status code 400) * @see PetApi#deletePet */ - fun deletePet(petId: kotlin.Long, apiKey: kotlin.String?): Unit + fun deletePet(petId: kotlin.Long): Unit /** * GET /pet/findByStatus : Finds Pets by status diff --git a/samples/server/petstore/kotlin-springboot-source-swagger1/src/main/kotlin/org/openapitools/api/PetApiServiceImpl.kt b/samples/server/petstore/kotlin-springboot-source-swagger1/src/main/kotlin/org/openapitools/api/PetApiServiceImpl.kt index a48482be32bd..95b0546a3d9e 100644 --- a/samples/server/petstore/kotlin-springboot-source-swagger1/src/main/kotlin/org/openapitools/api/PetApiServiceImpl.kt +++ b/samples/server/petstore/kotlin-springboot-source-swagger1/src/main/kotlin/org/openapitools/api/PetApiServiceImpl.kt @@ -10,7 +10,7 @@ class PetApiServiceImpl : PetApiService { TODO("Implement me") } - override fun deletePet(petId: kotlin.Long, apiKey: kotlin.String?): Unit { + override fun deletePet(petId: kotlin.Long): Unit { TODO("Implement me") } diff --git a/samples/server/petstore/kotlin-springboot-source-swagger1/src/main/kotlin/org/openapitools/api/StoreApiController.kt b/samples/server/petstore/kotlin-springboot-source-swagger1/src/main/kotlin/org/openapitools/api/StoreApiController.kt index 2fcff50b5a80..db8663ba2a2f 100644 --- a/samples/server/petstore/kotlin-springboot-source-swagger1/src/main/kotlin/org/openapitools/api/StoreApiController.kt +++ b/samples/server/petstore/kotlin-springboot-source-swagger1/src/main/kotlin/org/openapitools/api/StoreApiController.kt @@ -2,6 +2,8 @@ package org.openapitools.api import org.openapitools.model.Order import io.swagger.annotations.Api +import io.swagger.annotations.ApiImplicitParam +import io.swagger.annotations.ApiImplicitParams import io.swagger.annotations.ApiOperation import io.swagger.annotations.ApiParam import io.swagger.annotations.ApiResponse diff --git a/samples/server/petstore/kotlin-springboot-source-swagger1/src/main/kotlin/org/openapitools/api/UserApiController.kt b/samples/server/petstore/kotlin-springboot-source-swagger1/src/main/kotlin/org/openapitools/api/UserApiController.kt index 14338953a646..f361f71587df 100644 --- a/samples/server/petstore/kotlin-springboot-source-swagger1/src/main/kotlin/org/openapitools/api/UserApiController.kt +++ b/samples/server/petstore/kotlin-springboot-source-swagger1/src/main/kotlin/org/openapitools/api/UserApiController.kt @@ -2,6 +2,8 @@ package org.openapitools.api import org.openapitools.model.User import io.swagger.annotations.Api +import io.swagger.annotations.ApiImplicitParam +import io.swagger.annotations.ApiImplicitParams import io.swagger.annotations.ApiOperation import io.swagger.annotations.ApiParam import io.swagger.annotations.ApiResponse diff --git a/samples/server/petstore/kotlin-springboot-source-swagger2/src/main/kotlin/org/openapitools/api/PetApiController.kt b/samples/server/petstore/kotlin-springboot-source-swagger2/src/main/kotlin/org/openapitools/api/PetApiController.kt index e18012463efb..98c84939c6dd 100644 --- a/samples/server/petstore/kotlin-springboot-source-swagger2/src/main/kotlin/org/openapitools/api/PetApiController.kt +++ b/samples/server/petstore/kotlin-springboot-source-swagger2/src/main/kotlin/org/openapitools/api/PetApiController.kt @@ -62,16 +62,18 @@ class PetApiController(@Autowired(required = true) val service: PetApiService) { ApiResponse(responseCode = "400", description = "Invalid pet value") ], security = [ SecurityRequirement(name = "petstore_auth", scopes = [ "write:pets", "read:pets" ]) ] ) + @Parameters(value = [ + Parameter(name = "api_key", description = "", `in` = ParameterIn.HEADER) + ]) @RequestMapping( method = [RequestMethod.DELETE], // "/pet/{petId}" value = [PATH_DELETE_PET] ) fun deletePet( - @Parameter(description = "Pet id to delete", required = true) @PathVariable("petId") petId: kotlin.Long, - @Parameter(description = "", `in` = ParameterIn.HEADER) @RequestHeader(value = "api_key", required = false) apiKey: kotlin.String? + @Parameter(description = "Pet id to delete", required = true) @PathVariable("petId") petId: kotlin.Long ): ResponseEntity { - return ResponseEntity(service.deletePet(petId, apiKey), HttpStatus.valueOf(400)) + return ResponseEntity(service.deletePet(petId), HttpStatus.valueOf(400)) } @Operation( diff --git a/samples/server/petstore/kotlin-springboot-source-swagger2/src/main/kotlin/org/openapitools/api/PetApiService.kt b/samples/server/petstore/kotlin-springboot-source-swagger2/src/main/kotlin/org/openapitools/api/PetApiService.kt index 566196d1e86d..2fe7b38c0682 100644 --- a/samples/server/petstore/kotlin-springboot-source-swagger2/src/main/kotlin/org/openapitools/api/PetApiService.kt +++ b/samples/server/petstore/kotlin-springboot-source-swagger2/src/main/kotlin/org/openapitools/api/PetApiService.kt @@ -18,11 +18,10 @@ interface PetApiService { * DELETE /pet/{petId} : Deletes a pet * * @param petId Pet id to delete (required) - * @param apiKey (optional) * @return Invalid pet value (status code 400) * @see PetApi#deletePet */ - fun deletePet(petId: kotlin.Long, apiKey: kotlin.String?): Unit + fun deletePet(petId: kotlin.Long): Unit /** * GET /pet/findByStatus : Finds Pets by status diff --git a/samples/server/petstore/kotlin-springboot-source-swagger2/src/main/kotlin/org/openapitools/api/PetApiServiceImpl.kt b/samples/server/petstore/kotlin-springboot-source-swagger2/src/main/kotlin/org/openapitools/api/PetApiServiceImpl.kt index a48482be32bd..95b0546a3d9e 100644 --- a/samples/server/petstore/kotlin-springboot-source-swagger2/src/main/kotlin/org/openapitools/api/PetApiServiceImpl.kt +++ b/samples/server/petstore/kotlin-springboot-source-swagger2/src/main/kotlin/org/openapitools/api/PetApiServiceImpl.kt @@ -10,7 +10,7 @@ class PetApiServiceImpl : PetApiService { TODO("Implement me") } - override fun deletePet(petId: kotlin.Long, apiKey: kotlin.String?): Unit { + override fun deletePet(petId: kotlin.Long): Unit { TODO("Implement me") } From 4f2972eb84e94fdd01f35dd06393912b3dc87e73 Mon Sep 17 00:00:00 2001 From: feczkob Date: Wed, 1 Apr 2026 15:42:41 +0200 Subject: [PATCH 6/6] Run export docs --- docs/generators/kotlin-misk.md | 1 + docs/generators/kotlin-server.md | 1 + docs/generators/kotlin-spring.md | 1 + docs/generators/kotlin-vertx.md | 1 + docs/generators/kotlin-wiremock.md | 1 + docs/generators/kotlin.md | 1 + docs/generators/ktorm-schema.md | 1 + 7 files changed, 7 insertions(+) diff --git a/docs/generators/kotlin-misk.md b/docs/generators/kotlin-misk.md index c02e0ca2abe9..b0aa29064a10 100644 --- a/docs/generators/kotlin-misk.md +++ b/docs/generators/kotlin-misk.md @@ -32,6 +32,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |enumPropertyNaming|Naming convention for enum properties: 'camelCase', 'PascalCase', 'snake_case', 'UPPERCASE', and 'original'| |original| |generateStubImplClasses|Generate Stub Impl Classes| |false| |groupId|Generated artifact package's organization (i.e. maven groupId).| |org.openapitools| +|implicitHeaders|Skip header parameters in the generated API methods.| |false| |modelMutable|Create mutable models| |false| |moduleClassName|Name of the generated module class| |OpenApiModule| |packageName|Generated artifact package name.| |org.openapitools| diff --git a/docs/generators/kotlin-server.md b/docs/generators/kotlin-server.md index 7fa06c87bb25..e53b6934d2a6 100644 --- a/docs/generators/kotlin-server.md +++ b/docs/generators/kotlin-server.md @@ -32,6 +32,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |featureResources|Generates routes in a typed way, for both: constructing URLs and reading the parameters.| |true| |fixJacksonJsonTypeInfoInheritance|When true (default), ensures Jackson polymorphism works correctly by: (1) always setting visible=true on @JsonTypeInfo, and (2) adding the discriminator property to child models with appropriate default values. When false, visible is only set to true if all children already define the discriminator property.| |true| |groupId|Generated artifact package's organization (i.e. maven groupId).| |org.openapitools| +|implicitHeaders|Skip header parameters in the generated API methods.| |false| |interfaceOnly|Whether to generate only API interface stubs without the server files. This option is currently supported only when using jaxrs-spec library.| |false| |library|library template (sub-template)|
**ktor**
ktor framework
**ktor2**
ktor (2.x) framework
**jaxrs-spec**
JAX-RS spec only
**javalin5**
Javalin 5
**javalin6**
Javalin 6
|ktor| |modelMutable|Create mutable models| |false| diff --git a/docs/generators/kotlin-spring.md b/docs/generators/kotlin-spring.md index 6c43046fbfb9..580d834f52c0 100644 --- a/docs/generators/kotlin-spring.md +++ b/docs/generators/kotlin-spring.md @@ -36,6 +36,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |exceptionHandler|generate default global exception handlers (not compatible with reactive. enabling reactive will disable exceptionHandler )| |true| |gradleBuildFile|generate a gradle build file using the Kotlin DSL| |true| |groupId|Generated artifact package's organization (i.e. maven groupId).| |org.openapitools| +|implicitHeaders|Skip header parameters in the generated API methods.| |false| |includeHttpRequestContext|Whether to include HttpServletRequest (blocking) or ServerWebExchange (reactive) as additional parameter in generated methods.| |false| |interfaceOnly|Whether to generate only API interface stubs without the server files.| |false| |library|library template (sub-template)|
**spring-boot**
Spring-boot Server application.
**spring-cloud**
Spring-Cloud-Feign client with Spring-Boot auto-configured settings.
**spring-declarative-http-interface**
Spring Declarative Interface client
|spring-boot| diff --git a/docs/generators/kotlin-vertx.md b/docs/generators/kotlin-vertx.md index 041b7a74087e..279e7330f4e4 100644 --- a/docs/generators/kotlin-vertx.md +++ b/docs/generators/kotlin-vertx.md @@ -24,6 +24,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |artifactVersion|Generated artifact's package version.| |1.0.0| |enumPropertyNaming|Naming convention for enum properties: 'camelCase', 'PascalCase', 'snake_case', 'UPPERCASE', and 'original'| |original| |groupId|Generated artifact package's organization (i.e. maven groupId).| |org.openapitools| +|implicitHeaders|Skip header parameters in the generated API methods.| |false| |modelMutable|Create mutable models| |false| |packageName|Generated artifact package name.| |org.openapitools| |parcelizeModels|toggle "@Parcelize" for generated models| |null| diff --git a/docs/generators/kotlin-wiremock.md b/docs/generators/kotlin-wiremock.md index c836ebc7f23b..8bd595b2e4e5 100644 --- a/docs/generators/kotlin-wiremock.md +++ b/docs/generators/kotlin-wiremock.md @@ -24,6 +24,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |artifactVersion|Generated artifact's package version.| |1.0.0| |enumPropertyNaming|Naming convention for enum properties: 'camelCase', 'PascalCase', 'snake_case', 'UPPERCASE', and 'original'| |original| |groupId|Generated artifact package's organization (i.e. maven groupId).| |org.openapitools| +|implicitHeaders|Skip header parameters in the generated API methods.| |false| |modelMutable|Create mutable models| |false| |packageName|Generated artifact package name.| |org.openapitools| |parcelizeModels|toggle "@Parcelize" for generated models| |null| diff --git a/docs/generators/kotlin.md b/docs/generators/kotlin.md index 8d0552018d80..7e79ba98bfc8 100644 --- a/docs/generators/kotlin.md +++ b/docs/generators/kotlin.md @@ -32,6 +32,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |generateRoomModels|Generate Android Room database models in addition to API models (JVM Volley library only)| |false| |groupId|Generated artifact package's organization (i.e. maven groupId).| |org.openapitools| |idea|Add IntelliJ Idea plugin and mark Kotlin main and test folders as source folders.| |false| +|implicitHeaders|Skip header parameters in the generated API methods.| |false| |library|Library template (sub-template) to use|
**jvm-ktor**
Platform: Java Virtual Machine. HTTP client: Ktor 1.6.7. JSON processing: Gson, Jackson (default).
**jvm-okhttp4**
[DEFAULT] Platform: Java Virtual Machine. HTTP client: OkHttp 4.2.0 (Android 5.0+ and Java 8+). JSON processing: Moshi 1.8.0.
**jvm-spring-webclient**
Platform: Java Virtual Machine. HTTP: Spring 5 (or 6 with useSpringBoot3 enabled) WebClient. JSON processing: Jackson.
**jvm-spring-restclient**
Platform: Java Virtual Machine. HTTP: Spring 6 RestClient. JSON processing: Jackson.
**jvm-retrofit2**
Platform: Java Virtual Machine. HTTP client: Retrofit 2.6.2.
**multiplatform**
Platform: Kotlin multiplatform. HTTP client: Ktor 1.6.7. JSON processing: Kotlinx Serialization: 1.2.1.
**jvm-volley**
Platform: JVM for Android. HTTP client: Volley 1.2.1. JSON processing: gson 2.8.9 (Deprecated)
**jvm-vertx**
Platform: Java Virtual Machine. HTTP client: Vert.x Web Client. JSON processing: Moshi, Gson or Jackson.
|jvm-okhttp4| |mapFileBinaryToByteArray|Map File and Binary to ByteArray (default: false)| |false| |modelMutable|Create mutable models| |false| diff --git a/docs/generators/ktorm-schema.md b/docs/generators/ktorm-schema.md index 8bbad926bc99..179d7c7647c0 100644 --- a/docs/generators/ktorm-schema.md +++ b/docs/generators/ktorm-schema.md @@ -26,6 +26,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |enumPropertyNaming|Naming convention for enum properties: 'camelCase', 'PascalCase', 'snake_case', 'UPPERCASE', and 'original'| |original| |groupId|Generated artifact package's organization (i.e. maven groupId).| |org.openapitools| |identifierNamingConvention|Naming convention of Ktorm identifiers(table names and column names). This is not related to database name which is defined by defaultDatabaseName option|
**original**
Do not transform original names
**snake_case**
Use snake_case names
|original| +|implicitHeaders|Skip header parameters in the generated API methods.| |false| |importModelPackageName|Package name of the imported models| |org.openapitools.database.models| |modelMutable|Create mutable models| |false| |packageName|Generated artifact package name.| |org.openapitools.database|