Skip to content

Commit 76540e5

Browse files
Improve Kotlin Misk OpenApi Generator (#21165)
* first pass * fixing types * fixing action * updating samples * updating files * adding guido * fixing misk * removing old files * cleaning generated files * cleaning generated files * adding back in license * first pass * second pass * third pass * typo * fixup * fixup 2 * fixup 3 * fixup 4 * fixup 5 * fixup 6 * fixing api override * fixing docs * fixing docs json * fix misk version * add action prefix * fixup * fixup 2 * fixup 3 * fixup 4 * fixup 5
1 parent 56eb8f7 commit 76540e5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+2033
-325
lines changed

.github/workflows/samples-kotlin-server.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ jobs:
4848
- samples/server/others/kotlin-server/jaxrs-spec-array-response
4949
- samples/server/petstore/kotlin-spring-cloud
5050
- samples/server/petstore/kotlin-misk
51+
- samples/server/petstore/kotlin-misk-config
5152
# comment out due to gradle build failure
5253
#- samples/server/petstore/kotlin-spring-default
5354
# no build.gradle file

bin/configs/kotlin-misk-config.yaml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
generatorName: kotlin-misk
2+
outputDir: samples/server/petstore/kotlin-misk-config
3+
inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore.yaml
4+
templateDir: modules/openapi-generator/src/main/resources/kotlin-misk
5+
validateSpec: false
6+
additionalProperties:
7+
hideGenerationTimestamp: "true"
8+
moduleClassName: "PetStoreModule"
9+
generateStubImplClasses: true
10+
addModelMoshiJsonAnnotation: true
11+
actionPathPrefix : "samplePrefix"

bin/configs/kotlin-misk.yaml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ generatorName: kotlin-misk
22
outputDir: samples/server/petstore/kotlin-misk
33
inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore.yaml
44
templateDir: modules/openapi-generator/src/main/resources/kotlin-misk
5-
validateSpec: false
65
additionalProperties:
76
hideGenerationTimestamp: "true"
87
moduleClassName: "PetStoreModule"

docs/generators/kotlin-misk.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,14 @@ These options may be applied as additional-properties (cli) or configOptions (pl
1818

1919
| Option | Description | Values | Default |
2020
| ------ | ----------- | ------ | ------- |
21+
|actionPathPrefix|Prefix for action path| ||
22+
|addModelMoshiJsonAnnotation|Add a Moshi JSON adapter annotation to all model classes| |true|
2123
|additionalModelTypeAnnotations|Additional annotations for model type(class level annotations). List separated by semicolon(;) or new line (Linux or Windows)| |null|
2224
|apiSuffix|suffix for api classes| |Api|
2325
|artifactId|Generated artifact id (name of jar).| |null|
2426
|artifactVersion|Generated artifact's package version.| |1.0.0|
2527
|enumPropertyNaming|Naming convention for enum properties: 'camelCase', 'PascalCase', 'snake_case', 'UPPERCASE', and 'original'| |original|
28+
|generateStubImplClasses|Generate Stub Impl Classes| |false|
2629
|groupId|Generated artifact package's organization (i.e. maven groupId).| |org.openapitools|
2730
|modelMutable|Create mutable models| |false|
2831
|moduleClassName|Name of the generated module class| |OpenApiModule|
@@ -273,7 +276,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
273276
### Wire Format Feature
274277
| Name | Supported | Defined By |
275278
| ---- | --------- | ---------- |
276-
|JSON||OAS2,OAS3
279+
|JSON||OAS2,OAS3
277280
|XML|✗|OAS2,OAS3
278281
|PROTOBUF|✓|ToolingExtension
279282
|Custom|✗|OAS2,OAS3

modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinMiskServerCodegen.java

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,17 +47,28 @@
4747

4848
public class KotlinMiskServerCodegen extends AbstractKotlinCodegen implements BeanValidationFeatures {
4949

50+
private final Logger LOGGER = LoggerFactory.getLogger(KotlinMiskServerCodegen.class);
51+
5052
public static final String MODULE_CLASS_NAME = "moduleClassName";
53+
public static final String ACTION_PATH_PREFIX = "actionPathPrefix";
5154

52-
private final Logger LOGGER = LoggerFactory.getLogger(KotlinMiskServerCodegen.class);
5355
private static final String ROOT_PACKAGE = "rootPackage";
56+
public static final String GENERATE_STUB_IMPL_CLASSES = "generateStubImplClasses";
57+
public static final String ADD_MODEL_MOSHI_JSON_ANNOTATION = "addModelMoshiJsonAnnotation";
5458

5559
private boolean useBeanValidation = true;
5660

61+
@Setter
62+
private boolean generateStubImplClasses = false;
63+
64+
@Setter
65+
private boolean addModelMoshiJsonAnnotation = true;
66+
5767
protected String rootPackage = "org.openapitools.server.api";
5868
protected String apiVersion = "1.0.0-SNAPSHOT";
5969

6070
@Setter protected String moduleClassName = "OpenApiModule";
71+
@Setter protected String actionPathPrefix = "";
6172

6273
@Override
6374
public CodegenType getTag() {
@@ -78,10 +89,12 @@ public KotlinMiskServerCodegen() {
7889
super();
7990

8091
addSwitch(USE_BEANVALIDATION, "Use BeanValidation API annotations to validate data types", useBeanValidation);
92+
addSwitch(GENERATE_STUB_IMPL_CLASSES, "Generate Stub Impl Classes", generateStubImplClasses);
93+
addSwitch(ADD_MODEL_MOSHI_JSON_ANNOTATION, "Add a Moshi JSON adapter annotation to all model classes", addModelMoshiJsonAnnotation);
8194

8295
modifyFeatureSet(features -> features
8396
.includeDocumentationFeatures(DocumentationFeature.Readme)
84-
.wireFormatFeatures(EnumSet.of(WireFormatFeature.PROTOBUF))
97+
.wireFormatFeatures(EnumSet.of(WireFormatFeature.JSON, WireFormatFeature.PROTOBUF))
8598
.securityFeatures(EnumSet.noneOf(
8699
SecurityFeature.class
87100
))
@@ -108,6 +121,7 @@ public KotlinMiskServerCodegen() {
108121
outputFolder = "generated-code" + File.separator + "kotlin-misk";
109122

110123
addOption(MODULE_CLASS_NAME, "Name of the generated module class", moduleClassName);
124+
addOption(ACTION_PATH_PREFIX, "Prefix for action path", actionPathPrefix);
111125

112126
apiTestTemplateFiles.clear();
113127
apiTestTemplateFiles.put("api_test.mustache", ".kt");
@@ -122,8 +136,12 @@ public KotlinMiskServerCodegen() {
122136

123137
apiTemplateFiles.clear();
124138
apiTemplateFiles.put("apiAction.mustache", "Action.kt");
125-
apiTemplateFiles.put("apiImpl.mustache", "Impl.kt");
126-
apiTemplateFiles.put("apiInterface.mustache", ".kt");
139+
140+
if (generateStubImplClasses) {
141+
apiTemplateFiles.put("apiImpl.mustache", "Impl.kt");
142+
apiTemplateFiles.put("apiInterface.mustache", ".kt");
143+
}
144+
127145
modelTemplateFiles.put("model.mustache", ".kt");
128146

129147
apiPackage = rootPackage + ".api";
@@ -148,13 +166,27 @@ public void processOpts() {
148166
if (additionalProperties.containsKey(MODULE_CLASS_NAME)) {
149167
setModuleClassName((String) additionalProperties.get(MODULE_CLASS_NAME));
150168
}
151-
additionalProperties.put(MODULE_CLASS_NAME, moduleClassName);
169+
writePropertyBack(MODULE_CLASS_NAME, moduleClassName);
170+
171+
if (additionalProperties.containsKey(ACTION_PATH_PREFIX)) {
172+
setActionPathPrefix((String) additionalProperties.get(ACTION_PATH_PREFIX));
173+
}
174+
writePropertyBack(ACTION_PATH_PREFIX, actionPathPrefix);
152175

153176
if (additionalProperties.containsKey(USE_BEANVALIDATION)) {
154177
this.setUseBeanValidation(convertPropertyToBoolean(USE_BEANVALIDATION));
155178
}
156179
writePropertyBack(USE_BEANVALIDATION, useBeanValidation);
157180

181+
if (additionalProperties.containsKey(GENERATE_STUB_IMPL_CLASSES)) {
182+
setGenerateStubImplClasses(convertPropertyToBoolean(GENERATE_STUB_IMPL_CLASSES));
183+
}
184+
writePropertyBack(GENERATE_STUB_IMPL_CLASSES, generateStubImplClasses);
185+
186+
if (additionalProperties.containsKey(ADD_MODEL_MOSHI_JSON_ANNOTATION)) {
187+
setAddModelMoshiJsonAnnotation(convertPropertyToBoolean(ADD_MODEL_MOSHI_JSON_ANNOTATION));
188+
}
189+
writePropertyBack(ADD_MODEL_MOSHI_JSON_ANNOTATION, addModelMoshiJsonAnnotation);
158190
applyJakartaPackage();
159191

160192
String apiModuleFolder = (sourceFolder + File.separator + apiPackage).replace(".", File.separator);
@@ -211,6 +243,7 @@ private static Map<String, String> getMappings() {
211243
result.put("application/grpc", "MediaTypes.APPLICATION_GRPC");
212244
result.put("application/javascript", "MediaTypes.APPLICATION_JAVASCRIPT");
213245
result.put("application/json", "MediaTypes.APPLICATION_JSON");
246+
result.put("application/jwt", "MediaTypes.APPLICATION_JWT");
214247
result.put("application/octetstream", "MediaTypes.APPLICATION_OCTETSTREAM");
215248
result.put("application/pdf", "MediaTypes.APPLICATION_OCTETSTREAM");
216249
result.put("application/x-protobuf", "MediaTypes.APPLICATION_PROTOBUF");
@@ -219,10 +252,11 @@ private static Map<String, String> getMappings() {
219252
result.put("application/zip", "MediaTypes.APPLICATION_ZIP");
220253

221254
result.put("image/gif", "MediaTypes.IMAGE_GIF");
255+
result.put("image/x-icon", "MediaTypes.IMAGE_ICO");
222256
result.put("image/jpeg", "MediaTypes.IMAGE_JPEG");
223257
result.put("image/png", "MediaTypes.IMAGE_PNG");
224258
result.put("image/svg+xml", "MediaTypes.IMAGE_SVG");
225-
result.put("image/x-icon", "MediaTypes.IMAGE_ICO");
259+
result.put("image/tiff", "MediaTypes.IMAGE_TIFF");
226260

227261
result.put("multipart/form-data", "MediaTypes.FORM_DATA");
228262

modules/openapi-generator/src/main/resources/kotlin-misk/apiAction.mustache

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,22 +32,22 @@ import misk.web.mediatype.MediaTypes
3232
{{#imports}}import {{import}}
3333
{{/imports}}
3434

35-
{{#operations}}
3635
/**
37-
* Generated file, please change {{classname}}Impl.
38-
*/
36+
* @TODO("Fill out implementation")
37+
*/
38+
{{#operations}}
3939
@Singleton
4040
class {{classname}}Action @Inject constructor(
41-
private val {{#lambda.camelcase}}{{classname}}{{/lambda.camelcase}}: {{classname}}
42-
) : WebAction, {{classname}} {
41+
) : WebAction {
4342
{{#operation}}
4443

45-
@{{httpMethod}}("{{path}}")
44+
@{{httpMethod}}("{{actionPathPrefix}}{{path}}")
4645
@Description("{{{summary}}}"){{#hasConsumes}}
4746
@RequestContentType({{#consumes}}{{{mediaType}}}{{^-last}}, {{/-last}}{{/consumes}}){{/hasConsumes}}{{#hasProduces}}
4847
@ResponseContentType({{#produces}}{{{mediaType}}}{{^-last}}, {{/-last}}{{/produces}}){{/hasProduces}}
4948
@LogRequestResponse(bodySampling = 1.0, errorBodySampling = 1.0)
50-
override fun {{operationId}}({{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>cookieParams}}{{>bodyParams}}{{>formParams}}{{^-last}}, {{/-last}}{{/allParams}}){{#returnType}}: {{{returnType}}}{{/returnType}} {
49+
fun {{operationId}}({{#allParams}}
50+
{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>cookieParams}}{{>bodyParams}}{{>formParams}}{{^-last}}, {{/-last}}{{/allParams}}){{#returnType}}: {{{returnType}}}{{/returnType}} {
5151
TODO()
5252
}
5353
{{/operation}}

modules/openapi-generator/src/main/resources/kotlin-misk/apiImpl.mustache

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ class {{classname}}Impl @Inject constructor(
3030
): {{classname}} {
3131
{{#operation}}
3232

33-
override fun {{operationId}}({{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>cookieParams}}{{>bodyParams}}{{>formParams}}{{^-last}}, {{/-last}}{{/allParams}}){{#returnType}}: {{{returnType}}}{{/returnType}} {
33+
override fun {{operationId}}({{#allParams}}
34+
{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>cookieParams}}{{>bodyParams}}{{>formParams}}{{^-last}}, {{/-last}}{{/allParams}}){{#returnType}}: {{{returnType}}}{{/returnType}} {
3435
TODO()
3536
}
3637
{{/operation}}

modules/openapi-generator/src/main/resources/kotlin-misk/apiInterface.mustache

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ import misk.web.RequestHeader
2323
interface {{classname}} {
2424
{{#operation}}
2525

26-
fun {{operationId}}({{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>cookieParams}}{{>bodyParams}}{{>formParams}}{{^-last}}, {{/-last}}{{/allParams}}){{#returnType}}: {{{returnType}}}{{/returnType}}
26+
fun {{operationId}}({{#allParams}}
27+
{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>cookieParams}}{{>bodyParams}}{{>formParams}}{{^-last}}, {{/-last}}{{/allParams}}){{#returnType}}: {{{returnType}}}{{/returnType}} {
2728
{{/operation}}
2829
}
2930
{{/operations}}

modules/openapi-generator/src/main/resources/kotlin-misk/api_test.mustache

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import misk.web.RequestHeader
1616
@MiskTest(startService = true)
1717
internal class {{classname}}Test {
1818
19-
@Inject private lateinit var {{#lambda.camelcase}}{{classname}}{{/lambda.camelcase}}: {{classname}}
19+
@Inject private lateinit var {{#lambda.camelcase}}{{classname}}{{/lambda.camelcase}}: {{classname}}Action
2020

2121
{{#operations}}
2222
{{#operation}}

modules/openapi-generator/src/main/resources/kotlin-misk/build.gradle.kts.mustache

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ version = "{{artifactVersion}}"
99

1010
dependencies {
1111
implementation("jakarta.validation:jakarta.validation-api:3.1.1")
12-
implementation("com.squareup.misk:misk:2025.04.02.195630-a61d550")
13-
//implementation("com.squareup.wire:wire-runtime:5.2.1")
12+
implementation("com.squareup.misk:misk:2025.04.27.230742-6035cb3")
13+
implementation("com.squareup.moshi:moshi:1.15.2")
1414
1515
testImplementation("com.squareup.misk:misk-testing:2025.02.11.123913-8a41324")
1616
testImplementation("org.junit.jupiter:junit-jupiter:5.9.2")

modules/openapi-generator/src/main/resources/kotlin-misk/model.mustache

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package {{modelPackage}}
33
{{#imports}}
44
import {{import}}
55
{{/imports}}
6-
76
{{#models}}
87
{{#model}}
98
{{#isEnum}}
@@ -16,6 +15,9 @@ enum class {{classname}} {
1615
}
1716
{{/isEnum}}
1817
{{^isEnum}}
18+
{{#addModelMoshiJsonAnnotation}}import com.squareup.moshi.JsonClass
19+
20+
@JsonClass(generateAdapter = true){{/addModelMoshiJsonAnnotation}}
1921
data class {{classname}}(
2022
{{#vars}}
2123
{{#description}}

modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/misk/KotlinMiskServerCodegenOptionsTest.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,5 +38,8 @@ protected void verifyOptions() {
3838
verify(codegen).setAdditionalModelTypeAnnotations(List.of(KotlinMiskServerCodegenOptionsProvider.ADDITIONAL_MODEL_TYPE_ANNOTATIONS_VALUE));
3939
verify(codegen).setUseBeanValidation(Boolean.valueOf(KotlinMiskServerCodegenOptionsProvider.USE_BEAN_VALIDATION));
4040
verify(codegen).setModuleClassName(KotlinMiskServerCodegenOptionsProvider.MODULE_CLASS_NAME);
41+
verify(codegen).setActionPathPrefix(KotlinMiskServerCodegenOptionsProvider.ACTION_PATH_PREFIX);
42+
verify(codegen).setGenerateStubImplClasses(Boolean.valueOf(KotlinMiskServerCodegenOptionsProvider.GENERATE_STUB_IMPL_CLASSES));
43+
verify(codegen).setAddModelMoshiJsonAnnotation(Boolean.valueOf(KotlinMiskServerCodegenOptionsProvider.ADD_MODEL_MOSHI_JSON_ANNOTATION));
4144
}
4245
}

modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/misk/KotlinMiskServerCodegenTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ public void testDefaultConfiguration() {
3333
Assert.assertEquals(codegen.apiPackage(), "org.openapitools.server.api.api");
3434
Assert.assertEquals(codegen.modelPackage(), "org.openapitools.server.api.model");
3535

36-
// Test PROTOBUF wire format
36+
// Test wire formats
37+
Assert.assertTrue(codegen.getFeatureSet().getWireFormatFeatures().contains(WireFormatFeature.JSON));
3738
Assert.assertTrue(codegen.getFeatureSet().getWireFormatFeatures().contains(WireFormatFeature.PROTOBUF));
3839
}
3940

modules/openapi-generator/src/test/java/org/openapitools/codegen/options/KotlinMiskServerCodegenOptionsProvider.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,10 @@ public class KotlinMiskServerCodegenOptionsProvider implements OptionsProvider {
2323
public static final String API_SUFFIX_VALUE = "Api";
2424
public static final String ADDITIONAL_MODEL_TYPE_ANNOTATIONS_VALUE = "";
2525
public static final String USE_BEAN_VALIDATION = "false";
26+
public static final String GENERATE_STUB_IMPL_CLASSES = "false";
27+
public static final String ADD_MODEL_MOSHI_JSON_ANNOTATION = "true";
2628
public static final String MODULE_CLASS_NAME = "OpenApiModule";
29+
public static final String ACTION_PATH_PREFIX = "samplePrefix";
2730

2831
@Override
2932
public String getLanguage() {
@@ -51,6 +54,9 @@ public Map<String, String> createOptions() {
5154
ADDITIONAL_MODEL_TYPE_ANNOTATIONS_VALUE)
5255
.put(KotlinMiskServerCodegen.MODULE_CLASS_NAME, MODULE_CLASS_NAME)
5356
.put(BeanValidationFeatures.USE_BEANVALIDATION, USE_BEAN_VALIDATION)
57+
.put(KotlinMiskServerCodegen.ACTION_PATH_PREFIX, ACTION_PATH_PREFIX)
58+
.put(KotlinMiskServerCodegen.ADD_MODEL_MOSHI_JSON_ANNOTATION, ADD_MODEL_MOSHI_JSON_ANNOTATION)
59+
.put(KotlinMiskServerCodegen.GENERATE_STUB_IMPL_CLASSES, GENERATE_STUB_IMPL_CLASSES)
5460
.build();
5561
}
5662

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# OpenAPI Generator Ignore
2+
# Generated by openapi-generator https://github.com/openapitools/openapi-generator
3+
4+
# Use this file to prevent files from being overwritten by the generator.
5+
# The patterns follow closely to .gitignore or .dockerignore.
6+
7+
# As an example, the C# client generator defines ApiClient.cs.
8+
# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line:
9+
#ApiClient.cs
10+
11+
# You can match any string of characters against a directory, file or extension with a single asterisk (*):
12+
#foo/*/qux
13+
# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux
14+
15+
# You can recursively match patterns against a directory, file or extension with a double asterisk (**):
16+
#foo/**/qux
17+
# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux
18+
19+
# You can also negate patterns with an exclamation (!).
20+
# For example, you can ignore all files in a docs folder with the file extension .md:
21+
#docs/*.md
22+
# Then explicitly reverse the ignore rule for a single file:
23+
#!docs/README.md
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
README.md
2+
build.gradle.kts
3+
docs/ApiResponse.md
4+
docs/Category.md
5+
docs/Order.md
6+
docs/Pet.md
7+
docs/PetApi.md
8+
docs/StoreApi.md
9+
docs/Tag.md
10+
docs/User.md
11+
docs/UserApi.md
12+
settings.gradle.kts
13+
src/main/kotlin/org/openapitools/server/api/api/PetApiAction.kt
14+
src/main/kotlin/org/openapitools/server/api/api/PetStoreModule.kt
15+
src/main/kotlin/org/openapitools/server/api/api/StoreApiAction.kt
16+
src/main/kotlin/org/openapitools/server/api/api/UserApiAction.kt
17+
src/main/kotlin/org/openapitools/server/api/model/Category.kt
18+
src/main/kotlin/org/openapitools/server/api/model/ModelApiResponse.kt
19+
src/main/kotlin/org/openapitools/server/api/model/Order.kt
20+
src/main/kotlin/org/openapitools/server/api/model/Pet.kt
21+
src/main/kotlin/org/openapitools/server/api/model/Tag.kt
22+
src/main/kotlin/org/openapitools/server/api/model/User.kt
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
7.14.0-SNAPSHOT

0 commit comments

Comments
 (0)