Skip to content

Commit 9bb2fb7

Browse files
lordvladhbelmiro
andauthored
Introduce support for truly non-blocking APIs with resteasy-reactive and mutiny (#387)
* feat(api): return response instead of void Imagine POSTing to a resource that creates something and returns no payload but a 201 with a Location header. Right now, there is no way to get that url. After this commit, it will be possible * feat(api): support non-blocking apis Introduce a ew config property `mutiny`, which will change the Api classes to return `Uni<X>` instead of `X` for every method. This is required to make truly non-blocking api calls with quarkus-resteasy-reactive. Of course, this requires `quarkus-resteasy-reactive` on the classpath. * Update deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/SpecItemConfig.java Co-authored-by: Helber Belmiro <[email protected]> * Apply suggestions from code review Co-authored-by: Helber Belmiro <[email protected]> * Update deployment/src/main/resources/templates/api.qute Co-authored-by: Helber Belmiro <[email protected]> --------- Co-authored-by: Helber Belmiro <[email protected]>
1 parent f613c72 commit 9bb2fb7

File tree

5 files changed

+51
-4
lines changed

5 files changed

+51
-4
lines changed

README.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,12 @@ You can use the `quarkus-openapi-generator` with REST Client Classic or REST Cli
144144
</dependency>
145145
```
146146

147-
For both implementations, the generated code is always blocking code.
147+
To make truly non-blocking calls, you need to also set the `mutiny` option to `true`. This
148+
will wrap all API return types in a `io.smallrye.mutiny.Uni`.
149+
150+
```properties
151+
quarkus.openapi-generator.codegen.spec.my_openapi_yaml.mutiny=true
152+
```
148153

149154
When using RESTEasy Reactive:
150155
- The client must not declare multiple MIME-TYPES with `@Consumes`

deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/SpecItemConfig.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,4 +75,10 @@ public class SpecItemConfig {
7575
*/
7676
@ConfigItem(name = "open-api-normalizer")
7777
public Map<String, String> normalizer;
78+
79+
/**
80+
* Enable SmallRye Mutiny support. If you set this to `true`, all return types will be wrapped in `io.smallrye.mutiny.Uni`.
81+
*/
82+
@ConfigItem(name = "mutiny")
83+
public Optional<Boolean> supportMutiny;
7884
}

deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/wrapper/OpenApiClientGeneratorWrapper.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,13 @@ public OpenApiClientGeneratorWrapper withCustomRegisterProviders(String config)
113113
return this;
114114
}
115115

116+
public OpenApiClientGeneratorWrapper withMutiny(final Boolean config) {
117+
if (config != null) {
118+
configurator.addAdditionalProperty("mutiny", config);
119+
}
120+
return this;
121+
}
122+
116123
/**
117124
* Sets the global 'skipFormModel' setting. If not set this setting will default to true.
118125
*

deployment/src/main/resources/templates/api.qute

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package {package};
33
{#for imp in imports}
44
import {imp.import};
55
{/for}
6-
76
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
87
{#if hasAuthMethods || custom-register-providers.orEmpty.size > 0}
98
import org.eclipse.microprofile.rest.client.annotation.RegisterProvider;
@@ -83,10 +82,18 @@ public interface {classname} {
8382
@org.eclipse.microprofile.faulttolerance.CircuitBreaker
8483
{/if}{/for}
8584
{/if}{/for}
86-
{#if return-response}
87-
public jakarta.ws.rs.core.Response {op.nickname}(
85+
{#if mutiny}
86+
{#if return-response}
87+
public io.smallrye.mutiny.Uni<jakarta.ws.rs.core.Response> {op.nickname}(
88+
{#else}
89+
public {#if op.returnType}io.smallrye.mutiny.Uni<{op.returnType}>{#else}io.smallrye.mutiny.Uni<jakarta.ws.rs.core.Response>{/if} {op.nickname}(
90+
{/if}
8891
{#else}
92+
{#if return-response}
93+
public jakarta.ws.rs.core.Response {op.nickname}(
94+
{#else}
8995
public {#if op.returnType}{op.returnType}{#else}jakarta.ws.rs.core.Response{/if} {op.nickname}(
96+
{/if}
9097
{/if}
9198
{#if op.hasFormParams}
9299
{#if is-resteasy-reactive}

deployment/src/test/java/io/quarkiverse/openapi/generator/deployment/wrapper/OpenApiClientGeneratorWrapperTest.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,28 @@ void withoutAnyTypeOrImportMappingsItShouldGenerateUsingJava8DatesAndTimes()
387387
.contains("java.time.LocalDate", "java.time.OffsetDateTime");
388388
}
389389

390+
@Test
391+
void shouldBeAbleToEnableMutiny() throws URISyntaxException, FileNotFoundException {
392+
List<File> generatedFiles = createGeneratorWrapper("simple-openapi.json")
393+
.withMutiny(true)
394+
.generate("org.mutiny.enabled");
395+
396+
Optional<File> file = generatedFiles.stream()
397+
.filter(f -> f.getName().endsWith("DefaultApi.java"))
398+
.findAny();
399+
assertThat(file).isNotEmpty();
400+
CompilationUnit compilationUnit = StaticJavaParser.parse(file.orElseThrow());
401+
List<MethodDeclaration> methodDeclarations = compilationUnit.findAll(MethodDeclaration.class);
402+
assertThat(methodDeclarations).isNotEmpty();
403+
404+
methodDeclarations.forEach(m -> {
405+
var returnType = m.getType().toString();
406+
assertTrue(returnType.startsWith("io.smallrye.mutiny.Uni<"));
407+
assertTrue(returnType.endsWith(">"));
408+
});
409+
410+
}
411+
390412
@Test
391413
void shouldBeAbleToAddCustomDateAndTimeMappings() throws URISyntaxException, FileNotFoundException {
392414
List<File> generatedFiles = createGeneratorWrapper("datetime-regression.yml")

0 commit comments

Comments
 (0)