From 6862185829e5a7d381b872aef5480a7b8075ff01 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 happends under some RestClient definition hierarchy. This commit reproduces the problem in Quarkus 2.12 and earlier versions --- .../reactive/AuthorizationResource.java | 8 +++ .../restclient/reactive/ClientResource.java | 10 ++++ .../restclient/reactive/ClientsResource.java | 9 ++++ .../reactive/PermissionsResource.java | 8 +++ .../reactive/PlainRootResource.java | 51 ------------------- .../reactive/ReactiveClientRootResource.java | 25 --------- .../restclient/reactive/RealmResource.java | 18 +++++++ .../reactive/ResourcePermissionResource.java | 8 +++ .../reactive/ResourcePermissionsResource.java | 9 ++++ .../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 | 12 +++-- 16 files changed, 138 insertions(+), 122 deletions(-) create mode 100644 http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/AuthorizationResource.java create mode 100644 http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/ClientResource.java create mode 100644 http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/ClientsResource.java create mode 100644 http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/PermissionsResource.java 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/RealmResource.java create mode 100644 http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/ResourcePermissionResource.java create mode 100644 http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/ResourcePermissionsResource.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/AuthorizationResource.java b/http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/AuthorizationResource.java new file mode 100644 index 0000000000..78cf2a8cd4 --- /dev/null +++ b/http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/AuthorizationResource.java @@ -0,0 +1,8 @@ +package io.quarkus.ts.http.restclient.reactive; + +import javax.ws.rs.Path; + +public interface AuthorizationResource { + @Path("/permission") + PermissionsResource permissions(); +} diff --git a/http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/ClientResource.java b/http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/ClientResource.java new file mode 100644 index 0000000000..513ed0a8d0 --- /dev/null +++ b/http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/ClientResource.java @@ -0,0 +1,10 @@ +package io.quarkus.ts.http.restclient.reactive; + +import javax.ws.rs.Path; + +public interface ClientResource { + + @Path("/authz/resource-server") + AuthorizationResource authorization(); + +} diff --git a/http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/ClientsResource.java b/http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/ClientsResource.java new file mode 100644 index 0000000000..33f0490935 --- /dev/null +++ b/http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/ClientsResource.java @@ -0,0 +1,9 @@ +package io.quarkus.ts.http.restclient.reactive; + +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; + +public interface ClientsResource { + @Path("{id}") + ClientResource get(@PathParam("id") String id); +} diff --git a/http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/PermissionsResource.java b/http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/PermissionsResource.java new file mode 100644 index 0000000000..6c39dfa91d --- /dev/null +++ b/http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/PermissionsResource.java @@ -0,0 +1,8 @@ +package io.quarkus.ts.http.restclient.reactive; + +import javax.ws.rs.Path; + +public interface PermissionsResource { + @Path("resource") + ResourcePermissionsResource resource(); +} 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/RealmResource.java b/http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/RealmResource.java new file mode 100644 index 0000000000..9bb0b27056 --- /dev/null +++ b/http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/RealmResource.java @@ -0,0 +1,18 @@ +package io.quarkus.ts.http.restclient.reactive; + +import javax.ws.rs.Consumes; +import javax.ws.rs.Path; +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 RealmResource { + @Path("clients") + ClientsResource clients(); +} diff --git a/http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/ResourcePermissionResource.java b/http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/ResourcePermissionResource.java new file mode 100644 index 0000000000..fa450535ac --- /dev/null +++ b/http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/ResourcePermissionResource.java @@ -0,0 +1,8 @@ +package io.quarkus.ts.http.restclient.reactive; + +import javax.ws.rs.DELETE; + +public interface ResourcePermissionResource { + @DELETE + String remove(); +} diff --git a/http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/ResourcePermissionsResource.java b/http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/ResourcePermissionsResource.java new file mode 100644 index 0000000000..5a4ca341d8 --- /dev/null +++ b/http/rest-client-reactive/src/main/java/io/quarkus/ts/http/restclient/reactive/ResourcePermissionsResource.java @@ -0,0 +1,9 @@ +package io.quarkus.ts.http.restclient.reactive; + +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; + +public interface ResourcePermissionsResource { + @Path("{id}") + ResourcePermissionResource 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..87d33a39c2 --- /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.eclipse.microprofile.rest.client.RestClientBuilder; +import org.eclipse.microprofile.rest.client.inject.RestClient; + +import io.quarkus.ts.http.restclient.reactive.RealmResource; + +@Path("clients/{clientId}/clientResource") +@Consumes("text/plain") +@Produces("text/plain") +public class PlainComplexClientResource { + @Inject + @RestClient + RealmResource realmResource; + + @DELETE + @Path("/{id}") + @Produces(MediaType.TEXT_PLAIN) + public String deleteClientResource(@PathParam("clientId") String rootParam, @PathParam("id") String id) { + return realmResource.clients().get(rootParam).authorization().permissions().resource().findById(id).remove(); + } + + @DELETE + @Path("/{id}/manual/build") + @Produces(MediaType.TEXT_PLAIN) + public String deleteClientResource(@PathParam("clientId") String rootParam, @PathParam("id") String id, + @QueryParam("baseUri") String baseUri) throws URISyntaxException { + RealmResource rClient = RestClientBuilder.newBuilder().baseUri(new URI(baseUri)).build(RealmResource.class); + return rClient.clients().get(rootParam).authorization().permissions().resource().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..bb64d872fd --- /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}/authz/resource-server/permission/resource") +public class ReactivecomplexClientResource { + @Path("/{id}") + @DELETE + public String deleteById(@PathParam("rootPath") String rootPath, @PathParam("id") String id) { + return "/clients/" + rootPath + "/authz/resource-server/permission/resource/" + 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..b9063b0e2f 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.RealmResource".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..c3e1593cac 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,6 +1,6 @@ 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; @@ -202,22 +202,24 @@ public void checkSuffixPriority() { @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() + String id = "3479dd56-02e9-4222-94fe-6a13cd065195"; + String result = app.given().delete("clients/myRealm/clientResource/" + id).then() .statusCode(HttpStatus.SC_OK) .extract().asString(); - assertEquals("root/method/sub/sub/subsub", result); + assertEquals("/clients/myRealm/authz/resource-server/permission/resource/" + id, result); } @Tag("QUARKUS-2741") @Test public void checkProcessPathBeforeSubResourcesManualRestClientBuild() { + String id = "3479dd56-02e9-4222-94fe-6a13cd065195"; 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() + String result = app.given().get("clients/myRealm/clientResource" + id + "/manual/build?baseUri=" + baseUri).then() .statusCode(HttpStatus.SC_OK) .extract().asString(); - assertEquals("root/method/sub/sub/subsub", result); + assertEquals("/clients/myRealm/authz/resource-server/permission/resource/" + id, result); } }