From d8b0dbb432ad2f37db2c13fcc0b208128c259466 Mon Sep 17 00:00:00 2001 From: Georgios Andrianakis Date: Wed, 22 Sep 2021 14:52:28 +0300 Subject: [PATCH] Support CompletableFuture as a return type of RESTEasy Reactive Resource methods Fixes: #20207 (cherry picked from commit d376f1edf155a35c75d6197a61765bad80fad07f) --- .../test/simple/SimpleQuarkusRestResource.java | 14 ++++++++++++++ .../test/simple/SimpleQuarkusRestTestCase.java | 5 +++++ .../common/processor/EndpointIndexer.java | 2 ++ .../processor/ResteasyReactiveDotNames.java | 4 ++++ .../scanning/AsyncReturnTypeScanner.java | 16 +++++++--------- 5 files changed, 32 insertions(+), 9 deletions(-) diff --git a/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/test/java/io/quarkus/resteasy/reactive/server/test/simple/SimpleQuarkusRestResource.java b/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/test/java/io/quarkus/resteasy/reactive/server/test/simple/SimpleQuarkusRestResource.java index e847095bb96f4..0e04ce42ea58e 100644 --- a/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/test/java/io/quarkus/resteasy/reactive/server/test/simple/SimpleQuarkusRestResource.java +++ b/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/test/java/io/quarkus/resteasy/reactive/server/test/simple/SimpleQuarkusRestResource.java @@ -246,6 +246,20 @@ public CompletionStage asyncCompletionStageFail() { return ret; } + @GET + @Path("async/cf/ok") + public CompletableFuture asyncCompletableFutureOK() { + return CompletableFuture.completedFuture("CF-OK"); + } + + @GET + @Path("async/cf/fail") + public CompletableFuture asyncCompletableFutureFail() { + CompletableFuture ret = new CompletableFuture<>(); + ret.completeExceptionally(new TestException()); + return ret; + } + @GET @Path("async/uni/ok") public Uni asyncUniOK() { diff --git a/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/test/java/io/quarkus/resteasy/reactive/server/test/simple/SimpleQuarkusRestTestCase.java b/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/test/java/io/quarkus/resteasy/reactive/server/test/simple/SimpleQuarkusRestTestCase.java index ece6f57e522ce..956e335d955c6 100644 --- a/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/test/java/io/quarkus/resteasy/reactive/server/test/simple/SimpleQuarkusRestTestCase.java +++ b/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/test/java/io/quarkus/resteasy/reactive/server/test/simple/SimpleQuarkusRestTestCase.java @@ -193,6 +193,11 @@ public void testAsync() { RestAssured.get("/simple/async/cs/fail") .then().body(Matchers.equalTo("OK")) .statusCode(666); + RestAssured.get("/simple/async/cf/ok") + .then().body(Matchers.equalTo("CF-OK")); + RestAssured.get("/simple/async/cf/fail") + .then().body(Matchers.equalTo("OK")) + .statusCode(666); RestAssured.get("/simple/async/uni/ok") .then().body(Matchers.equalTo("UNI-OK")); RestAssured.get("/simple/async/uni/fail") diff --git a/independent-projects/resteasy-reactive/common/processor/src/main/java/org/jboss/resteasy/reactive/common/processor/EndpointIndexer.java b/independent-projects/resteasy-reactive/common/processor/src/main/java/org/jboss/resteasy/reactive/common/processor/EndpointIndexer.java index 79fd7953eb808..81c7c72c5f4fb 100644 --- a/independent-projects/resteasy-reactive/common/processor/src/main/java/org/jboss/resteasy/reactive/common/processor/EndpointIndexer.java +++ b/independent-projects/resteasy-reactive/common/processor/src/main/java/org/jboss/resteasy/reactive/common/processor/EndpointIndexer.java @@ -6,6 +6,7 @@ import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.BLOCKING; import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.BOOLEAN; import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.CHARACTER; +import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.COMPLETABLE_FUTURE; import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.COMPLETION_STAGE; import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.CONSUMES; import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.CONTEXT; @@ -685,6 +686,7 @@ private Type getNonAsyncReturnType(Type returnType) { // NOTE: same code in RuntimeResourceDeployment.getNonAsyncReturnType ParameterizedType parameterizedType = returnType.asParameterizedType(); if (COMPLETION_STAGE.equals(parameterizedType.name()) + || COMPLETABLE_FUTURE.equals(parameterizedType.name()) || UNI.equals(parameterizedType.name()) || MULTI.equals(parameterizedType.name()) || REST_RESPONSE.equals(parameterizedType.name())) { diff --git a/independent-projects/resteasy-reactive/common/processor/src/main/java/org/jboss/resteasy/reactive/common/processor/ResteasyReactiveDotNames.java b/independent-projects/resteasy-reactive/common/processor/src/main/java/org/jboss/resteasy/reactive/common/processor/ResteasyReactiveDotNames.java index 2cf5287725461..17037ea64bc0c 100644 --- a/independent-projects/resteasy-reactive/common/processor/src/main/java/org/jboss/resteasy/reactive/common/processor/ResteasyReactiveDotNames.java +++ b/independent-projects/resteasy-reactive/common/processor/src/main/java/org/jboss/resteasy/reactive/common/processor/ResteasyReactiveDotNames.java @@ -17,6 +17,7 @@ import java.util.Optional; import java.util.Set; import java.util.SortedSet; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; import javax.annotation.Priority; import javax.enterprise.context.ApplicationScoped; @@ -84,6 +85,7 @@ import org.jboss.resteasy.reactive.RestQuery; import org.jboss.resteasy.reactive.RestResponse; import org.jboss.resteasy.reactive.RestSseElementType; +import org.reactivestreams.Publisher; public final class ResteasyReactiveDotNames { @@ -176,6 +178,8 @@ public final class ResteasyReactiveDotNames { public static final DotName UNI = DotName.createSimple(Uni.class.getName()); public static final DotName MULTI = DotName.createSimple(Multi.class.getName()); public static final DotName COMPLETION_STAGE = DotName.createSimple(CompletionStage.class.getName()); + public static final DotName COMPLETABLE_FUTURE = DotName.createSimple(CompletableFuture.class.getName()); + public static final DotName PUBLISHER = DotName.createSimple(Publisher.class.getName()); public static final DotName REST_RESPONSE = DotName.createSimple(RestResponse.class.getName()); public static final DotName INTEGER = DotName.createSimple(Integer.class.getName()); diff --git a/independent-projects/resteasy-reactive/server/processor/src/main/java/org/jboss/resteasy/reactive/server/processor/scanning/AsyncReturnTypeScanner.java b/independent-projects/resteasy-reactive/server/processor/src/main/java/org/jboss/resteasy/reactive/server/processor/scanning/AsyncReturnTypeScanner.java index b8285a0b28af9..132202bfa5146 100644 --- a/independent-projects/resteasy-reactive/server/processor/src/main/java/org/jboss/resteasy/reactive/server/processor/scanning/AsyncReturnTypeScanner.java +++ b/independent-projects/resteasy-reactive/server/processor/src/main/java/org/jboss/resteasy/reactive/server/processor/scanning/AsyncReturnTypeScanner.java @@ -1,11 +1,14 @@ package org.jboss.resteasy.reactive.server.processor.scanning; -import io.smallrye.mutiny.Multi; -import io.smallrye.mutiny.Uni; +import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.COMPLETABLE_FUTURE; +import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.COMPLETION_STAGE; +import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.MULTI; +import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.PUBLISHER; +import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.UNI; + import java.util.Collections; import java.util.List; import java.util.Map; -import java.util.concurrent.CompletionStage; import org.jboss.jandex.ClassInfo; import org.jboss.jandex.DotName; import org.jboss.jandex.MethodInfo; @@ -14,19 +17,14 @@ import org.jboss.resteasy.reactive.server.handlers.UniResponseHandler; import org.jboss.resteasy.reactive.server.model.FixedHandlerChainCustomizer; import org.jboss.resteasy.reactive.server.model.HandlerChainCustomizer; -import org.reactivestreams.Publisher; public class AsyncReturnTypeScanner implements MethodScanner { - private static final DotName COMPLETION_STAGE = DotName.createSimple(CompletionStage.class.getName()); - private static final DotName UNI = DotName.createSimple(Uni.class.getName()); - private static final DotName MULTI = DotName.createSimple(Multi.class.getName()); - private static final DotName PUBLISHER = DotName.createSimple(Publisher.class.getName()); @Override public List scan(MethodInfo method, ClassInfo actualEndpointClass, Map methodContext) { DotName returnTypeName = method.returnType().name(); - if (returnTypeName.equals(COMPLETION_STAGE)) { + if (returnTypeName.equals(COMPLETION_STAGE) || returnTypeName.equals(COMPLETABLE_FUTURE)) { return Collections.singletonList(new FixedHandlerChainCustomizer(new CompletionStageResponseHandler(), HandlerChainCustomizer.Phase.AFTER_METHOD_INVOKE)); } else if (returnTypeName.equals(UNI)) {