From d59530a38faa30b40bb1f38c703164268489e0aa Mon Sep 17 00:00:00 2001 From: Georgios Andrianakis Date: Wed, 21 Jul 2021 09:11:29 +0300 Subject: [PATCH] Make REST Client Reactive work with Mutiny retry Fixes: #17145 --- .../resteasy/reactive/client/impl/UniInvoker.java | 9 ++++++++- .../rest/client/main/ClientCallingResource.java | 15 +++++++++++++++ .../java/io/quarkus/it/rest/client/BasicTest.java | 9 +++++++++ 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/independent-projects/resteasy-reactive/client/runtime/src/main/java/org/jboss/resteasy/reactive/client/impl/UniInvoker.java b/independent-projects/resteasy-reactive/client/runtime/src/main/java/org/jboss/resteasy/reactive/client/impl/UniInvoker.java index aebc78c36ccc1..85e34db423555 100644 --- a/independent-projects/resteasy-reactive/client/runtime/src/main/java/org/jboss/resteasy/reactive/client/impl/UniInvoker.java +++ b/independent-projects/resteasy-reactive/client/runtime/src/main/java/org/jboss/resteasy/reactive/client/impl/UniInvoker.java @@ -1,6 +1,8 @@ package org.jboss.resteasy.reactive.client.impl; import io.smallrye.mutiny.Uni; +import java.util.concurrent.CompletionStage; +import java.util.function.Supplier; import javax.ws.rs.client.Entity; import javax.ws.rs.core.GenericType; import javax.ws.rs.core.Response; @@ -16,7 +18,12 @@ public UniInvoker(InvocationBuilderImpl invocationBuilder) { @Override public Uni method(String name, Entity entity, GenericType responseType) { AsyncInvokerImpl invoker = (AsyncInvokerImpl) invocationBuilder.rx(); - return Uni.createFrom().completionStage(invoker.method(name, entity, responseType)); + return Uni.createFrom().completionStage(new Supplier>() { + @Override + public CompletionStage get() { + return invoker.method(name, entity, responseType); + } + }); } @Override diff --git a/integration-tests/resteasy-reactive-rest-client/src/main/java/io/quarkus/it/rest/client/main/ClientCallingResource.java b/integration-tests/resteasy-reactive-rest-client/src/main/java/io/quarkus/it/rest/client/main/ClientCallingResource.java index c61e336bc04fc..7dee0e453e1ee 100644 --- a/integration-tests/resteasy-reactive-rest-client/src/main/java/io/quarkus/it/rest/client/main/ClientCallingResource.java +++ b/integration-tests/resteasy-reactive-rest-client/src/main/java/io/quarkus/it/rest/client/main/ClientCallingResource.java @@ -20,6 +20,7 @@ import io.opentelemetry.sdk.testing.exporter.InMemorySpanExporter; import io.quarkus.it.rest.client.main.MyResponseExceptionMapper.MyException; import io.smallrye.mutiny.Uni; +import io.vertx.core.Future; import io.vertx.core.json.Json; import io.vertx.ext.web.Router; import io.vertx.ext.web.RoutingContext; @@ -85,6 +86,16 @@ void init(@Observes Router router) { }, t -> fail(rc, t.getMessage())); }); + router.route("/call-client-retry").blockingHandler(rc -> { + String url = rc.getBody().toString(); + AppleClient client = RestClientBuilder.newBuilder().baseUri(URI.create(url + "/does-not-exist")) + .build(AppleClient.class); + AtomicInteger count = new AtomicInteger(0); + client.uniSwapApple(new Apple("lobo")).onFailure().retry().until(t -> count.incrementAndGet() <= 3) + .subscribe() + .with(m -> success(rc, count.toString()), t -> success(rc, count.toString())); + }); + router.post("/hello").handler(rc -> rc.response().putHeader("content-type", MediaType.TEXT_PLAIN) .end("Hello, " + (rc.getBodyAsString()).repeat(getCount(rc)))); @@ -109,6 +120,10 @@ void init(@Observes Router router) { }); } + private Future success(RoutingContext rc, String body) { + return rc.response().putHeader("content-type", "text-plain").end(body); + } + private int getCount(io.vertx.ext.web.RoutingContext rc) { List countQueryParam = rc.queryParam("count"); if (countQueryParam.isEmpty()) { diff --git a/integration-tests/resteasy-reactive-rest-client/src/test/java/io/quarkus/it/rest/client/BasicTest.java b/integration-tests/resteasy-reactive-rest-client/src/test/java/io/quarkus/it/rest/client/BasicTest.java index bf21b4221d4c3..78724c6e10cc5 100644 --- a/integration-tests/resteasy-reactive-rest-client/src/test/java/io/quarkus/it/rest/client/BasicTest.java +++ b/integration-tests/resteasy-reactive-rest-client/src/test/java/io/quarkus/it/rest/client/BasicTest.java @@ -4,6 +4,7 @@ import static java.util.stream.Collectors.counting; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.entry; +import static org.hamcrest.Matchers.equalTo; import java.time.Duration; import java.util.List; @@ -55,6 +56,14 @@ void shouldMakeJsonRequest() { assertThat(valueByCount).containsOnly(entry("cortland", 3L), entry("lobo", 3L), entry("golden delicious", 3L)); } + @Test + void shouldRetryOnFailure() { + RestAssured.with().body(appleUrl).post("/call-client-retry") + .then() + .statusCode(200) + .body(equalTo("4")); + } + @Test void shouldMapException() { RestAssured.with().body(baseUrl).post("/call-client-with-exception-mapper")