From 477d0657a1988f43eac74307f51a5f611aabbbd3 Mon Sep 17 00:00:00 2001 From: pablo gonzalez granados Date: Sat, 14 Jan 2023 13:47:59 +0100 Subject: [PATCH] Improve reactive rest client "process paths before sub resources" scenario There is an issue in upstream (https://github.com/quarkusio/quarkus/pull/29821) that only happens under some RestClient definition hierarchy. This commit reproduces the problem in Quarkus 2.12 and earlier versions --- .../reactive/PlainRootResource.java | 51 ------------------- .../reactive/ReactiveClientRootResource.java | 25 --------- .../ResourceAndSubResourcesClient.java | 40 +++++++++++++++ .../reactive/SubResourcesClient.java | 38 -------------- .../{ => resources}/PlainBookResource.java | 2 +- .../resources/PlainComplexClientResource.java | 43 ++++++++++++++++ .../ReactiveClientBookResource.java | 3 +- .../ReactivecomplexClientResource.java | 14 +++++ .../src/main/resources/modern.properties | 2 +- .../reactive/ReactiveRestClientIT.java | 20 +++++--- 10 files changed, 113 insertions(+), 125 deletions(-) delete mode 100644 http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/PlainRootResource.java delete mode 100644 http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/ReactiveClientRootResource.java create mode 100644 http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/ResourceAndSubResourcesClient.java delete mode 100644 http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/SubResourcesClient.java rename http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/{ => resources}/PlainBookResource.java (98%) create mode 100644 http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/resources/PlainComplexClientResource.java rename http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/{ => resources}/ReactiveClientBookResource.java (97%) create mode 100644 http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/resources/ReactivecomplexClientResource.java diff --git a/http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/PlainRootResource.java b/http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/PlainRootResource.java deleted file mode 100644 index 837ba4e95d..0000000000 --- a/http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/PlainRootResource.java +++ /dev/null @@ -1,51 +0,0 @@ -package io.quarkus.ts.http.restclient.reactive; - -import java.net.URI; -import java.net.URISyntaxException; - -import javax.inject.Inject; -import javax.ws.rs.Consumes; -import javax.ws.rs.GET; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; -import javax.ws.rs.QueryParam; -import javax.ws.rs.core.MediaType; - -import org.eclipse.microprofile.rest.client.RestClientBuilder; -import org.eclipse.microprofile.rest.client.inject.RestClient; -import org.jboss.resteasy.reactive.RestPath; - -@Path("/plain-root/{rootParam}") -@Consumes("text/plain") -@Produces("text/plain") -public class PlainRootResource { - - @Inject - @RestClient - SubResourcesClient subResourcesClient; - - @GET - @Path("{method}/{param2}/{param3}") - @Produces(MediaType.TEXT_PLAIN) - public String getSubResource( - @RestPath("rootParam") String rootParam, - @RestPath("method") String method, - @RestPath("param2") String param2, - @RestPath("param3") String param3) { - return subResourcesClient.sub(rootParam, method).sub(param2).get(param3); - } - - @GET - @Path("/manualClient/{method}/{param2}/{param3}") - @Produces(MediaType.TEXT_PLAIN) - public String getSubResourceManualClient( - @PathParam("rootParam") String rootParam, - @PathParam("method") String method, - @PathParam("param2") String param2, - @PathParam("param3") String param3, - @QueryParam("baseUri") String baseUri) throws URISyntaxException { - SubResourcesClient rClient = RestClientBuilder.newBuilder().baseUri(new URI(baseUri)).build(SubResourcesClient.class); - return rClient.sub(rootParam, method).sub(param2).get(param3); - } -} diff --git a/http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/ReactiveClientRootResource.java b/http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/ReactiveClientRootResource.java deleted file mode 100644 index 1c4fcf6421..0000000000 --- a/http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/ReactiveClientRootResource.java +++ /dev/null @@ -1,25 +0,0 @@ -package io.quarkus.ts.http.restclient.reactive; - -import javax.ws.rs.Consumes; -import javax.ws.rs.GET; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; - -import org.eclipse.microprofile.rest.client.annotation.ClientHeaderParam; - -@Path("/root") -@Consumes("text/plain") -@Produces("text/plain") -@ClientHeaderParam(name = "fromRoot", value = "headerValue") -@ClientHeaderParam(name = "overridable", value = "RootClient") -public class ReactiveClientRootResource { - - @GET - @Path("{part1}/{part2}/{part3}/{part4}/{part5}") - public String getUriParts(@PathParam("part1") String part1, @PathParam("part2") String part2, - @PathParam("part3") String part3, @PathParam("part4") String part4, - @PathParam("part5") String part5) { - return String.format("%s/%s/%s/%s/%s", part1, part2, part3, part4, part5); - } -} diff --git a/http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/ResourceAndSubResourcesClient.java b/http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/ResourceAndSubResourcesClient.java new file mode 100644 index 0000000000..357eb92319 --- /dev/null +++ b/http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/ResourceAndSubResourcesClient.java @@ -0,0 +1,40 @@ +package io.quarkus.ts.http.restclient.reactive; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +import org.eclipse.microprofile.rest.client.annotation.RegisterClientHeaders; +import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; + +@RegisterRestClient +@RegisterClientHeaders +@Consumes(MediaType.TEXT_PLAIN) +@Produces(MediaType.TEXT_PLAIN) +public interface ResourceAndSubResourcesClient { + @Path("clients") + ClientsResource clients(); + + interface ClientsResource { + @Path("{id}") + ClientResource get(@PathParam("id") String id); + } + + interface ClientResource { + @Path("/resource-server") + SubResource sub(); + } + + interface leafResource { + @DELETE + String remove(); + } + + interface SubResource { + @Path("{id}") + leafResource findById(@PathParam("id") String id); + } +} diff --git a/http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/SubResourcesClient.java b/http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/SubResourcesClient.java deleted file mode 100644 index 456fb4fd13..0000000000 --- a/http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/SubResourcesClient.java +++ /dev/null @@ -1,38 +0,0 @@ -package io.quarkus.ts.http.restclient.reactive; - -import javax.ws.rs.Consumes; -import javax.ws.rs.GET; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; -import javax.ws.rs.core.MediaType; - -import org.eclipse.microprofile.rest.client.annotation.RegisterClientHeaders; -import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; - -@RegisterRestClient -@Path("/root/{rootParam}") -@RegisterClientHeaders -@Consumes(MediaType.TEXT_PLAIN) -@Produces(MediaType.TEXT_PLAIN) -public interface SubResourcesClient { - - @Path("/{param1}") - SubClient sub(@PathParam("rootParam") String rootParam, @PathParam("param1") String param1); - - @Consumes("text/plain") - @Produces("text/plain") - interface SubClient { - @Path("/sub/{param2}") - SubSubClient sub(@PathParam("param2") String param2); - } - - @Consumes("text/plain") - @Produces("text/plain") - interface SubSubClient { - - @GET - @Path("/{param3}") - String get(@PathParam("param3") String param3); - } -} diff --git a/http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/PlainBookResource.java b/http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/resources/PlainBookResource.java similarity index 98% rename from http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/PlainBookResource.java rename to http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/resources/PlainBookResource.java index 19571a3a3b..39d3d075e5 100644 --- a/http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/PlainBookResource.java +++ b/http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/resources/PlainBookResource.java @@ -1,4 +1,4 @@ -package io.quarkus.ts.http.restclient.reactive; +package io.quarkus.ts.http.restclient.reactive.resources; import java.util.ArrayList; import java.util.List; diff --git a/http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/resources/PlainComplexClientResource.java b/http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/resources/PlainComplexClientResource.java new file mode 100644 index 0000000000..3b1a8a2780 --- /dev/null +++ b/http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/resources/PlainComplexClientResource.java @@ -0,0 +1,43 @@ +package io.quarkus.ts.http.restclient.reactive.resources; + +import java.net.URI; +import java.net.URISyntaxException; + +import javax.inject.Inject; +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; + +import org.apache.commons.lang3.StringUtils; +import org.eclipse.microprofile.rest.client.RestClientBuilder; +import org.eclipse.microprofile.rest.client.inject.RestClient; + +import io.quarkus.ts.http.restclient.reactive.ResourceAndSubResourcesClient; + +@Path("clients/{clientId}/clientResource") +@Consumes("text/plain") +@Produces("text/plain") +public class PlainComplexClientResource { + @Inject + @RestClient + ResourceAndSubResourcesClient resourceAndSubResourcesClient; + + @DELETE + @Path("/{id}") + @Produces(MediaType.TEXT_PLAIN) + public String deleteClientResource(@PathParam("clientId") String rootParam, + @PathParam("id") String id, + @QueryParam("baseUri") String baseUri) throws URISyntaxException { + if (!StringUtils.isEmpty(baseUri)) { + ResourceAndSubResourcesClient rClient = RestClientBuilder.newBuilder().baseUri(new URI(baseUri)) + .build(ResourceAndSubResourcesClient.class); + return rClient.clients().get(rootParam).sub().findById(id).remove(); + } + + return resourceAndSubResourcesClient.clients().get(rootParam).sub().findById(id).remove(); + } +} diff --git a/http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/ReactiveClientBookResource.java b/http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/resources/ReactiveClientBookResource.java similarity index 97% rename from http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/ReactiveClientBookResource.java rename to http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/resources/ReactiveClientBookResource.java index 466a1f426f..d5b4e1ffe8 100644 --- a/http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/ReactiveClientBookResource.java +++ b/http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/resources/ReactiveClientBookResource.java @@ -1,4 +1,4 @@ -package io.quarkus.ts.http.restclient.reactive; +package io.quarkus.ts.http.restclient.reactive.resources; import java.util.List; import java.util.Map; @@ -14,6 +14,7 @@ import org.eclipse.microprofile.rest.client.inject.RestClient; +import io.quarkus.ts.http.restclient.reactive.BookClient; import io.quarkus.ts.http.restclient.reactive.json.Book; import io.quarkus.ts.http.restclient.reactive.json.BookIdWrapper; import io.quarkus.ts.http.restclient.reactive.json.IdBeanParam; diff --git a/http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/resources/ReactivecomplexClientResource.java b/http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/resources/ReactivecomplexClientResource.java new file mode 100644 index 0000000000..d8413987e4 --- /dev/null +++ b/http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/resources/ReactivecomplexClientResource.java @@ -0,0 +1,14 @@ +package io.quarkus.ts.http.restclient.reactive.resources; + +import javax.ws.rs.DELETE; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; + +@Path("/clients/{rootPath}/resource-server") +public class ReactivecomplexClientResource { + @Path("/{id}") + @DELETE + public String deleteById(@PathParam("rootPath") String rootPath, @PathParam("id") String id) { + return "/clients/" + rootPath + "/resource-server/" + id; + } +} diff --git a/http/rest-client-reactive/src/main/resources/modern.properties b/http/rest-client-reactive/src/main/resources/modern.properties index bee98811e4..4f9f899f68 100644 --- a/http/rest-client-reactive/src/main/resources/modern.properties +++ b/http/rest-client-reactive/src/main/resources/modern.properties @@ -3,7 +3,7 @@ quarkus.rest-client."io.quarkus.ts.http.restclient.reactive.json.JsonRestInterfa quarkus.rest-client."io.quarkus.ts.http.restclient.reactive.files.FileClient".url=http://localhost:${quarkus.http.port} quarkus.rest-client."io.quarkus.ts.http.restclient.reactive.BookClient".url=http://localhost:${quarkus.http.port} quarkus.rest-client."io.quarkus.ts.http.restclient.reactive.BookClient.AuthorClient".url=http://localhost:${quarkus.http.port} -quarkus.rest-client."io.quarkus.ts.http.restclient.reactive.SubResourcesClient".url=http://localhost:${quarkus.http.port} +quarkus.rest-client."io.quarkus.ts.http.restclient.reactive.ResourceAndSubResourcesClient".url=http://localhost:${quarkus.http.port} quarkus.rest-client.logging.scope=request-response quarkus.log.category."org.jboss.resteasy.reactive.client.logging".level=DEBUG diff --git a/http/rest-client-reactive/src/test/java/io/quarkus/ts/http/restclient/reactive/ReactiveRestClientIT.java b/http/rest-client-reactive/src/test/java/io/quarkus/ts/http/restclient/reactive/ReactiveRestClientIT.java index f331c6b949..6cf4665ea7 100644 --- a/http/rest-client-reactive/src/test/java/io/quarkus/ts/http/restclient/reactive/ReactiveRestClientIT.java +++ b/http/rest-client-reactive/src/test/java/io/quarkus/ts/http/restclient/reactive/ReactiveRestClientIT.java @@ -1,15 +1,18 @@ package io.quarkus.ts.http.restclient.reactive; -import static io.quarkus.ts.http.restclient.reactive.PlainBookResource.SEARCH_TERM_VAL; +import static io.quarkus.ts.http.restclient.reactive.resources.PlainBookResource.SEARCH_TERM_VAL; import static org.hamcrest.Matchers.nullValue; import static org.junit.jupiter.api.Assertions.assertEquals; +import java.util.UUID; + import org.apache.http.HttpStatus; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.DisabledOnOs; import org.junit.jupiter.api.condition.OS; +import io.quarkus.test.bootstrap.Protocol; import io.quarkus.test.bootstrap.RestService; import io.quarkus.test.scenarios.QuarkusScenario; import io.quarkus.test.scenarios.annotations.DisabledOnQuarkusVersion; @@ -201,23 +204,24 @@ public void checkSuffixPriority() { @Tag("QUARKUS-2741") @Test public void checkProcessPathBeforeSubResources() { - // should result in sending GET root/method/sub/sub/subsub - String result = app.given().get("/plain-root/root/method/sub/subsub").then() + final String randomId = UUID.randomUUID().toString(); + String result = app.given().delete("clients/myRealm/clientResource/" + randomId).then() .statusCode(HttpStatus.SC_OK) .extract().asString(); - assertEquals("root/method/sub/sub/subsub", result); + assertEquals("/clients/myRealm/resource-server/" + randomId, result); } @Tag("QUARKUS-2741") @Test public void checkProcessPathBeforeSubResourcesManualRestClientBuild() { - String baseUri = String.format("http://%s:%s", app.getURI().getHost(), "" + app.getURI().getPort()); - // should result in sending GET root/method/sub/sub/subsub - String result = app.given().get("/plain-root/root/manualClient/method/sub/subsub?baseUri=" + baseUri).then() + final String randomId = UUID.randomUUID().toString(); + String baseUri = String.format("%s:%s", app.getURI(Protocol.HTTP).getRestAssuredStyleUri(), + "" + app.getURI().getPort()); + String result = app.given().delete("clients/myRealm/clientResource/" + randomId + "/?baseUri=" + baseUri).then() .statusCode(HttpStatus.SC_OK) .extract().asString(); - assertEquals("root/method/sub/sub/subsub", result); + assertEquals("/clients/myRealm/resource-server/" + randomId, result); } }