diff --git a/docs/generators/kotlin-spring.md b/docs/generators/kotlin-spring.md
index 89ec5f81e793..cab59d222303 100644
--- a/docs/generators/kotlin-spring.md
+++ b/docs/generators/kotlin-spring.md
@@ -25,4 +25,5 @@ sidebar_label: kotlin-spring
|serviceInterface|generate service interfaces to go alongside controllers. In most cases this option would be used to update an existing project, so not to override implementations. Useful to help facilitate the generation gap pattern| |false|
|serviceImplementation|generate stub service implementations that extends service interfaces. If this is set to true service interfaces will also be generated| |false|
|useBeanValidation|Use BeanValidation API annotations to validate data types| |true|
+|reactive|wrap responses in Mono/Flux Reactor types (spring-boot only)| |false|
|library|library template (sub-template) to use|
- **spring-boot**
- Spring-boot Server application.
|spring-boot|
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 8536e099ca4a..f106289f4d5e 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
@@ -61,6 +61,8 @@ public class KotlinSpringServerCodegen extends AbstractKotlinCodegen
public static final String SERVICE_INTERFACE = "serviceInterface";
public static final String SERVICE_IMPLEMENTATION = "serviceImplementation";
+ public static final String REACTIVE = "reactive";
+
private String basePackage;
private String invokerPackage;
private String serverPort = "8080";
@@ -72,6 +74,7 @@ public class KotlinSpringServerCodegen extends AbstractKotlinCodegen
private boolean swaggerAnnotations = false;
private boolean serviceInterface = false;
private boolean serviceImplementation = false;
+ private boolean reactive = false;
public KotlinSpringServerCodegen() {
super();
@@ -145,6 +148,7 @@ public KotlinSpringServerCodegen() {
addSwitch(SERVICE_IMPLEMENTATION, "generate stub service implementations that extends service " +
"interfaces. If this is set to true service interfaces will also be generated", serviceImplementation);
addSwitch(USE_BEANVALIDATION, "Use BeanValidation API annotations to validate data types", useBeanValidation);
+ addSwitch(REACTIVE, "wrap responses in Mono/Flux Reactor types (spring-boot only)", reactive);
supportedLibraries.put(SPRING_BOOT, "Spring-boot Server application.");
setLibrary(SPRING_BOOT);
@@ -236,6 +240,14 @@ public void setUseBeanValidation(boolean useBeanValidation) {
this.useBeanValidation = useBeanValidation;
}
+ public boolean isReactive() {
+ return reactive;
+ }
+
+ public void setReactive(boolean reactive) {
+ this.reactive = reactive;
+ }
+
@Override
public CodegenType getTag() {
return CodegenType.SERVER;
@@ -328,6 +340,11 @@ public void processOpts() {
}
writePropertyBack(USE_BEANVALIDATION, useBeanValidation);
+ if (additionalProperties.containsKey(REACTIVE) && library.equals(SPRING_BOOT) && serviceInterface) {
+ this.setReactive(convertPropertyToBoolean(REACTIVE));
+ }
+ writePropertyBack(REACTIVE, reactive);
+
modelTemplateFiles.put("model.mustache", ".kt");
apiTemplateFiles.put("api.mustache", ".kt");
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
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 65f1f78b0659..65b34368825a 100644
--- a/modules/openapi-generator/src/main/resources/kotlin-spring/api.mustache
+++ b/modules/openapi-generator/src/main/resources/kotlin-spring/api.mustache
@@ -16,6 +16,11 @@ import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.RequestHeader
import org.springframework.web.bind.annotation.RequestMethod
import org.springframework.web.bind.annotation.RequestMapping
+{{#reactive}}
+import org.springframework.web.server.ServerWebExchange;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+{{/reactive}}
{{#useBeanValidation}}
import org.springframework.validation.annotation.Validated
{{/useBeanValidation}}
@@ -61,7 +66,7 @@ class {{classname}}Controller({{#serviceInterface}}@Autowired(required = true) v
produces = [{{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}}], {{/hasProduces}}{{#hasConsumes}}
consumes = [{{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}}],{{/hasConsumes}}{{/singleContentTypes}}
method = [RequestMethod.{{httpMethod}}])
- fun {{operationId}}({{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}}{{#hasMore}},{{/hasMore}}{{/allParams}}): ResponseEntity<{{>returnTypes}}> {
+ fun {{operationId}}({{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}}{{#hasMore}},{{/hasMore}}{{/allParams}}{{#reactive}}{{#allParams}},{{/allParams}} exchange: ServerWebExchange{{/reactive}}): {{^reactive}}ResponseEntity<{{/reactive}}{{>returnTypes}}{{^reactive}}>{{/reactive}} {
return {{>returnValue}}
}
{{/operation}}
diff --git a/modules/openapi-generator/src/main/resources/kotlin-spring/bodyParams.mustache b/modules/openapi-generator/src/main/resources/kotlin-spring/bodyParams.mustache
index c05599c7b027..87109e34fb67 100644
--- a/modules/openapi-generator/src/main/resources/kotlin-spring/bodyParams.mustache
+++ b/modules/openapi-generator/src/main/resources/kotlin-spring/bodyParams.mustache
@@ -1 +1 @@
-{{#isBodyParam}}{{#swaggerAnnotations}}@ApiParam(value = "{{{description}}}" {{#required}},required=true{{/required}} {{^isContainer}}{{#allowableValues}}, allowableValues="{{{allowableValues}}}"{{/allowableValues}}{{/isContainer}}{{#defaultValue}}, defaultValue="{{{defaultValue}}}"{{/defaultValue}}){{/swaggerAnnotations}} {{#useBeanValidation}}@Valid{{/useBeanValidation}} @RequestBody {{paramName}}: {{^reactive}}{{>optionalDataType}}{{/reactive}}{{#reactive}}{{^isListContainer}}Mono{{/isListContainer}}{{#isListContainer}}Flux{{/isListContainer}}<{{{baseType}}}>{{/reactive}}{{/isBodyParam}}
\ No newline at end of file
+{{#isBodyParam}}{{#swaggerAnnotations}}@ApiParam(value = "{{{description}}}" {{#required}},required=true{{/required}} {{^isContainer}}{{#allowableValues}}, allowableValues="{{{allowableValues}}}"{{/allowableValues}}{{/isContainer}}{{#defaultValue}}, defaultValue="{{{defaultValue}}}"{{/defaultValue}}){{/swaggerAnnotations}} {{#useBeanValidation}}@Valid{{/useBeanValidation}} @RequestBody {{paramName}}: {{>optionalDataType}}{{/isBodyParam}}
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/kotlin-spring/returnValue.mustache b/modules/openapi-generator/src/main/resources/kotlin-spring/returnValue.mustache
index 4973c83431d2..732aa03eb3f1 100644
--- a/modules/openapi-generator/src/main/resources/kotlin-spring/returnValue.mustache
+++ b/modules/openapi-generator/src/main/resources/kotlin-spring/returnValue.mustache
@@ -1 +1 @@
-{{#serviceInterface}}ResponseEntity(service.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}), HttpStatus.OK){{/serviceInterface}}{{^serviceInterface}}ResponseEntity(HttpStatus.NOT_IMPLEMENTED){{/serviceInterface}}
\ No newline at end of file
+{{^reactive}}{{#serviceInterface}}ResponseEntity(service.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}), HttpStatus.OK){{/serviceInterface}}{{^serviceInterface}}ResponseEntity(HttpStatus.NOT_IMPLEMENTED){{/serviceInterface}}{{/reactive}}{{#reactive}}service.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}{{#allParams}},{{/allParams}} exchange){{/reactive}}
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/kotlin-spring/service.mustache b/modules/openapi-generator/src/main/resources/kotlin-spring/service.mustache
index 12b073f7009f..b146df6a1361 100644
--- a/modules/openapi-generator/src/main/resources/kotlin-spring/service.mustache
+++ b/modules/openapi-generator/src/main/resources/kotlin-spring/service.mustache
@@ -2,12 +2,17 @@ package {{package}}
{{#imports}}import {{import}}
{{/imports}}
+{{#reactive}}
+import org.springframework.web.server.ServerWebExchange;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+{{/reactive}}
{{#operations}}
interface {{classname}}Service {
{{#operation}}
- fun {{operationId}}({{#allParams}}{{paramName}}: {{>optionalDataType}}{{#hasMore}}, {{/hasMore}}{{/allParams}}): {{>returnTypes}}
+ fun {{operationId}}({{#allParams}}{{paramName}}: {{>optionalDataType}}{{#hasMore}}, {{/hasMore}}{{/allParams}}{{#reactive}}{{#allParams}},{{/allParams}} exchange: ServerWebExchange{{/reactive}}): {{>returnTypes}}
{{/operation}}
}
{{/operations}}
diff --git a/modules/openapi-generator/src/main/resources/kotlin-spring/serviceImpl.mustache b/modules/openapi-generator/src/main/resources/kotlin-spring/serviceImpl.mustache
index 32e62866af21..0fcc60f44f4e 100644
--- a/modules/openapi-generator/src/main/resources/kotlin-spring/serviceImpl.mustache
+++ b/modules/openapi-generator/src/main/resources/kotlin-spring/serviceImpl.mustache
@@ -2,13 +2,18 @@ package {{package}}
{{#imports}}import {{import}}
{{/imports}}
+{{#reactive}}
+import org.springframework.web.server.ServerWebExchange;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+{{/reactive}}
import org.springframework.stereotype.Service
@Service
{{#operations}}
class {{classname}}ServiceImpl : {{classname}}Service {
{{#operation}}
- override fun {{operationId}}({{#allParams}}{{paramName}}: {{>optionalDataType}}{{#hasMore}}, {{/hasMore}}{{/allParams}}): {{>returnTypes}} {
+ override fun {{operationId}}({{#allParams}}{{paramName}}: {{>optionalDataType}}{{#hasMore}}, {{/hasMore}}{{/allParams}}{{#reactive}}{{#allParams}},{{/allParams}} exchange: ServerWebExchange{{/reactive}}): {{>returnTypes}} {
TODO("Implement me")
}
{{/operation}}
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 87847e16cf71..c830cd29b969 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
@@ -47,6 +47,7 @@ public void testSettersForConfigValues() throws Exception {
codegen.setServiceInterface(true);
codegen.setServiceImplementation(true);
codegen.setUseBeanValidation(false);
+ codegen.setReactive(false);
codegen.processOpts();
Assert.assertEquals(codegen.modelPackage(), "xx.yyyyyyyy.model");
@@ -69,6 +70,8 @@ public void testSettersForConfigValues() throws Exception {
Assert.assertEquals(codegen.additionalProperties().get(KotlinSpringServerCodegen.SERVICE_IMPLEMENTATION), true);
Assert.assertFalse(codegen.getUseBeanValidation());
Assert.assertEquals(codegen.additionalProperties().get(KotlinSpringServerCodegen.USE_BEANVALIDATION), false);
+ Assert.assertFalse(codegen.isReactive());
+ Assert.assertEquals(codegen.additionalProperties().get(KotlinSpringServerCodegen.REACTIVE), false);
}
@Test
@@ -84,6 +87,7 @@ public void testAdditionalPropertiesPutForConfigValues() throws Exception {
codegen.additionalProperties().put(KotlinSpringServerCodegen.SERVICE_INTERFACE, true);
codegen.additionalProperties().put(KotlinSpringServerCodegen.SERVICE_IMPLEMENTATION, true);
codegen.additionalProperties().put(KotlinSpringServerCodegen.USE_BEANVALIDATION, false);
+ codegen.additionalProperties().put(KotlinSpringServerCodegen.REACTIVE, false);
codegen.processOpts();
final OpenAPI openAPI = new OpenAPI();
@@ -112,6 +116,8 @@ public void testAdditionalPropertiesPutForConfigValues() throws Exception {
Assert.assertEquals(codegen.additionalProperties().get(KotlinSpringServerCodegen.SERVICE_IMPLEMENTATION), true);
Assert.assertFalse(codegen.getUseBeanValidation());
Assert.assertEquals(codegen.additionalProperties().get(KotlinSpringServerCodegen.USE_BEANVALIDATION), false);
+ Assert.assertFalse(codegen.isReactive());
+ Assert.assertEquals(codegen.additionalProperties().get(KotlinSpringServerCodegen.REACTIVE), false);
}
@Test