From c0e11c6d6fa25d70248d4be4853b46e8bd5bfb28 Mon Sep 17 00:00:00 2001 From: Tomas Hofman Date: Fri, 9 Sep 2022 14:46:49 +0200 Subject: [PATCH] Add RestClientBuilder factories These factories should make it easier for developers to obtain a RestClientBuilder instance preconfigured according to current application config. The builder can be further tweaked and then used to programatically build a rest client proxy. --- .../config/RestClientBuilderFactory.java | 34 ++++++++++++++++++ .../ClassicRestClientBuilderFactoryTest.java | 36 +++++++++++++++++++ .../EchoClientWithoutAnnotation.java | 18 ++++++++++ .../factory-test-application.properties | 3 ++ .../ClassicRestClientBuilderFactory.java | 27 ++++++++++++++ ...restclient.config.RestClientBuilderFactory | 1 + .../ReactiveRestClientBuilderFactoryTest.java | 29 +++++++++++++++ .../factory-test-application.properties | 2 ++ .../ReactiveRestClientBuilderFactory.java | 28 +++++++++++++++ .../runtime/RestClientCDIDelegateBuilder.java | 8 ++--- ...restclient.config.RestClientBuilderFactory | 1 + .../RestClientCDIDelegateBuilderTest.java | 4 +-- 12 files changed, 185 insertions(+), 6 deletions(-) create mode 100644 extensions/resteasy-classic/rest-client-config/runtime/src/main/java/io/quarkus/restclient/config/RestClientBuilderFactory.java create mode 100644 extensions/resteasy-classic/rest-client/deployment/src/test/java/io/quarkus/restclient/configuration/ClassicRestClientBuilderFactoryTest.java create mode 100644 extensions/resteasy-classic/rest-client/deployment/src/test/java/io/quarkus/restclient/configuration/EchoClientWithoutAnnotation.java create mode 100644 extensions/resteasy-classic/rest-client/deployment/src/test/resources/factory-test-application.properties create mode 100644 extensions/resteasy-classic/rest-client/runtime/src/main/java/io/quarkus/restclient/runtime/ClassicRestClientBuilderFactory.java create mode 100644 extensions/resteasy-classic/rest-client/runtime/src/main/resources/META-INF/services/io.quarkus.restclient.config.RestClientBuilderFactory create mode 100644 extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/ReactiveRestClientBuilderFactoryTest.java create mode 100644 extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/resources/factory-test-application.properties create mode 100644 extensions/resteasy-reactive/rest-client-reactive/runtime/src/main/java/io/quarkus/rest/client/reactive/runtime/ReactiveRestClientBuilderFactory.java create mode 100644 extensions/resteasy-reactive/rest-client-reactive/runtime/src/main/resources/META-INF/services/io.quarkus.restclient.config.RestClientBuilderFactory diff --git a/extensions/resteasy-classic/rest-client-config/runtime/src/main/java/io/quarkus/restclient/config/RestClientBuilderFactory.java b/extensions/resteasy-classic/rest-client-config/runtime/src/main/java/io/quarkus/restclient/config/RestClientBuilderFactory.java new file mode 100644 index 0000000000000..3e9222f6f4106 --- /dev/null +++ b/extensions/resteasy-classic/rest-client-config/runtime/src/main/java/io/quarkus/restclient/config/RestClientBuilderFactory.java @@ -0,0 +1,34 @@ +package io.quarkus.restclient.config; + +import java.util.ServiceLoader; + +import org.eclipse.microprofile.rest.client.RestClientBuilder; + +/** + * Factory which creates MicroProfile RestClientBuilder instance configured according to current Quarkus application + * configuration. + * + * The builder instance can be further tweaked, if needed, before building the rest client proxy. + */ +public interface RestClientBuilderFactory { + + default RestClientBuilder newBuilder(Class proxyType) { + return newBuilder(proxyType, RestClientsConfig.getInstance()); + } + + RestClientBuilder newBuilder(Class proxyType, RestClientsConfig restClientsConfigRoot); + + static RestClientBuilderFactory getInstance() { + ServiceLoader sl = ServiceLoader.load(RestClientBuilderFactory.class); + RestClientBuilderFactory instance = null; + for (RestClientBuilderFactory spi : sl) { + if (instance != null) { + throw new IllegalStateException("Multiple RestClientBuilderFactory implementations found: " + + spi.getClass().getName() + " and " + + instance.getClass().getName()); + } + instance = spi; + } + return instance; + } +} diff --git a/extensions/resteasy-classic/rest-client/deployment/src/test/java/io/quarkus/restclient/configuration/ClassicRestClientBuilderFactoryTest.java b/extensions/resteasy-classic/rest-client/deployment/src/test/java/io/quarkus/restclient/configuration/ClassicRestClientBuilderFactoryTest.java new file mode 100644 index 0000000000000..03d9485ea7dba --- /dev/null +++ b/extensions/resteasy-classic/rest-client/deployment/src/test/java/io/quarkus/restclient/configuration/ClassicRestClientBuilderFactoryTest.java @@ -0,0 +1,36 @@ +package io.quarkus.restclient.configuration; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.eclipse.microprofile.rest.client.RestClientBuilder; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.restclient.config.RestClientBuilderFactory; +import io.quarkus.test.QuarkusUnitTest; + +public class ClassicRestClientBuilderFactoryTest { + + @RegisterExtension + static final QuarkusUnitTest TEST = new QuarkusUnitTest() + .withApplicationRoot((jar) -> jar.addClasses(EchoClientWithoutAnnotation.class, EchoClientWithConfigKey.class, + EchoResource.class)) + .withConfigurationResource("factory-test-application.properties"); + + @Test + public void testAnnotatedClientClass() { + RestClientBuilder restClientBuilder = RestClientBuilderFactory.getInstance().newBuilder(EchoClientWithConfigKey.class); + EchoClientWithConfigKey restClient = restClientBuilder.build(EchoClientWithConfigKey.class); + + assertThat(restClient.echo("Hello")).contains("Hello"); + } + + @Test + public void testNotAnnotatedClientClass() { + RestClientBuilder restClientBuilder = RestClientBuilderFactory.getInstance() + .newBuilder(EchoClientWithoutAnnotation.class); + EchoClientWithoutAnnotation restClient = restClientBuilder.build(EchoClientWithoutAnnotation.class); + + assertThat(restClient.echo("Hello")).contains("Hello"); + } +} diff --git a/extensions/resteasy-classic/rest-client/deployment/src/test/java/io/quarkus/restclient/configuration/EchoClientWithoutAnnotation.java b/extensions/resteasy-classic/rest-client/deployment/src/test/java/io/quarkus/restclient/configuration/EchoClientWithoutAnnotation.java new file mode 100644 index 0000000000000..f27d86054b4f6 --- /dev/null +++ b/extensions/resteasy-classic/rest-client/deployment/src/test/java/io/quarkus/restclient/configuration/EchoClientWithoutAnnotation.java @@ -0,0 +1,18 @@ +package io.quarkus.restclient.configuration; + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; + +@Path("/echo") +public interface EchoClientWithoutAnnotation { + + @GET + @Produces(MediaType.TEXT_PLAIN) + @Consumes(MediaType.TEXT_PLAIN) + String echo(@QueryParam("message") String message); + +} diff --git a/extensions/resteasy-classic/rest-client/deployment/src/test/resources/factory-test-application.properties b/extensions/resteasy-classic/rest-client/deployment/src/test/resources/factory-test-application.properties new file mode 100644 index 0000000000000..da5f5178a2e45 --- /dev/null +++ b/extensions/resteasy-classic/rest-client/deployment/src/test/resources/factory-test-application.properties @@ -0,0 +1,3 @@ +quarkus.rest-client.echo-client.url=http://localhost:8081 +quarkus.rest-client.EchoClientWithoutAnnotation.url=http://localhost:8081 +quarkus.rest-client.read-timeout=3456 diff --git a/extensions/resteasy-classic/rest-client/runtime/src/main/java/io/quarkus/restclient/runtime/ClassicRestClientBuilderFactory.java b/extensions/resteasy-classic/rest-client/runtime/src/main/java/io/quarkus/restclient/runtime/ClassicRestClientBuilderFactory.java new file mode 100644 index 0000000000000..f8f51859f6fce --- /dev/null +++ b/extensions/resteasy-classic/rest-client/runtime/src/main/java/io/quarkus/restclient/runtime/ClassicRestClientBuilderFactory.java @@ -0,0 +1,27 @@ +package io.quarkus.restclient.runtime; + +import org.eclipse.microprofile.rest.client.RestClientBuilder; +import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; + +import io.quarkus.restclient.config.RestClientBuilderFactory; +import io.quarkus.restclient.config.RestClientsConfig; + +public class ClassicRestClientBuilderFactory implements RestClientBuilderFactory { + + public RestClientBuilder newBuilder(Class proxyType, RestClientsConfig restClientsConfigRoot) { + RegisterRestClient annotation = proxyType.getAnnotation(RegisterRestClient.class); + String configKey = null; + String baseUri = null; + if (annotation != null) { + configKey = annotation.configKey(); + baseUri = annotation.baseUri(); + } + + RestClientBuilder restClientBuilder = RestClientBuilder.newBuilder(); + RestClientBase restClientBase = new RestClientBase(proxyType, baseUri, configKey, new Class[0], restClientsConfigRoot); + restClientBase.configureBuilder(restClientBuilder); + + return restClientBuilder; + } + +} diff --git a/extensions/resteasy-classic/rest-client/runtime/src/main/resources/META-INF/services/io.quarkus.restclient.config.RestClientBuilderFactory b/extensions/resteasy-classic/rest-client/runtime/src/main/resources/META-INF/services/io.quarkus.restclient.config.RestClientBuilderFactory new file mode 100644 index 0000000000000..0f3850a8499fb --- /dev/null +++ b/extensions/resteasy-classic/rest-client/runtime/src/main/resources/META-INF/services/io.quarkus.restclient.config.RestClientBuilderFactory @@ -0,0 +1 @@ +io.quarkus.restclient.runtime.ClassicRestClientBuilderFactory \ No newline at end of file diff --git a/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/ReactiveRestClientBuilderFactoryTest.java b/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/ReactiveRestClientBuilderFactoryTest.java new file mode 100644 index 0000000000000..f8546ea1c32d5 --- /dev/null +++ b/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/ReactiveRestClientBuilderFactoryTest.java @@ -0,0 +1,29 @@ +package io.quarkus.rest.client.reactive; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.eclipse.microprofile.rest.client.RestClientBuilder; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.rest.client.reactive.configuration.EchoResource; +import io.quarkus.restclient.config.RestClientBuilderFactory; +import io.quarkus.test.QuarkusUnitTest; + +public class ReactiveRestClientBuilderFactoryTest { + + @RegisterExtension + static final QuarkusUnitTest TEST = new QuarkusUnitTest() + .withApplicationRoot((jar) -> jar.addClasses(HelloClient2.class, EchoResource.class)) + .withConfigurationResource("factory-test-application.properties"); + + @Test + public void test() throws Exception { + RestClientBuilder restClientBuilder = RestClientBuilderFactory.getInstance().newBuilder(HelloClient2.class); + HelloClient2 restClient = restClientBuilder.build(HelloClient2.class); + + assertThat(restClientBuilder.getConfiguration().getProperties().get("io.quarkus.rest.client.read-timeout")) + .isEqualTo(3456L); + assertThat(restClient.echo("Hello")).contains("Hello"); + } +} diff --git a/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/resources/factory-test-application.properties b/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/resources/factory-test-application.properties new file mode 100644 index 0000000000000..5bf6f265622e7 --- /dev/null +++ b/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/resources/factory-test-application.properties @@ -0,0 +1,2 @@ +quarkus.rest-client.hello2.url=http://localhost:8081/hello +quarkus.rest-client.read-timeout=3456 \ No newline at end of file diff --git a/extensions/resteasy-reactive/rest-client-reactive/runtime/src/main/java/io/quarkus/rest/client/reactive/runtime/ReactiveRestClientBuilderFactory.java b/extensions/resteasy-reactive/rest-client-reactive/runtime/src/main/java/io/quarkus/rest/client/reactive/runtime/ReactiveRestClientBuilderFactory.java new file mode 100644 index 0000000000000..d055bda239e18 --- /dev/null +++ b/extensions/resteasy-reactive/rest-client-reactive/runtime/src/main/java/io/quarkus/rest/client/reactive/runtime/ReactiveRestClientBuilderFactory.java @@ -0,0 +1,28 @@ +package io.quarkus.rest.client.reactive.runtime; + +import org.eclipse.microprofile.rest.client.RestClientBuilder; +import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; + +import io.quarkus.restclient.config.RestClientBuilderFactory; +import io.quarkus.restclient.config.RestClientsConfig; + +public class ReactiveRestClientBuilderFactory implements RestClientBuilderFactory { + + public RestClientBuilder newBuilder(Class proxyType, RestClientsConfig restClientsConfigRoot) { + RegisterRestClient annotation = proxyType.getAnnotation(RegisterRestClient.class); + String configKey = null; + String baseUri = null; + if (annotation != null) { + configKey = annotation.configKey(); + baseUri = annotation.baseUri(); + } + + RestClientBuilderImpl restClientBuilder = new RestClientBuilderImpl(); + RestClientCDIDelegateBuilder restClientBase = new RestClientCDIDelegateBuilder<>(proxyType, baseUri, configKey, + restClientsConfigRoot); + restClientBase.configureBuilder(restClientBuilder); + + return restClientBuilder; + } + +} diff --git a/extensions/resteasy-reactive/rest-client-reactive/runtime/src/main/java/io/quarkus/rest/client/reactive/runtime/RestClientCDIDelegateBuilder.java b/extensions/resteasy-reactive/rest-client-reactive/runtime/src/main/java/io/quarkus/rest/client/reactive/runtime/RestClientCDIDelegateBuilder.java index c5de36ca33ae1..83e647ae666df 100644 --- a/extensions/resteasy-reactive/rest-client-reactive/runtime/src/main/java/io/quarkus/rest/client/reactive/runtime/RestClientCDIDelegateBuilder.java +++ b/extensions/resteasy-reactive/rest-client-reactive/runtime/src/main/java/io/quarkus/rest/client/reactive/runtime/RestClientCDIDelegateBuilder.java @@ -60,10 +60,11 @@ private T build() { throw new IllegalStateException("Expected RestClientBuilder to be an instance of " + RestClientBuilderImpl.class.getName() + ", got " + builder.getClass().getName()); } - return build((RestClientBuilderImpl) builder); + configureBuilder((RestClientBuilderImpl) builder); + return builder.build(jaxrsInterface); } - T build(RestClientBuilderImpl builder) { + void configureBuilder(RestClientBuilderImpl builder) { configureBaseUrl(builder); configureTimeouts(builder); configureProviders(builder); @@ -73,12 +74,11 @@ T build(RestClientBuilderImpl builder) { configureProxy(builder); configureShared(builder); configureCustomProperties(builder); - return builder.build(jaxrsInterface); } private void configureCustomProperties(RestClientBuilder builder) { Optional encoder = configRoot.multipartPostEncoderMode; - if (encoder.isPresent()) { + if (encoder != null && encoder.isPresent()) { HttpPostRequestEncoder.EncoderMode mode = HttpPostRequestEncoder.EncoderMode .valueOf(encoder.get().toUpperCase(Locale.ROOT)); builder.property(QuarkusRestClientProperties.MULTIPART_ENCODER_MODE, mode); diff --git a/extensions/resteasy-reactive/rest-client-reactive/runtime/src/main/resources/META-INF/services/io.quarkus.restclient.config.RestClientBuilderFactory b/extensions/resteasy-reactive/rest-client-reactive/runtime/src/main/resources/META-INF/services/io.quarkus.restclient.config.RestClientBuilderFactory new file mode 100644 index 0000000000000..45fa8b003d6ee --- /dev/null +++ b/extensions/resteasy-reactive/rest-client-reactive/runtime/src/main/resources/META-INF/services/io.quarkus.restclient.config.RestClientBuilderFactory @@ -0,0 +1 @@ +io.quarkus.rest.client.reactive.runtime.ReactiveRestClientBuilderFactory \ No newline at end of file diff --git a/extensions/resteasy-reactive/rest-client-reactive/runtime/src/test/java/io/quarkus/rest/client/reactive/runtime/RestClientCDIDelegateBuilderTest.java b/extensions/resteasy-reactive/rest-client-reactive/runtime/src/test/java/io/quarkus/rest/client/reactive/runtime/RestClientCDIDelegateBuilderTest.java index 7088d7ba1bf04..60f80120fb6a7 100644 --- a/extensions/resteasy-reactive/rest-client-reactive/runtime/src/test/java/io/quarkus/rest/client/reactive/runtime/RestClientCDIDelegateBuilderTest.java +++ b/extensions/resteasy-reactive/rest-client-reactive/runtime/src/test/java/io/quarkus/rest/client/reactive/runtime/RestClientCDIDelegateBuilderTest.java @@ -82,7 +82,7 @@ public void testClientSpecificConfigs() { new RestClientCDIDelegateBuilder<>(TestClient.class, "http://localhost:8080", "test-client", - configRoot).build(restClientBuilderMock); + configRoot).configureBuilder(restClientBuilderMock); // then @@ -125,7 +125,7 @@ public void testGlobalConfigs() { new RestClientCDIDelegateBuilder<>(TestClient.class, "http://localhost:8080", "test-client", - configRoot).build(restClientBuilderMock); + configRoot).configureBuilder(restClientBuilderMock); // then