diff --git a/client/deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/CodegenConfig.java b/client/deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/CodegenConfig.java index 3f6baff0..c0619c8b 100644 --- a/client/deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/CodegenConfig.java +++ b/client/deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/CodegenConfig.java @@ -48,6 +48,7 @@ public enum ConfigName { //global & spec configs SKIP_FORM_MODEL("skip-form-model"), MUTINY("mutiny"), + MUTINY_OPERATION_IDS("mutiny.operation-ids"), ADDITIONAL_MODEL_TYPE_ANNOTATIONS("additional-model-type-annotations"), ADDITIONAL_ENUM_TYPE_UNEXPECTED_MEMBER("additional-enum-type-unexpected-member"), ADDITIONAL_ENUM_TYPE_UNEXPECTED_MEMBER_NAME("additional-enum-type-unexpected-member-name"), diff --git a/client/deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/CommonItemConfig.java b/client/deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/CommonItemConfig.java index beef0eb8..55e36fe1 100644 --- a/client/deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/CommonItemConfig.java +++ b/client/deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/CommonItemConfig.java @@ -86,6 +86,34 @@ public class CommonItemConfig { @ConfigItem(name = "mutiny") public Optional supportMutiny; + /** + * Handles the return type for each operation, depending on the configuration. + * The following cases are supported: + *

+ * 1. If {@code mutiny} is enabled and the operation ID is specified to return {@code Multi}: + * - The return type will be wrapped in {@link io.smallrye.mutiny.Multi}. + * - If {@code return-response} is enabled, the return type will be + * {@link io.smallrye.mutiny.Multi}. + * - If the operation has a void return type, it will return {@link io.smallrye.mutiny.Multi}. + * - Otherwise, it will return {@link io.smallrye.mutiny.Multi}. + *

+ * 2. If {@code mutiny} is enabled and the operation ID is specified to return {@code Uni}: + * - The return type will be wrapped in {@link io.smallrye.mutiny.Uni}. + * - If {@code return-response} is enabled, the return type will be + * {@link io.smallrye.mutiny.Uni}. + * - If the operation has a void return type, it will return {@link io.smallrye.mutiny.Uni}. + * - Otherwise, it will return {@link io.smallrye.mutiny.Uni}. + *

+ * 3. If {@code mutiny} is enabled but no specific operation ID is configured for {@code Multi} or {@code Uni}: + * - The return type defaults to {@code Uni}. + * - If {@code return-response} is enabled, the return type will be + * {@link io.smallrye.mutiny.Uni}. + * - If the operation has a void return type, it will return {@link io.smallrye.mutiny.Uni}. + * - Otherwise, it will return {@link io.smallrye.mutiny.Uni}`. + */ + @ConfigItem(name = "mutiny.operation-ids") + public Optional> mutinyMultiOperationIds; + /** * Defines, whether the `PartFilename` ({@link org.jboss.resteasy.reactive.PartFilename} or * {@link org.jboss.resteasy.annotations.providers.multipart.PartFilename}) annotation should be generated for @@ -118,4 +146,4 @@ public class CommonItemConfig { */ @ConfigItem(name = "use-bean-validation") public Optional useBeanValidation; -} \ No newline at end of file +} diff --git a/client/deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/codegen/OpenApiGeneratorCodeGenBase.java b/client/deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/codegen/OpenApiGeneratorCodeGenBase.java index aadd47f6..733147b7 100644 --- a/client/deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/codegen/OpenApiGeneratorCodeGenBase.java +++ b/client/deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/codegen/OpenApiGeneratorCodeGenBase.java @@ -266,6 +266,9 @@ protected void generate(final Config config, final Path openApiFilePath, final P CodegenConfig.ConfigName.ADDITIONAL_PROPERTIES_AS_ATTRIBUTE, Boolean.class) .orElse(Boolean.FALSE); + getValues(smallRyeConfig, openApiFilePath, CodegenConfig.ConfigName.MUTINY_OPERATION_IDS, String.class, String.class) + .ifPresent(generator::withMutinyReturnTypes); + generator.withAdditionalPropertiesAsAttribute(additionalPropertiesAsAttribute); GlobalSettings.setProperty( OpenApiClientGeneratorWrapper.SUPPORTS_ADDITIONAL_PROPERTIES_AS_ATTRIBUTE, diff --git a/client/deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/wrapper/OpenApiClientGeneratorWrapper.java b/client/deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/wrapper/OpenApiClientGeneratorWrapper.java index 0a7e3aa9..93fa8906 100644 --- a/client/deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/wrapper/OpenApiClientGeneratorWrapper.java +++ b/client/deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/wrapper/OpenApiClientGeneratorWrapper.java @@ -12,6 +12,7 @@ import java.io.File; import java.nio.file.Path; import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; @@ -117,6 +118,14 @@ public OpenApiClientGeneratorWrapper withMutiny(final Boolean config) { return this; } + public OpenApiClientGeneratorWrapper withMutinyReturnTypes(final Map returnTypeMappings) { + if (returnTypeMappings != null && !returnTypeMappings.isEmpty()) { + Map mutinyOperationIdsMap = new HashMap<>(returnTypeMappings); + configurator.addAdditionalProperty("mutiny-operation-ids", mutinyOperationIdsMap); + } + return this; + } + /** * Sets the global 'skipFormModel' setting. If not set this setting will default to true. * diff --git a/client/deployment/src/main/resources/templates/libraries/microprofile/api.qute b/client/deployment/src/main/resources/templates/libraries/microprofile/api.qute index 468afb97..b7b2f79d 100644 --- a/client/deployment/src/main/resources/templates/libraries/microprofile/api.qute +++ b/client/deployment/src/main/resources/templates/libraries/microprofile/api.qute @@ -50,13 +50,57 @@ public interface {classname} { {/if}{/for} {/if}{/for} {#if mutiny} - {#if return-response} - public io.smallrye.mutiny.Uni {op.nickname}( + {#if mutiny-operation-ids.get(op.operationIdOriginal) == "Multi"} + {#if return-response} + public io.smallrye.mutiny.Multi {op.nickname}( + {#else} + {#if op.returnType == "void"} + public io.smallrye.mutiny.Multi {op.nickname}( + {#else} + public io.smallrye.mutiny.Multi<{#if op.returnType}{op.returnType}{#else}jakarta.ws.rs.core.Response{/if}> {op.nickname}( + {/if} + {/if} {#else} - {#if op.returnType == "void"} + {#if mutiny-operation-ids.get(op.operationIdOriginal) == "Uni"} + {#if return-response} + public io.smallrye.mutiny.Uni {op.nickname}( + {#else} + {#if op.returnType == "void"} public io.smallrye.mutiny.Uni {op.nickname}( + {#else} + public io.smallrye.mutiny.Uni<{#if op.returnType}{op.returnType}{#else}jakarta.ws.rs.core.Response{/if}> {op.nickname}( + {/if} + {/if} {#else} + {#if !mutiny-operation-ids} + {#if return-response} + public io.smallrye.mutiny.Uni {op.nickname}( + {#else} + {#if op.returnType == "void"} + public io.smallrye.mutiny.Uni {op.nickname}( + {#else} + public {#if op.returnType}io.smallrye.mutiny.Uni<{op.returnType}>{#else}io.smallrye.mutiny.Uni{/if} {op.nickname}( + {/if} + {/if} + {#else} + {#if mutiny-operation-ids.get(op.operationIdOriginal)} + {#if op.returnType == "void"} + public io.smallrye.mutiny.Uni {op.nickname}( + {#else} public {#if op.returnType}io.smallrye.mutiny.Uni<{op.returnType}>{#else}io.smallrye.mutiny.Uni{/if} {op.nickname}( + {/if} + {#else} + {#if return-response} + public jakarta.ws.rs.core.Response {op.nickname}( + {#else} + {#if op.returnType == "void"} + public jakarta.ws.rs.core.Response {op.nickname}( + {#else} + public {#if op.returnType}{op.returnType}{#else}jakarta.ws.rs.core.Response{/if} {op.nickname}( + {/if} + {/if} + {/if} + {/if} {/if} {/if} {#else} diff --git a/client/deployment/src/test/java/io/quarkiverse/openapi/generator/deployment/wrapper/OpenApiClientGeneratorWrapperTest.java b/client/deployment/src/test/java/io/quarkiverse/openapi/generator/deployment/wrapper/OpenApiClientGeneratorWrapperTest.java index abce1b6f..0bd4002c 100644 --- a/client/deployment/src/test/java/io/quarkiverse/openapi/generator/deployment/wrapper/OpenApiClientGeneratorWrapperTest.java +++ b/client/deployment/src/test/java/io/quarkiverse/openapi/generator/deployment/wrapper/OpenApiClientGeneratorWrapperTest.java @@ -2,6 +2,7 @@ import static io.quarkiverse.openapi.generator.deployment.assertions.Assertions.assertThat; import static java.util.Objects.requireNonNull; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -434,6 +435,75 @@ void shouldBeAbleToEnableMutiny() throws URISyntaxException, FileNotFoundExcepti } + @Test + void shouldBeAbleToApplyMutinyOnSpecificEndpoints() throws URISyntaxException, FileNotFoundException { + List generatedFiles = createGeneratorWrapper("simple-openapi.json") + .withMutiny(true) + .withMutinyReturnTypes(Map.of("helloMethod", "Uni", "Bye method_get", "Multi")) + .generate("org.mutiny.enabled"); + + Optional file = generatedFiles.stream() + .filter(f -> f.getName().endsWith("DefaultApi.java")) + .findAny(); + assertThat(file).isNotEmpty(); + CompilationUnit compilationUnit = StaticJavaParser.parse(file.orElseThrow()); + List methodDeclarations = compilationUnit.findAll(MethodDeclaration.class); + assertThat(methodDeclarations).isNotEmpty(); + + Optional helloMethodDeclaration = getMethodDeclarationByIdentifier(methodDeclarations, + "helloMethod"); + Optional byeMethodGetDeclaration = getMethodDeclarationByIdentifier(methodDeclarations, + "byeMethodGet"); + Optional getUserDeclaration = getMethodDeclarationByIdentifier(methodDeclarations, + "getUser"); + Optional getNumbersDeclaration = getMethodDeclarationByIdentifier(methodDeclarations, + "getNumbers"); + + assertThat(helloMethodDeclaration).hasValueSatisfying( + methodDeclaration -> assertEquals("io.smallrye.mutiny.Uni", methodDeclaration.getType().toString())); + assertThat(byeMethodGetDeclaration).hasValueSatisfying( + methodDeclaration -> assertEquals("io.smallrye.mutiny.Multi", methodDeclaration.getType().toString())); + assertThat(getUserDeclaration).hasValueSatisfying( + methodDeclaration -> assertEquals("GetUser200Response", methodDeclaration.getType().toString())); + assertThat(getNumbersDeclaration).hasValueSatisfying( + methodDeclaration -> assertEquals("List", methodDeclaration.getType().toString())); + } + + @Test + void shouldBeAbleToApplyMutinyOnSpecificEndpointsWhenUserDefineWrongConfiguration() + throws URISyntaxException, FileNotFoundException { + List generatedFiles = createGeneratorWrapper("simple-openapi.json") + .withMutiny(true) + .withMutinyReturnTypes(Map.of("helloMethod", "Uni", "Bye method_get", "BadConfig")) + .generate("org.mutiny.enabled"); + + Optional file = generatedFiles.stream() + .filter(f -> f.getName().endsWith("DefaultApi.java")) + .findAny(); + assertThat(file).isNotEmpty(); + CompilationUnit compilationUnit = StaticJavaParser.parse(file.orElseThrow()); + List methodDeclarations = compilationUnit.findAll(MethodDeclaration.class); + assertThat(methodDeclarations).isNotEmpty(); + + Optional helloMethodDeclaration = getMethodDeclarationByIdentifier(methodDeclarations, + "helloMethod"); + Optional byeMethodGetDeclaration = getMethodDeclarationByIdentifier(methodDeclarations, + "byeMethodGet"); + Optional getUserDeclaration = getMethodDeclarationByIdentifier(methodDeclarations, + "getUser"); + Optional getNumbersDeclaration = getMethodDeclarationByIdentifier(methodDeclarations, + "getNumbers"); + + assertThat(helloMethodDeclaration).hasValueSatisfying( + methodDeclaration -> assertEquals("io.smallrye.mutiny.Uni", methodDeclaration.getType().toString())); + assertThat(byeMethodGetDeclaration).hasValueSatisfying( + methodDeclaration -> assertEquals("io.smallrye.mutiny.Uni", methodDeclaration.getType().toString())); + assertThat(getUserDeclaration).hasValueSatisfying( + methodDeclaration -> assertEquals("GetUser200Response", methodDeclaration.getType().toString())); + assertThat(getNumbersDeclaration).hasValueSatisfying( + methodDeclaration -> assertEquals("List", methodDeclaration.getType().toString())); + } + @Test void shouldBeAbleToAddCustomDateAndTimeMappings() throws URISyntaxException, FileNotFoundException { List generatedFiles = createGeneratorWrapper("datetime-regression.yml") @@ -677,4 +747,9 @@ private Optional findVariableByName(List f .filter((VariableDeclarator variable) -> name.equals(variable.getName().asString())) .findFirst(); } + + private static Optional getMethodDeclarationByIdentifier(List methodDeclarations, + String methodName) { + return methodDeclarations.stream().filter(md -> md.getName().getIdentifier().equals(methodName)).findAny(); + } } diff --git a/client/deployment/src/test/resources/openapi/simple-openapi.json b/client/deployment/src/test/resources/openapi/simple-openapi.json index caed9954..ccaf6f05 100644 --- a/client/deployment/src/test/resources/openapi/simple-openapi.json +++ b/client/deployment/src/test/resources/openapi/simple-openapi.json @@ -39,6 +39,51 @@ } } } + }, + "/user": { + "get": { + "operationId": "getUser", + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/numbers": { + "get": { + "operationId": "getNumbers", + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "integer" + } + } + } + } + } + } + } } } -} \ No newline at end of file +} diff --git a/client/integration-tests/mutiny/src/main/openapi/quarkus-multiple-endpoints-openapi.yaml b/client/integration-tests/mutiny/src/main/openapi/quarkus-multiple-endpoints-openapi.yaml new file mode 100644 index 00000000..3d07c372 --- /dev/null +++ b/client/integration-tests/mutiny/src/main/openapi/quarkus-multiple-endpoints-openapi.yaml @@ -0,0 +1,87 @@ +openapi: 3.0.3 +info: + title: Test API + version: "1.0" +paths: + /testEndpoint1: + get: + tags: + - Test Endpoint + summary: Simple test endpoint that returns a plain message. + operationId: testEndpoint1 + responses: + "200": + description: Success + content: + application/json: + schema: + type: object + properties: + message: + type: string + example: "Test Endpoint 1 success!" + /testEndpoint2: + post: + tags: + - Test Endpoint + summary: Test endpoint to validate POST requests. + operationId: testEndpoint2 + requestBody: + content: + application/json: + schema: + type: object + properties: + input: + type: string + example: "Test input" + responses: + "200": + description: Successfully received input. + content: + application/json: + schema: + type: object + properties: + message: + type: string + example: "Test Endpoint 2 received the input." + /testEndpoint3: + put: + tags: + - Test Endpoint + summary: Test PUT request with a JSON body. + operationId: testEndpoint3 + requestBody: + content: + application/json: + schema: + type: object + properties: + name: + type: string + example: "Test Name" + value: + type: integer + example: 123 + responses: + "200": + description: PUT request successful. + content: + application/json: + schema: + type: object + properties: + message: + type: string + example: "Test Endpoint 3 processed the data successfully." +components: + schemas: + Response: + type: object + properties: + status: + format: int32 + type: integer + entity: + type: object diff --git a/client/integration-tests/mutiny/src/main/openapi/quarkus-multiple-endpoints-wrong-configuration-openapi.yaml b/client/integration-tests/mutiny/src/main/openapi/quarkus-multiple-endpoints-wrong-configuration-openapi.yaml new file mode 100644 index 00000000..16c8a052 --- /dev/null +++ b/client/integration-tests/mutiny/src/main/openapi/quarkus-multiple-endpoints-wrong-configuration-openapi.yaml @@ -0,0 +1,114 @@ +openapi: 3.0.3 +info: + title: Test API + version: "1.0" +paths: + /testEndpoint1: + get: + tags: + - Test Endpoint Wrong Configuration + summary: Simple test endpoint that returns a plain message. + operationId: testEndpoint1 + responses: + "200": + description: Success + content: + application/json: + schema: + type: object + properties: + message: + type: string + example: "Test Endpoint 1 success!" + /testEndpoint2: + post: + tags: + - Test Endpoint Wrong Configuration + summary: Test endpoint to validate POST requests. + operationId: testEndpoint2 + requestBody: + content: + application/json: + schema: + type: object + properties: + input: + type: string + example: "Test input" + responses: + "200": + description: Successfully received input. + content: + application/json: + schema: + type: object + properties: + message: + type: string + example: "Test Endpoint 2 received the input." + /testEndpoint3: + put: + tags: + - Test Endpoint Wrong Configuration + summary: Test PUT request with a JSON body. + operationId: testEndpoint3 + requestBody: + content: + application/json: + schema: + type: object + properties: + name: + type: string + example: "Test Name" + value: + type: integer + example: 123 + responses: + "200": + description: PUT request successful. + content: + application/json: + schema: + type: object + properties: + message: + type: string + example: "Test Endpoint 3 processed the data successfully." + + + /testEndpoint4: + delete: + tags: + - Test Endpoint Wrong Configuration + summary: Test DELETE request to remove an entity. + operationId: testEndpoint4 + parameters: + - name: id + in: query + required: true + description: ID of the entity to delete + schema: + type: integer + example: 456 + responses: + "200": + description: DELETE request successful. + content: + application/json: + schema: + type: object + properties: + message: + type: string + example: "Test Endpoint 4 successfully deleted the entity." +components: + schemas: + Response: + type: object + properties: + status: + format: int32 + type: integer + entity: + type: object diff --git a/client/integration-tests/mutiny/src/main/resources/application.properties b/client/integration-tests/mutiny/src/main/resources/application.properties index 4ea74c42..b1900ad1 100644 --- a/client/integration-tests/mutiny/src/main/resources/application.properties +++ b/client/integration-tests/mutiny/src/main/resources/application.properties @@ -1,2 +1,11 @@ quarkus.rest-client.quarkus_simple_openapi_yaml.url=http://localhost:8080 -quarkus.openapi-generator.codegen.spec.quarkus_simple_openapi_yaml.mutiny=true \ No newline at end of file +quarkus.openapi-generator.codegen.spec.quarkus_simple_openapi_yaml.mutiny=true + +quarkus.openapi-generator.codegen.spec.quarkus_multiple_endpoints_openapi_yaml.mutiny=true +quarkus.openapi-generator.codegen.spec.quarkus_multiple_endpoints_openapi_yaml.mutiny.operation-ids.testEndpoint1=Multi +quarkus.openapi-generator.codegen.spec.quarkus_multiple_endpoints_openapi_yaml.mutiny.operation-ids.testEndpoint2=Uni + +quarkus.openapi-generator.codegen.spec.quarkus_multiple_endpoints_wrong_configuration_openapi_yaml.mutiny=true +quarkus.openapi-generator.codegen.spec.quarkus_multiple_endpoints_wrong_configuration_openapi_yaml.mutiny.operation-ids.testEndpoint1=Multi +quarkus.openapi-generator.codegen.spec.quarkus_multiple_endpoints_wrong_configuration_openapi_yaml.mutiny.operation-ids.testEndpoint2=Uni +quarkus.openapi-generator.codegen.spec.quarkus_multiple_endpoints_wrong_configuration_openapi_yaml.mutiny.operation-ids.testEndpoint3=Umi \ No newline at end of file diff --git a/client/integration-tests/mutiny/src/test/java/io/quarkiverse/openapi/generator/it/MutinyTest.java b/client/integration-tests/mutiny/src/test/java/io/quarkiverse/openapi/generator/it/MutinyTest.java index ba27c861..ae9853de 100644 --- a/client/integration-tests/mutiny/src/test/java/io/quarkiverse/openapi/generator/it/MutinyTest.java +++ b/client/integration-tests/mutiny/src/test/java/io/quarkiverse/openapi/generator/it/MutinyTest.java @@ -4,9 +4,16 @@ import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; +import org.openapi.quarkus.quarkus_multiple_endpoints_openapi_yaml.api.TestEndpointApi; +import org.openapi.quarkus.quarkus_multiple_endpoints_openapi_yaml.model.TestEndpoint2Request; +import org.openapi.quarkus.quarkus_multiple_endpoints_openapi_yaml.model.TestEndpoint3200Response; +import org.openapi.quarkus.quarkus_multiple_endpoints_openapi_yaml.model.TestEndpoint3Request; +import org.openapi.quarkus.quarkus_multiple_endpoints_wrong_configuration_openapi_yaml.api.TestEndpointWrongConfigurationApi; +import org.openapi.quarkus.quarkus_multiple_endpoints_wrong_configuration_openapi_yaml.model.TestEndpoint4200Response; import org.openapi.quarkus.quarkus_simple_openapi_yaml.api.ReactiveGreetingResourceApi; import io.quarkus.test.junit.QuarkusTest; +import io.smallrye.mutiny.Multi; import io.smallrye.mutiny.Uni; @QuarkusTest @@ -18,4 +25,30 @@ void apiIsBeingGenerated() throws NoSuchMethodException { assertThat(ReactiveGreetingResourceApi.class.getMethod("hello").getReturnType()) .isEqualTo(Uni.class); } + + @Test + void apiIsBeingGeneratedWithDeclaredMutinyReturnsType() throws NoSuchMethodException { + assertThat(TestEndpointApi.class.getMethod("testEndpoint1").getReturnType()) + .isEqualTo(Multi.class); + assertThat(TestEndpointApi.class.getMethod("testEndpoint2", TestEndpoint2Request.class).getReturnType()) + .isEqualTo(Uni.class); + assertThat(TestEndpointApi.class.getMethod("testEndpoint3", TestEndpoint3Request.class).getReturnType()) + .isEqualTo(TestEndpoint3200Response.class); + } + + @Test + void apiIsBeingGenerateWithWrongConfigurationdWithDeclaredMutinyReturnsType() throws NoSuchMethodException { + assertThat(TestEndpointWrongConfigurationApi.class.getMethod("testEndpoint1").getReturnType()) + .isEqualTo(Multi.class); + assertThat(TestEndpointWrongConfigurationApi.class.getMethod("testEndpoint2", + org.openapi.quarkus.quarkus_multiple_endpoints_wrong_configuration_openapi_yaml.model.TestEndpoint2Request.class) + .getReturnType()) + .isEqualTo(Uni.class); + assertThat(TestEndpointWrongConfigurationApi.class.getMethod("testEndpoint3", + org.openapi.quarkus.quarkus_multiple_endpoints_wrong_configuration_openapi_yaml.model.TestEndpoint3Request.class) + .getReturnType()) + .isEqualTo(Uni.class); + assertThat(TestEndpointWrongConfigurationApi.class.getMethod("testEndpoint4", Integer.class).getReturnType()) + .isEqualTo(TestEndpoint4200Response.class); + } } diff --git a/client/integration-tests/return-response/src/main/openapi/mutiny-multi-return-response-false-string-simple-openapi.yaml b/client/integration-tests/return-response/src/main/openapi/mutiny-multi-return-response-false-string-simple-openapi.yaml new file mode 100644 index 00000000..685fdba7 --- /dev/null +++ b/client/integration-tests/return-response/src/main/openapi/mutiny-multi-return-response-false-string-simple-openapi.yaml @@ -0,0 +1,274 @@ +--- +openapi: 3.0.3 +info: + title: greeting-flow API + version: "1.0" +paths: + /: + post: + requestBody: + content: + '*/*': + schema: + $ref: '#/components/schemas/CloudEvent' + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/Response' + /hello: + get: + tags: + - MutinyMultiReturnResponseFalseString + operationId: hello + responses: + "200": + description: OK + content: + text/plain: + schema: + type: string + /messaging/topics: + get: + tags: + - Quarkus Topics Information Resource + responses: + "200": + description: OK +components: + schemas: + CloudEvent: + type: object + properties: + specVersion: + $ref: '#/components/schemas/SpecVersion' + id: + type: string + type: + type: string + source: + format: uri + type: string + dataContentType: + type: string + dataSchema: + format: uri + type: string + subject: + type: string + time: + format: date-time + type: string + attributeNames: + uniqueItems: true + type: array + items: + type: string + extensionNames: + uniqueItems: true + type: array + items: + type: string + data: + $ref: '#/components/schemas/CloudEventData' + CloudEventData: + type: object + EntityTag: + type: object + properties: + value: + type: string + weak: + type: boolean + Family: + enum: + - INFORMATIONAL + - SUCCESSFUL + - REDIRECTION + - CLIENT_ERROR + - SERVER_ERROR + - OTHER + type: string + Link: + type: object + properties: + uri: + format: uri + type: string + uriBuilder: + $ref: '#/components/schemas/UriBuilder' + rel: + type: string + rels: + type: array + items: + type: string + title: + type: string + type: + type: string + params: + type: object + additionalProperties: + type: string + Locale: + type: object + properties: + language: + type: string + script: + type: string + country: + type: string + variant: + type: string + extensionKeys: + uniqueItems: true + type: array + items: + format: byte + type: string + unicodeLocaleAttributes: + uniqueItems: true + type: array + items: + type: string + unicodeLocaleKeys: + uniqueItems: true + type: array + items: + type: string + iSO3Language: + type: string + iSO3Country: + type: string + displayLanguage: + type: string + displayScript: + type: string + displayCountry: + type: string + displayVariant: + type: string + displayName: + type: string + MediaType: + type: object + properties: + type: + type: string + subtype: + type: string + parameters: + type: object + additionalProperties: + type: string + wildcardType: + type: boolean + wildcardSubtype: + type: boolean + MultivaluedMapStringObject: + type: object + additionalProperties: + type: array + items: + type: object + MultivaluedMapStringString: + type: object + additionalProperties: + type: array + items: + type: string + NewCookie: + type: object + properties: + name: + type: string + value: + type: string + version: + format: int32 + type: integer + path: + type: string + domain: + type: string + comment: + type: string + maxAge: + format: int32 + type: integer + expiry: + format: date + type: string + secure: + type: boolean + httpOnly: + type: boolean + Response: + type: object + properties: + status: + format: int32 + type: integer + statusInfo: + $ref: '#/components/schemas/StatusType' + entity: + type: object + mediaType: + $ref: '#/components/schemas/MediaType' + language: + $ref: '#/components/schemas/Locale' + length: + format: int32 + type: integer + allowedMethods: + uniqueItems: true + type: array + items: + type: string + cookies: + type: object + additionalProperties: + $ref: '#/components/schemas/NewCookie' + entityTag: + $ref: '#/components/schemas/EntityTag' + date: + format: date + type: string + lastModified: + format: date + type: string + location: + format: uri + type: string + links: + uniqueItems: true + type: array + items: + $ref: '#/components/schemas/Link' + metadata: + $ref: '#/components/schemas/MultivaluedMapStringObject' + headers: + $ref: '#/components/schemas/MultivaluedMapStringObject' + stringHeaders: + $ref: '#/components/schemas/MultivaluedMapStringString' + SpecVersion: + enum: + - V03 + - V1 + type: string + StatusType: + type: object + properties: + statusCode: + format: int32 + type: integer + family: + $ref: '#/components/schemas/Family' + reasonPhrase: + type: string + UriBuilder: + type: object diff --git a/client/integration-tests/return-response/src/main/openapi/mutiny-multi-return-response-false-void-simple-openapi.yaml b/client/integration-tests/return-response/src/main/openapi/mutiny-multi-return-response-false-void-simple-openapi.yaml new file mode 100644 index 00000000..9e9eac85 --- /dev/null +++ b/client/integration-tests/return-response/src/main/openapi/mutiny-multi-return-response-false-void-simple-openapi.yaml @@ -0,0 +1,270 @@ +--- +openapi: 3.0.3 +info: + title: greeting-flow API + version: "1.0" +paths: + /: + post: + requestBody: + content: + '*/*': + schema: + $ref: '#/components/schemas/CloudEvent' + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/Response' + /hello: + get: + tags: + - MutinyMultiReturnResponseFalseVoid + operationId: hello + responses: + "200": + description: OK + /messaging/topics: + get: + tags: + - Quarkus Topics Information Resource + responses: + "200": + description: OK +components: + schemas: + CloudEvent: + type: object + properties: + specVersion: + $ref: '#/components/schemas/SpecVersion' + id: + type: string + type: + type: string + source: + format: uri + type: string + dataContentType: + type: string + dataSchema: + format: uri + type: string + subject: + type: string + time: + format: date-time + type: string + attributeNames: + uniqueItems: true + type: array + items: + type: string + extensionNames: + uniqueItems: true + type: array + items: + type: string + data: + $ref: '#/components/schemas/CloudEventData' + CloudEventData: + type: object + EntityTag: + type: object + properties: + value: + type: string + weak: + type: boolean + Family: + enum: + - INFORMATIONAL + - SUCCESSFUL + - REDIRECTION + - CLIENT_ERROR + - SERVER_ERROR + - OTHER + type: string + Link: + type: object + properties: + uri: + format: uri + type: string + uriBuilder: + $ref: '#/components/schemas/UriBuilder' + rel: + type: string + rels: + type: array + items: + type: string + title: + type: string + type: + type: string + params: + type: object + additionalProperties: + type: string + Locale: + type: object + properties: + language: + type: string + script: + type: string + country: + type: string + variant: + type: string + extensionKeys: + uniqueItems: true + type: array + items: + format: byte + type: string + unicodeLocaleAttributes: + uniqueItems: true + type: array + items: + type: string + unicodeLocaleKeys: + uniqueItems: true + type: array + items: + type: string + iSO3Language: + type: string + iSO3Country: + type: string + displayLanguage: + type: string + displayScript: + type: string + displayCountry: + type: string + displayVariant: + type: string + displayName: + type: string + MediaType: + type: object + properties: + type: + type: string + subtype: + type: string + parameters: + type: object + additionalProperties: + type: string + wildcardType: + type: boolean + wildcardSubtype: + type: boolean + MultivaluedMapStringObject: + type: object + additionalProperties: + type: array + items: + type: object + MultivaluedMapStringString: + type: object + additionalProperties: + type: array + items: + type: string + NewCookie: + type: object + properties: + name: + type: string + value: + type: string + version: + format: int32 + type: integer + path: + type: string + domain: + type: string + comment: + type: string + maxAge: + format: int32 + type: integer + expiry: + format: date + type: string + secure: + type: boolean + httpOnly: + type: boolean + Response: + type: object + properties: + status: + format: int32 + type: integer + statusInfo: + $ref: '#/components/schemas/StatusType' + entity: + type: object + mediaType: + $ref: '#/components/schemas/MediaType' + language: + $ref: '#/components/schemas/Locale' + length: + format: int32 + type: integer + allowedMethods: + uniqueItems: true + type: array + items: + type: string + cookies: + type: object + additionalProperties: + $ref: '#/components/schemas/NewCookie' + entityTag: + $ref: '#/components/schemas/EntityTag' + date: + format: date + type: string + lastModified: + format: date + type: string + location: + format: uri + type: string + links: + uniqueItems: true + type: array + items: + $ref: '#/components/schemas/Link' + metadata: + $ref: '#/components/schemas/MultivaluedMapStringObject' + headers: + $ref: '#/components/schemas/MultivaluedMapStringObject' + stringHeaders: + $ref: '#/components/schemas/MultivaluedMapStringString' + SpecVersion: + enum: + - V03 + - V1 + type: string + StatusType: + type: object + properties: + statusCode: + format: int32 + type: integer + family: + $ref: '#/components/schemas/Family' + reasonPhrase: + type: string + UriBuilder: + type: object diff --git a/client/integration-tests/return-response/src/main/openapi/mutiny-multi-return-response-true-string-simple-openapi.yaml b/client/integration-tests/return-response/src/main/openapi/mutiny-multi-return-response-true-string-simple-openapi.yaml new file mode 100644 index 00000000..5963ec54 --- /dev/null +++ b/client/integration-tests/return-response/src/main/openapi/mutiny-multi-return-response-true-string-simple-openapi.yaml @@ -0,0 +1,274 @@ +--- +openapi: 3.0.3 +info: + title: greeting-flow API + version: "1.0" +paths: + /: + post: + requestBody: + content: + '*/*': + schema: + $ref: '#/components/schemas/CloudEvent' + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/Response' + /hello: + get: + tags: + - MutinyMultiReturnResponseTrueString + operationId: hello + responses: + "200": + description: OK + content: + text/plain: + schema: + type: string + /messaging/topics: + get: + tags: + - Quarkus Topics Information Resource + responses: + "200": + description: OK +components: + schemas: + CloudEvent: + type: object + properties: + specVersion: + $ref: '#/components/schemas/SpecVersion' + id: + type: string + type: + type: string + source: + format: uri + type: string + dataContentType: + type: string + dataSchema: + format: uri + type: string + subject: + type: string + time: + format: date-time + type: string + attributeNames: + uniqueItems: true + type: array + items: + type: string + extensionNames: + uniqueItems: true + type: array + items: + type: string + data: + $ref: '#/components/schemas/CloudEventData' + CloudEventData: + type: object + EntityTag: + type: object + properties: + value: + type: string + weak: + type: boolean + Family: + enum: + - INFORMATIONAL + - SUCCESSFUL + - REDIRECTION + - CLIENT_ERROR + - SERVER_ERROR + - OTHER + type: string + Link: + type: object + properties: + uri: + format: uri + type: string + uriBuilder: + $ref: '#/components/schemas/UriBuilder' + rel: + type: string + rels: + type: array + items: + type: string + title: + type: string + type: + type: string + params: + type: object + additionalProperties: + type: string + Locale: + type: object + properties: + language: + type: string + script: + type: string + country: + type: string + variant: + type: string + extensionKeys: + uniqueItems: true + type: array + items: + format: byte + type: string + unicodeLocaleAttributes: + uniqueItems: true + type: array + items: + type: string + unicodeLocaleKeys: + uniqueItems: true + type: array + items: + type: string + iSO3Language: + type: string + iSO3Country: + type: string + displayLanguage: + type: string + displayScript: + type: string + displayCountry: + type: string + displayVariant: + type: string + displayName: + type: string + MediaType: + type: object + properties: + type: + type: string + subtype: + type: string + parameters: + type: object + additionalProperties: + type: string + wildcardType: + type: boolean + wildcardSubtype: + type: boolean + MultivaluedMapStringObject: + type: object + additionalProperties: + type: array + items: + type: object + MultivaluedMapStringString: + type: object + additionalProperties: + type: array + items: + type: string + NewCookie: + type: object + properties: + name: + type: string + value: + type: string + version: + format: int32 + type: integer + path: + type: string + domain: + type: string + comment: + type: string + maxAge: + format: int32 + type: integer + expiry: + format: date + type: string + secure: + type: boolean + httpOnly: + type: boolean + Response: + type: object + properties: + status: + format: int32 + type: integer + statusInfo: + $ref: '#/components/schemas/StatusType' + entity: + type: object + mediaType: + $ref: '#/components/schemas/MediaType' + language: + $ref: '#/components/schemas/Locale' + length: + format: int32 + type: integer + allowedMethods: + uniqueItems: true + type: array + items: + type: string + cookies: + type: object + additionalProperties: + $ref: '#/components/schemas/NewCookie' + entityTag: + $ref: '#/components/schemas/EntityTag' + date: + format: date + type: string + lastModified: + format: date + type: string + location: + format: uri + type: string + links: + uniqueItems: true + type: array + items: + $ref: '#/components/schemas/Link' + metadata: + $ref: '#/components/schemas/MultivaluedMapStringObject' + headers: + $ref: '#/components/schemas/MultivaluedMapStringObject' + stringHeaders: + $ref: '#/components/schemas/MultivaluedMapStringString' + SpecVersion: + enum: + - V03 + - V1 + type: string + StatusType: + type: object + properties: + statusCode: + format: int32 + type: integer + family: + $ref: '#/components/schemas/Family' + reasonPhrase: + type: string + UriBuilder: + type: object diff --git a/client/integration-tests/return-response/src/main/openapi/mutiny-multi-return-response-true-void-simple-openapi.yaml b/client/integration-tests/return-response/src/main/openapi/mutiny-multi-return-response-true-void-simple-openapi.yaml new file mode 100644 index 00000000..c3aca067 --- /dev/null +++ b/client/integration-tests/return-response/src/main/openapi/mutiny-multi-return-response-true-void-simple-openapi.yaml @@ -0,0 +1,270 @@ +--- +openapi: 3.0.3 +info: + title: greeting-flow API + version: "1.0" +paths: + /: + post: + requestBody: + content: + '*/*': + schema: + $ref: '#/components/schemas/CloudEvent' + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/Response' + /hello: + get: + tags: + - MutinyMultiReturnResponseTrueVoid + operationId: hello + responses: + "200": + description: OK + /messaging/topics: + get: + tags: + - Quarkus Topics Information Resource + responses: + "200": + description: OK +components: + schemas: + CloudEvent: + type: object + properties: + specVersion: + $ref: '#/components/schemas/SpecVersion' + id: + type: string + type: + type: string + source: + format: uri + type: string + dataContentType: + type: string + dataSchema: + format: uri + type: string + subject: + type: string + time: + format: date-time + type: string + attributeNames: + uniqueItems: true + type: array + items: + type: string + extensionNames: + uniqueItems: true + type: array + items: + type: string + data: + $ref: '#/components/schemas/CloudEventData' + CloudEventData: + type: object + EntityTag: + type: object + properties: + value: + type: string + weak: + type: boolean + Family: + enum: + - INFORMATIONAL + - SUCCESSFUL + - REDIRECTION + - CLIENT_ERROR + - SERVER_ERROR + - OTHER + type: string + Link: + type: object + properties: + uri: + format: uri + type: string + uriBuilder: + $ref: '#/components/schemas/UriBuilder' + rel: + type: string + rels: + type: array + items: + type: string + title: + type: string + type: + type: string + params: + type: object + additionalProperties: + type: string + Locale: + type: object + properties: + language: + type: string + script: + type: string + country: + type: string + variant: + type: string + extensionKeys: + uniqueItems: true + type: array + items: + format: byte + type: string + unicodeLocaleAttributes: + uniqueItems: true + type: array + items: + type: string + unicodeLocaleKeys: + uniqueItems: true + type: array + items: + type: string + iSO3Language: + type: string + iSO3Country: + type: string + displayLanguage: + type: string + displayScript: + type: string + displayCountry: + type: string + displayVariant: + type: string + displayName: + type: string + MediaType: + type: object + properties: + type: + type: string + subtype: + type: string + parameters: + type: object + additionalProperties: + type: string + wildcardType: + type: boolean + wildcardSubtype: + type: boolean + MultivaluedMapStringObject: + type: object + additionalProperties: + type: array + items: + type: object + MultivaluedMapStringString: + type: object + additionalProperties: + type: array + items: + type: string + NewCookie: + type: object + properties: + name: + type: string + value: + type: string + version: + format: int32 + type: integer + path: + type: string + domain: + type: string + comment: + type: string + maxAge: + format: int32 + type: integer + expiry: + format: date + type: string + secure: + type: boolean + httpOnly: + type: boolean + Response: + type: object + properties: + status: + format: int32 + type: integer + statusInfo: + $ref: '#/components/schemas/StatusType' + entity: + type: object + mediaType: + $ref: '#/components/schemas/MediaType' + language: + $ref: '#/components/schemas/Locale' + length: + format: int32 + type: integer + allowedMethods: + uniqueItems: true + type: array + items: + type: string + cookies: + type: object + additionalProperties: + $ref: '#/components/schemas/NewCookie' + entityTag: + $ref: '#/components/schemas/EntityTag' + date: + format: date + type: string + lastModified: + format: date + type: string + location: + format: uri + type: string + links: + uniqueItems: true + type: array + items: + $ref: '#/components/schemas/Link' + metadata: + $ref: '#/components/schemas/MultivaluedMapStringObject' + headers: + $ref: '#/components/schemas/MultivaluedMapStringObject' + stringHeaders: + $ref: '#/components/schemas/MultivaluedMapStringString' + SpecVersion: + enum: + - V03 + - V1 + type: string + StatusType: + type: object + properties: + statusCode: + format: int32 + type: integer + family: + $ref: '#/components/schemas/Family' + reasonPhrase: + type: string + UriBuilder: + type: object diff --git a/client/integration-tests/return-response/src/main/resources/application.properties b/client/integration-tests/return-response/src/main/resources/application.properties index 970c6984..0d83dd9a 100644 --- a/client/integration-tests/return-response/src/main/resources/application.properties +++ b/client/integration-tests/return-response/src/main/resources/application.properties @@ -14,16 +14,32 @@ quarkus.openapi-generator.codegen.spec.return_response_true_string_simple_openap quarkus.openapi-generator.codegen.spec.return_response_true_void_simple_openapi_yaml.mutiny = false quarkus.openapi-generator.codegen.spec.mutiny_return_response_false_string_simple_openapi_yaml.base-package = ${quarkus.openapi-generator.codegen.spec.return_response_false_string_simple_openapi_yaml.base-package} +quarkus.openapi-generator.codegen.spec.mutiny_multi_return_response_false_string_simple_openapi_yaml.base-package = ${quarkus.openapi-generator.codegen.spec.return_response_false_string_simple_openapi_yaml.base-package} quarkus.openapi-generator.codegen.spec.mutiny_return_response_false_void_simple_openapi_yaml.base-package = ${quarkus.openapi-generator.codegen.spec.return_response_false_void_simple_openapi_yaml.base-package} +quarkus.openapi-generator.codegen.spec.mutiny_multi_return_response_false_void_simple_openapi_yaml.base-package = ${quarkus.openapi-generator.codegen.spec.return_response_false_void_simple_openapi_yaml.base-package} quarkus.openapi-generator.codegen.spec.mutiny_return_response_true_string_simple_openapi_yaml.base-package = ${quarkus.openapi-generator.codegen.spec.return_response_true_string_simple_openapi_yaml.base-package} +quarkus.openapi-generator.codegen.spec.mutiny_multi_return_response_true_string_simple_openapi_yaml.base-package = ${quarkus.openapi-generator.codegen.spec.return_response_true_string_simple_openapi_yaml.base-package} quarkus.openapi-generator.codegen.spec.mutiny_return_response_true_void_simple_openapi_yaml.base-package = ${quarkus.openapi-generator.codegen.spec.return_response_true_void_simple_openapi_yaml.base-package} +quarkus.openapi-generator.codegen.spec.mutiny_multi_return_response_true_void_simple_openapi_yaml.base-package = ${quarkus.openapi-generator.codegen.spec.return_response_true_void_simple_openapi_yaml.base-package} quarkus.openapi-generator.codegen.spec.mutiny_return_response_false_string_simple_openapi_yaml.return-response = ${quarkus.openapi-generator.codegen.spec.return_response_false_string_simple_openapi_yaml.return-response} +quarkus.openapi-generator.codegen.spec.mutiny_multi_return_response_false_string_simple_openapi_yaml.return-response = ${quarkus.openapi-generator.codegen.spec.multi_return_response_false_string_simple_openapi_yaml.return-response} quarkus.openapi-generator.codegen.spec.mutiny_return_response_false_void_simple_openapi_yaml.return-response = ${quarkus.openapi-generator.codegen.spec.return_response_false_void_simple_openapi_yaml.return-response} +quarkus.openapi-generator.codegen.spec.mutiny_multi_return_response_false_void_simple_openapi_yaml.return-response = ${quarkus.openapi-generator.codegen.spec.return_response_false_void_simple_openapi_yaml.return-response} quarkus.openapi-generator.codegen.spec.mutiny_return_response_true_string_simple_openapi_yaml.return-response = ${quarkus.openapi-generator.codegen.spec.return_response_true_string_simple_openapi_yaml.return-response} +quarkus.openapi-generator.codegen.spec.mutiny_multi_return_response_true_string_simple_openapi_yaml.return-response = ${quarkus.openapi-generator.codegen.spec.return_response_true_string_simple_openapi_yaml.return-response} quarkus.openapi-generator.codegen.spec.mutiny_return_response_true_void_simple_openapi_yaml.return-response = ${quarkus.openapi-generator.codegen.spec.return_response_true_void_simple_openapi_yaml.return-response} +quarkus.openapi-generator.codegen.spec.mutiny_multi_return_response_true_void_simple_openapi_yaml.return-response = ${quarkus.openapi-generator.codegen.spec.return_response_true_void_simple_openapi_yaml.return-response} quarkus.openapi-generator.codegen.spec.mutiny_return_response_false_string_simple_openapi_yaml.mutiny = true +quarkus.openapi-generator.codegen.spec.mutiny_multi_return_response_false_string_simple_openapi_yaml.mutiny = true +quarkus.openapi-generator.codegen.spec.mutiny_multi_return_response_false_string_simple_openapi_yaml.mutiny.operation-ids.hello = Multi quarkus.openapi-generator.codegen.spec.mutiny_return_response_false_void_simple_openapi_yaml.mutiny = true +quarkus.openapi-generator.codegen.spec.mutiny_multi_return_response_false_void_simple_openapi_yaml.mutiny = true +quarkus.openapi-generator.codegen.spec.mutiny_multi_return_response_false_void_simple_openapi_yaml.mutiny.operation-ids.hello = Multi quarkus.openapi-generator.codegen.spec.mutiny_return_response_true_string_simple_openapi_yaml.mutiny = true +quarkus.openapi-generator.codegen.spec.mutiny_multi_return_response_true_string_simple_openapi_yaml.mutiny = true +quarkus.openapi-generator.codegen.spec.mutiny_multi_return_response_true_string_simple_openapi_yaml.mutiny.operation-ids.hello = Multi quarkus.openapi-generator.codegen.spec.mutiny_return_response_true_void_simple_openapi_yaml.mutiny = true +quarkus.openapi-generator.codegen.spec.mutiny_multi_return_response_true_void_simple_openapi_yaml.mutiny = true +quarkus.openapi-generator.codegen.spec.mutiny_multi_return_response_true_void_simple_openapi_yaml.mutiny.operation-ids.hello = Multi diff --git a/client/integration-tests/return-response/src/test/java/io/quarkiverse/openapi/generator/it/ReturnResponseTest.java b/client/integration-tests/return-response/src/test/java/io/quarkiverse/openapi/generator/it/ReturnResponseTest.java index 52bca908..68167a97 100644 --- a/client/integration-tests/return-response/src/test/java/io/quarkiverse/openapi/generator/it/ReturnResponseTest.java +++ b/client/integration-tests/return-response/src/test/java/io/quarkiverse/openapi/generator/it/ReturnResponseTest.java @@ -4,6 +4,10 @@ import jakarta.ws.rs.core.Response; +import org.acme.openapi.api.MutinyMultiReturnResponseFalseStringApi; +import org.acme.openapi.api.MutinyMultiReturnResponseFalseVoidApi; +import org.acme.openapi.api.MutinyMultiReturnResponseTrueStringApi; +import org.acme.openapi.api.MutinyMultiReturnResponseTrueVoidApi; import org.acme.openapi.api.MutinyReturnResponseFalseStringApi; import org.acme.openapi.api.MutinyReturnResponseFalseVoidApi; import org.acme.openapi.api.MutinyReturnResponseTrueStringApi; @@ -54,6 +58,13 @@ void testMutinyReturnResponseFalseString() throws NoSuchMethodException { .isEqualTo("io.smallrye.mutiny.Uni"); } + @Test + void testMutinyMultiReturnResponseFalseString() throws NoSuchMethodException { + var method = MutinyMultiReturnResponseFalseStringApi.class.getMethod("hello"); + assertThat(method.getGenericReturnType().getTypeName()) + .isEqualTo("io.smallrye.mutiny.Multi"); + } + @Test void testMutinyReturnResponseTrueString() throws NoSuchMethodException { var method = MutinyReturnResponseTrueStringApi.class.getMethod("hello"); @@ -61,6 +72,13 @@ void testMutinyReturnResponseTrueString() throws NoSuchMethodException { .isEqualTo("io.smallrye.mutiny.Uni"); } + @Test + void testMutinyMultiReturnResponseTrueString() throws NoSuchMethodException { + var method = MutinyMultiReturnResponseTrueStringApi.class.getMethod("hello"); + assertThat(method.getGenericReturnType().getTypeName()) + .isEqualTo("io.smallrye.mutiny.Multi"); + } + @Test void testMutinyReturnResponseFalseVoid() throws NoSuchMethodException { var method = MutinyReturnResponseFalseVoidApi.class.getMethod("hello"); @@ -68,10 +86,24 @@ void testMutinyReturnResponseFalseVoid() throws NoSuchMethodException { .isEqualTo("io.smallrye.mutiny.Uni"); } + @Test + void testMutinyMultiReturnResponseFalseVoid() throws NoSuchMethodException { + var method = MutinyMultiReturnResponseFalseVoidApi.class.getMethod("hello"); + assertThat(method.getGenericReturnType().getTypeName()) + .isEqualTo("io.smallrye.mutiny.Multi"); + } + @Test void testMutinyReturnResponseTrueVoid() throws NoSuchMethodException { var method = MutinyReturnResponseTrueVoidApi.class.getMethod("hello"); assertThat(method.getGenericReturnType().getTypeName()) .isEqualTo("io.smallrye.mutiny.Uni"); } + + @Test + void testMutinyMultiReturnResponseTrueVoid() throws NoSuchMethodException { + var method = MutinyMultiReturnResponseTrueVoidApi.class.getMethod("hello"); + assertThat(method.getGenericReturnType().getTypeName()) + .isEqualTo("io.smallrye.mutiny.Multi"); + } } diff --git a/docs/modules/ROOT/pages/includes/resteasy-support.adoc b/docs/modules/ROOT/pages/includes/resteasy-support.adoc index 943c6aa5..ae294107 100644 --- a/docs/modules/ROOT/pages/includes/resteasy-support.adoc +++ b/docs/modules/ROOT/pages/includes/resteasy-support.adoc @@ -31,6 +31,33 @@ will wrap all API return types in a `io.smallrye.mutiny.Uni`. quarkus.openapi-generator.codegen.spec.my_openapi_yaml.mutiny=true ---- +=== Configuring Return Types for Specific Operations + +In cases where you need more granular control over the return types of specific OpenAPI operations, you can configure individual operations to return either a `Uni` or a `Multi`. By default, when `mutiny=true` is enabled, all API methods will return a `Uni`. However, if you have operations that should return multiple items reactively, you can specify either `Multi` or `Uni` for those operations. + +To achieve this, use the `mutiny.operation-ids` configuration to set the return type for each operation by its `operationId` as defined in the OpenAPI specification. + +For example: + +[source,properties] +---- +# Enable Mutiny support for all operations +quarkus.openapi-generator.codegen.spec.my_openapi_yaml.mutiny=true + +# Configure return type for specific operation IDs +quarkus.openapi-generator.codegen.spec.my_openapi_yaml.mutiny.operation-ids.addPet=Uni +quarkus.openapi-generator.codegen.spec.my_openapi_yaml.mutiny.operation-ids.updatePet=Multi +---- + +In this example: + +* The `addPet` operation will return a `Uni`. +* The `updatePet` operation will return a `Multi`. + +This allows fine-grained control over which operations are expected to return a single result (`Uni`) and which should handle streams of results (`Multi`). + +WARNING: If an incorrect or unsupported return type is specified for an `mutiny.operation-ids`, the generator will fallback to returning a `Uni` by default. Ensure that the return type for each operation is either `Uni` or `Multi` to avoid unintended behavior. + When using RESTEasy Reactive: * The client must not declare multiple MIME-TYPES with `@Consumes`