Skip to content

Commit 3de5370

Browse files
authored
[Java][Spring] Fixes incorrect request body for map type in reactive spring (#8046)
* [java][spring] updated template to support proper reactive map type * [java][spring] supporting unit test for spring boot reactive request map issue * [java][spring] updated samples * [java][spring] refactoring the issue test spec
1 parent adcf54b commit 3de5370

File tree

7 files changed

+84
-5
lines changed

7 files changed

+84
-5
lines changed

modules/openapi-generator/src/main/resources/JavaSpring/api.mustache

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ public interface {{classname}} {
131131
}
132132

133133
// Override this method
134-
{{#jdk8-default-interface}}default {{/jdk8-default-interface}} {{#responseWrapper}}{{.}}<{{/responseWrapper}}ResponseEntity<{{>returnTypes}}>{{#responseWrapper}}>{{/responseWrapper}} {{operationId}}({{#allParams}}{{^isFile}}{{^isBodyParam}}{{>optionalDataType}}{{/isBodyParam}}{{#isBodyParam}}{{^reactive}}{{{dataType}}}{{/reactive}}{{#reactive}}{{^isArray}}Mono{{/isArray}}{{#isArray}}Flux{{/isArray}}<{{{baseType}}}>{{/reactive}}{{/isBodyParam}}{{/isFile}}{{#isFile}}{{#reactive}}Flux<Part>{{/reactive}}{{^reactive}}MultipartFile{{/reactive}}{{/isFile}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}{{#reactive}}{{#hasParams}}, {{/hasParams}}@ApiIgnore final ServerWebExchange exchange{{/reactive}}{{#vendorExtensions.x-spring-paginated}}, @ApiIgnore final Pageable pageable{{/vendorExtensions.x-spring-paginated}}){{#unhandledException}} throws Exception{{/unhandledException}} {
134+
{{#jdk8-default-interface}}default {{/jdk8-default-interface}} {{#responseWrapper}}{{.}}<{{/responseWrapper}}ResponseEntity<{{>returnTypes}}>{{#responseWrapper}}>{{/responseWrapper}} {{operationId}}({{#allParams}}{{^isFile}}{{^isBodyParam}}{{>optionalDataType}}{{/isBodyParam}}{{#isBodyParam}}{{^reactive}}{{{dataType}}}{{/reactive}}{{#reactive}}{{^isArray}}Mono<{{{dataType}}}>{{/isArray}}{{#isArray}}Flux<{{{baseType}}}>{{/isArray}}{{/reactive}}{{/isBodyParam}}{{/isFile}}{{#isFile}}{{#reactive}}Flux<Part>{{/reactive}}{{^reactive}}MultipartFile{{/reactive}}{{/isFile}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}{{#reactive}}{{#hasParams}}, {{/hasParams}}@ApiIgnore final ServerWebExchange exchange{{/reactive}}{{#vendorExtensions.x-spring-paginated}}, @ApiIgnore final Pageable pageable{{/vendorExtensions.x-spring-paginated}}){{#unhandledException}} throws Exception{{/unhandledException}} {
135135
{{/delegate-method}}
136136
{{^isDelegate}}
137137
{{>methodBody}}

modules/openapi-generator/src/main/resources/JavaSpring/apiDelegate.mustache

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ public interface {{classname}}Delegate {
6969
{{/externalDocs}}
7070
* @see {{classname}}#{{operationId}}
7171
*/
72-
{{#jdk8-default-interface}}default {{/jdk8-default-interface}}{{#responseWrapper}}{{.}}<{{/responseWrapper}}ResponseEntity<{{>returnTypes}}>{{#responseWrapper}}>{{/responseWrapper}} {{operationId}}({{#allParams}}{{^isFile}}{{^isBodyParam}}{{>optionalDataType}}{{/isBodyParam}}{{#isBodyParam}}{{^reactive}}{{{dataType}}}{{/reactive}}{{#reactive}}{{^isArray}}Mono{{/isArray}}{{#isArray}}Flux{{/isArray}}<{{{baseType}}}>{{/reactive}}{{/isBodyParam}}{{/isFile}}{{#isFile}}{{#isArray}}List<{{/isArray}}{{#reactive}}Flux<Part>{{/reactive}}{{^reactive}}MultipartFile{{/reactive}}{{#isArray}}>{{/isArray}}{{/isFile}} {{paramName}}{{^-last}},
72+
{{#jdk8-default-interface}}default {{/jdk8-default-interface}}{{#responseWrapper}}{{.}}<{{/responseWrapper}}ResponseEntity<{{>returnTypes}}>{{#responseWrapper}}>{{/responseWrapper}} {{operationId}}({{#allParams}}{{^isFile}}{{^isBodyParam}}{{>optionalDataType}}{{/isBodyParam}}{{#isBodyParam}}{{^reactive}}{{{dataType}}}{{/reactive}}{{#reactive}}{{^isArray}}Mono<{{{dataType}}}>{{/isArray}}{{#isArray}}Flux<{{{baseType}}}>{{/isArray}}{{/reactive}}{{/isBodyParam}}{{/isFile}}{{#isFile}}{{#isArray}}List<{{/isArray}}{{#reactive}}Flux<Part>{{/reactive}}{{^reactive}}MultipartFile{{/reactive}}{{#isArray}}>{{/isArray}}{{/isFile}} {{paramName}}{{^-last}},
7373
{{/-last}}{{/allParams}}{{#reactive}}{{#hasParams}},
7474
{{/hasParams}}ServerWebExchange exchange{{/reactive}}{{#vendorExtensions.x-spring-paginated}}, final Pageable pageable{{/vendorExtensions.x-spring-paginated}}){{#unhandledException}} throws Exception{{/unhandledException}}{{^jdk8-default-interface}};{{/jdk8-default-interface}}{{#jdk8-default-interface}} {
7575
{{>methodBody}}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{{#isBodyParam}}@ApiParam(value = "{{{description}}}" {{#required}},required=true{{/required}} {{^isContainer}}{{#allowableValues}}, allowableValues="{{{allowableValues}}}"{{/allowableValues}}{{#defaultValue}}, defaultValue={{^isString}}"{{/isString}}{{#isString}}{{#isEnum}}"{{/isEnum}}{{/isString}}{{{defaultValue}}}{{^isString}}"{{/isString}}{{#isString}}{{#isEnum}}"{{/isEnum}}{{/isString}}{{/defaultValue}}{{/isContainer}}) {{#useBeanValidation}}@Valid{{/useBeanValidation}} @RequestBody{{^required}}(required = false){{/required}} {{^reactive}}{{{dataType}}}{{/reactive}}{{#reactive}}{{^isArray}}Mono{{/isArray}}{{#isArray}}Flux{{/isArray}}<{{{baseType}}}>{{/reactive}} {{paramName}}{{/isBodyParam}}
1+
{{#isBodyParam}}@ApiParam(value = "{{{description}}}" {{#required}},required=true{{/required}} {{^isContainer}}{{#allowableValues}}, allowableValues="{{{allowableValues}}}"{{/allowableValues}}{{#defaultValue}}, defaultValue={{^isString}}"{{/isString}}{{#isString}}{{#isEnum}}"{{/isEnum}}{{/isString}}{{{defaultValue}}}{{^isString}}"{{/isString}}{{#isString}}{{#isEnum}}"{{/isEnum}}{{/isString}}{{/defaultValue}}{{/isContainer}}) {{#useBeanValidation}}@Valid{{/useBeanValidation}} @RequestBody{{^required}}(required = false){{/required}} {{^reactive}}{{{dataType}}}{{/reactive}}{{#reactive}}{{^isArray}}Mono<{{{dataType}}}>{{/isArray}}{{#isArray}}Flux<{{{baseType}}}>{{/isArray}}{{/reactive}} {{paramName}}{{/isBodyParam}}

modules/openapi-generator/src/test/java/org/openapitools/codegen/java/spring/SpringCodegenTest.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -619,4 +619,38 @@ private void beanValidationForFormatEmail(boolean useBeanValidation, boolean per
619619
public void useBeanValidationTruePerformBeanValidationTrueJava8TrueForFormatEmail() throws IOException {
620620
beanValidationForFormatEmail(true, true, true, "@javax.validation.constraints.Email", "@org.hibernate.validator.constraints.Email");
621621
}
622+
623+
@Test
624+
public void reactiveMapTypeRequestMonoTest() throws IOException {
625+
File output = Files.createTempDirectory("test").toFile().getCanonicalFile();
626+
output.deleteOnExit();
627+
String outputPath = output.getAbsolutePath().replace('\\', '/');
628+
629+
final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_0/spring/issue_8045.yaml");
630+
final SpringCodegen codegen = new SpringCodegen();
631+
codegen.setOpenAPI(openAPI);
632+
codegen.setOutputDir(output.getAbsolutePath());
633+
634+
codegen.additionalProperties().put(SpringCodegen.DELEGATE_PATTERN, "true");
635+
codegen.additionalProperties().put(SpringCodegen.REACTIVE, "true");
636+
637+
ClientOptInput input = new ClientOptInput();
638+
input.openAPI(openAPI);
639+
input.config(codegen);
640+
641+
DefaultGenerator generator = new DefaultGenerator();
642+
643+
generator.setGeneratorPropertyDefault(CodegenConstants.MODELS, "false");
644+
generator.setGeneratorPropertyDefault(CodegenConstants.MODEL_TESTS, "false");
645+
generator.setGeneratorPropertyDefault(CodegenConstants.MODEL_DOCS, "false");
646+
generator.setGeneratorPropertyDefault(CodegenConstants.APIS, "true");
647+
generator.setGeneratorPropertyDefault(CodegenConstants.SUPPORTING_FILES, "false");
648+
649+
generator.opts(input).generate();
650+
651+
assertFileContains(Paths.get(outputPath + "/src/main/java/org/openapitools/api/SomeApi.java"), "Mono<Map<String, DummyRequest>>");
652+
assertFileContains(Paths.get(outputPath + "/src/main/java/org/openapitools/api/SomeApiDelegate.java"), "Mono<Map<String, DummyRequest>>");
653+
assertFileNotContains(Paths.get(outputPath + "/src/main/java/org/openapitools/api/SomeApi.java"), "Mono<DummyRequest>");
654+
assertFileNotContains(Paths.get(outputPath + "/src/main/java/org/openapitools/api/SomeApiDelegate.java"), "Mono<DummyRequest>");
655+
}
622656
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
openapi: 3.0.0
2+
info:
3+
version: "1.0.0"
4+
title: reactive-spring-boot-request-body-issue
5+
tags:
6+
- name: ReactiveSpringBootRequestBodyIssue
7+
paths:
8+
/some/dummy/endpoint:
9+
post:
10+
tags:
11+
- ReactiveSpringBootRequestBodyIssue
12+
requestBody:
13+
description: request
14+
content:
15+
application/json:
16+
schema:
17+
type: object
18+
additionalProperties:
19+
$ref: '#/components/schemas/DummyRequest'
20+
required: true
21+
responses:
22+
200:
23+
description: Successfully created reverse listings for retail
24+
content:
25+
application/json:
26+
schema:
27+
type: object
28+
additionalProperties:
29+
$ref: '#/components/schemas/DummyResponse'
30+
components:
31+
schemas:
32+
DummyResponse:
33+
required:
34+
- status
35+
type: object
36+
properties:
37+
status:
38+
type: string
39+
DummyRequest:
40+
required:
41+
- product_id
42+
type: object
43+
properties:
44+
product_id:
45+
type: string

samples/server/petstore/springboot-reactive/src/main/java/org/openapitools/api/FakeApi.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ default Mono<ResponseEntity<Void>> testGroupParameters(@NotNull @ApiParam(value
295295
value = "/fake/inline-additionalProperties",
296296
consumes = { "application/json" }
297297
)
298-
default Mono<ResponseEntity<Void>> testInlineAdditionalProperties(@ApiParam(value = "request body" ,required=true ) @Valid @RequestBody Mono<String> param, @ApiIgnore final ServerWebExchange exchange) {
298+
default Mono<ResponseEntity<Void>> testInlineAdditionalProperties(@ApiParam(value = "request body" ,required=true ) @Valid @RequestBody Mono<Map<String, String>> param, @ApiIgnore final ServerWebExchange exchange) {
299299
return getDelegate().testInlineAdditionalProperties(param, exchange);
300300
}
301301

samples/server/petstore/springboot-reactive/src/main/java/org/openapitools/api/FakeApiDelegate.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ default Mono<ResponseEntity<Void>> testGroupParameters(Integer requiredStringGro
288288
* @return successful operation (status code 200)
289289
* @see FakeApi#testInlineAdditionalProperties
290290
*/
291-
default Mono<ResponseEntity<Void>> testInlineAdditionalProperties(Mono<String> param,
291+
default Mono<ResponseEntity<Void>> testInlineAdditionalProperties(Mono<Map<String, String>> param,
292292
ServerWebExchange exchange) {
293293
Mono<Void> result = Mono.empty();
294294
exchange.getResponse().setStatusCode(HttpStatus.NOT_IMPLEMENTED);

0 commit comments

Comments
 (0)