diff --git a/README.md b/README.md index 34bb4637b..b2a218874 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,9 @@ The project is very much Work In Progress and will be published on maven central # Release Notes BOAT is still under development and subject to change. +## 0.17.10 +* Boat maven plugin + * Fix: When using Multipart, generate with `@RequestPart` instead of `@RequestParam` ## 0.17.9 * Boat Maven plugin * Fix: [containerDefaultToNull=true is not backward compatible](https://github.com/Backbase/backbase-openapi-tools/issues/604) diff --git a/boat-scaffold/pom.xml b/boat-scaffold/pom.xml index 2d15fa43f..38e99542c 100644 --- a/boat-scaffold/pom.xml +++ b/boat-scaffold/pom.xml @@ -152,6 +152,13 @@ maven-resolver-transport-http ${maven.resolver.version} + + + com.github.javaparser + javaparser-core + 3.24.9 + test + diff --git a/boat-scaffold/src/main/templates/boat-spring/formParams.mustache b/boat-scaffold/src/main/templates/boat-spring/formParams.mustache index b0819f315..505e5909e 100644 --- a/boat-scaffold/src/main/templates/boat-spring/formParams.mustache +++ b/boat-scaffold/src/main/templates/boat-spring/formParams.mustache @@ -1 +1 @@ -{{#isFormParam}}{{^isFile}}{{>paramDoc}}{{#useBeanValidation}} @Valid{{/useBeanValidation}} @RequestParam(value = "{{baseName}}"{{#required}}, required = true{{/required}}{{^required}}, required = false{{/required}}){{>dateTimeParam}} {{{dataType}}} {{paramName}}{{/isFile}}{{#isFile}}{{>paramDoc}} @RequestPart(value = "{{baseName}}"{{#required}}, required = true{{/required}}{{^required}}, required = false{{/required}}) {{#isArray}}List<{{/isArray}}{{#reactive}}Flux{{/reactive}}{{^reactive}}MultipartFile{{/reactive}}{{#isArray}}>{{/isArray}} {{paramName}}{{/isFile}}{{/isFormParam}} \ No newline at end of file +{{#isFormParam}}{{^isFile}}{{>paramDoc}}{{#isMultipart}} @RequestPart(value = "{{baseName}}"{{#required}}, required = true{{/required}}{{^required}}, required = false{{/required}}) {{>dateTimeParam}} {{{dataType}}} {{paramName}}{{/isMultipart}}{{^isMultipart}}{{#useBeanValidation}} @Valid{{/useBeanValidation}} @RequestParam(value = "{{baseName}}"{{#required}}, required = true{{/required}}{{^required}}, required = false{{/required}}){{>dateTimeParam}} {{{dataType}}} {{paramName}}{{/isMultipart}}{{/isFile}}{{#isFile}}{{>paramDoc}} @RequestPart(value = "{{baseName}}"{{#required}}, required = true{{/required}}{{^required}}, required = false{{/required}}) {{#isArray}}List<{{/isArray}}{{#reactive}}Flux{{/reactive}}{{^reactive}}MultipartFile{{/reactive}}{{#isArray}}>{{/isArray}} {{paramName}}{{/isFile}}{{/isFormParam}} \ No newline at end of file diff --git a/boat-scaffold/src/test/java/com/backbase/oss/codegen/java/BoatSpringCodeGenTests.java b/boat-scaffold/src/test/java/com/backbase/oss/codegen/java/BoatSpringCodeGenTests.java index 1cf3b7bc3..730c92aa4 100644 --- a/boat-scaffold/src/test/java/com/backbase/oss/codegen/java/BoatSpringCodeGenTests.java +++ b/boat-scaffold/src/test/java/com/backbase/oss/codegen/java/BoatSpringCodeGenTests.java @@ -3,32 +3,48 @@ import static com.backbase.oss.codegen.java.BoatSpringCodeGen.USE_PROTECTED_FIELDS; import static java.util.stream.Collectors.groupingBy; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.allOf; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.hasEntry; -import static org.hamcrest.Matchers.is; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import com.backbase.oss.codegen.java.BoatSpringCodeGen.NewLineIndent; +import com.github.javaparser.StaticJavaParser; +import com.github.javaparser.ast.body.MethodDeclaration; +import com.github.javaparser.ast.body.Parameter; import com.samskivert.mustache.Template.Fragment; import io.swagger.v3.oas.models.Operation; +import io.swagger.parser.OpenAPIParser; +import io.swagger.v3.parser.core.models.ParseOptions; +import java.io.File; import java.io.IOException; import java.io.StringWriter; import java.util.Arrays; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.List; import java.util.Map; +import org.apache.commons.io.FileUtils; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.openapitools.codegen.CliOption; -import org.openapitools.codegen.CodegenModel; +import org.openapitools.codegen.ClientOptInput; import org.openapitools.codegen.CodegenOperation; -import org.openapitools.codegen.CodegenParameter; -import org.openapitools.codegen.CodegenProperty; - +import org.openapitools.codegen.DefaultGenerator; class BoatSpringCodeGenTests { + static final String PROP_BASE = BoatSpringCodeGenTests.class.getSimpleName() + "."; + static final String TEST_OUTPUT = System.getProperty(PROP_BASE + "output", "target/boat-spring-codegen-tests"); + + @BeforeAll + static void before() throws IOException { + Files.createDirectories(Paths.get(TEST_OUTPUT)); + FileUtils.deleteDirectory(new File(TEST_OUTPUT, "src")); + } + @Test void clientOptsUnicity() { final BoatSpringCodeGen gen = new BoatSpringCodeGen(); @@ -74,4 +90,37 @@ void addServletRequestTestFromOperation(){ assertEquals("httpServletRequest", co.allParams.get(0).paramName); assertTrue(Arrays.stream(co.allParams.get(0).getClass().getDeclaredFields()).anyMatch(f -> "isHttpServletRequest".equals(f.getName()))); } + + @Test + void multipartWithFileAndObject() throws IOException { + var codegen = new BoatSpringCodeGen(); + var input = new File("src/test/resources/boat-spring/multipart.yaml"); + codegen.setLibrary("spring-boot"); + codegen.setInterfaceOnly(true); + codegen.setOutputDir(TEST_OUTPUT + "/multipart"); + codegen.setInputSpec(input.getAbsolutePath()); + + var openApiInput = new OpenAPIParser().readLocation(input.getAbsolutePath(), null, new ParseOptions()).getOpenAPI(); + var clientOptInput = new ClientOptInput(); + clientOptInput.config(codegen); + clientOptInput.openAPI(openApiInput); + + List files = new DefaultGenerator().opts(clientOptInput).generate(); + + File testApi = files.stream().filter(file -> file.getName().equals("TestApi.java")) + .findFirst() + .get(); + MethodDeclaration testPostMethod = StaticJavaParser.parse(testApi) + .findAll(MethodDeclaration.class) + .get(1); + + Parameter filesParam = testPostMethod.getParameterByName("files").get(); + Parameter contentParam = testPostMethod.getParameterByName("content").get(); + + assertTrue(filesParam.getAnnotationByName("RequestPart").isPresent()); + assertTrue(contentParam.getAnnotationByName("RequestPart").isPresent()); + assertThat(contentParam.getTypeAsString(), equalTo("TestObjectPart")); + assertThat(filesParam.getTypeAsString(), equalTo("List")); + } + } diff --git a/boat-scaffold/src/test/resources/boat-spring/multipart.yaml b/boat-scaffold/src/test/resources/boat-spring/multipart.yaml new file mode 100644 index 000000000..f51f70d20 --- /dev/null +++ b/boat-scaffold/src/test/resources/boat-spring/multipart.yaml @@ -0,0 +1,39 @@ +openapi: 3.0.2 +info: + version: 1.0.0 + title: test + +paths: + /test: + post: + requestBody: + content: + multipart/form-data: + schema: + type: object + required: + - files + - content + properties: + files: + type: array + items: + type: string + format: binary + content: + $ref: "#/components/schemas/testObjectPart" + responses: + 200: + description: OK + +components: + schemas: + testObjectPart: + type: object + required: + - foo + properties: + foo: + type: string + bar: + type: number \ No newline at end of file