diff --git a/extensions/resteasy-classic/rest-client/config/src/main/java/io/quarkus/restclient/config/Constants.java b/extensions/resteasy-classic/rest-client/config/src/main/java/io/quarkus/restclient/config/Constants.java index e53a12462b13b..558b322e1d925 100644 --- a/extensions/resteasy-classic/rest-client/config/src/main/java/io/quarkus/restclient/config/Constants.java +++ b/extensions/resteasy-classic/rest-client/config/src/main/java/io/quarkus/restclient/config/Constants.java @@ -2,8 +2,10 @@ public final class Constants { - public static final String MP_REST_SCOPE_FORMAT = "%s/mp-rest/scope"; - public static final String QUARKUS_REST_SCOPE_FORMAT = "quarkus.rest-client.%s.scope"; + public static final String QUARKUS_CONFIG_PREFIX = "quarkus.rest-client."; + public static final String MP_REST = "/mp-rest/"; + public static final String MP_REST_SCOPE_FORMAT = "%s" + MP_REST + "scope"; + public static final String QUARKUS_REST_SCOPE_FORMAT = QUARKUS_CONFIG_PREFIX + "%s.scope"; private Constants() { } diff --git a/extensions/resteasy-classic/rest-client/config/src/main/java/io/quarkus/restclient/config/QueryParamStyleConverter.java b/extensions/resteasy-classic/rest-client/config/src/main/java/io/quarkus/restclient/config/QueryParamStyleConverter.java new file mode 100644 index 0000000000000..9c25f4075291f --- /dev/null +++ b/extensions/resteasy-classic/rest-client/config/src/main/java/io/quarkus/restclient/config/QueryParamStyleConverter.java @@ -0,0 +1,11 @@ +package io.quarkus.restclient.config; + +import org.eclipse.microprofile.config.spi.Converter; +import org.eclipse.microprofile.rest.client.ext.QueryParamStyle; + +public class QueryParamStyleConverter implements Converter { + @Override + public QueryParamStyle convert(String value) throws IllegalArgumentException, NullPointerException { + return QueryParamStyle.valueOf(value); + } +} diff --git a/extensions/resteasy-classic/rest-client/config/src/main/java/io/quarkus/restclient/config/RestClientConfig.java b/extensions/resteasy-classic/rest-client/config/src/main/java/io/quarkus/restclient/config/RestClientConfig.java index f28254d2e7bb5..fafe00369eb93 100644 --- a/extensions/resteasy-classic/rest-client/config/src/main/java/io/quarkus/restclient/config/RestClientConfig.java +++ b/extensions/resteasy-classic/rest-client/config/src/main/java/io/quarkus/restclient/config/RestClientConfig.java @@ -2,6 +2,8 @@ import java.util.Optional; +import org.eclipse.microprofile.config.Config; +import org.eclipse.microprofile.config.ConfigProvider; import org.eclipse.microprofile.rest.client.ext.QueryParamStyle; import io.quarkus.runtime.annotations.ConfigGroup; @@ -159,4 +161,83 @@ public class RestClientConfig { @ConfigItem public Optional maxRedirects; + public static RestClientConfig load(String configKey) { + final RestClientConfig instance = new RestClientConfig(); + + instance.url = getConfigValue(configKey, "url", String.class); + instance.uri = getConfigValue(configKey, "uri", String.class); + instance.scope = getConfigValue(configKey, "scope", String.class); + instance.providers = getConfigValue(configKey, "providers", String.class); + instance.connectTimeout = getConfigValue(configKey, "connect-timeout", Long.class); + instance.readTimeout = getConfigValue(configKey, "read-timeout", Long.class); + instance.followRedirects = getConfigValue(configKey, "follow-redirects", Boolean.class); + instance.proxyAddress = getConfigValue(configKey, "proxy-address", String.class); + instance.queryParamStyle = getConfigValue(configKey, "query-param-style", QueryParamStyle.class); + instance.trustStore = getConfigValue(configKey, "trust-store", String.class); + instance.trustStorePassword = getConfigValue(configKey, "trust-store-password", String.class); + instance.trustStoreType = getConfigValue(configKey, "trust-store-type", String.class); + instance.keyStore = getConfigValue(configKey, "key-store", String.class); + instance.keyStorePassword = getConfigValue(configKey, "key-store-password", String.class); + instance.keyStoreType = getConfigValue(configKey, "key-store-type", String.class); + instance.hostnameVerifier = getConfigValue(configKey, "hostname-verifier", String.class); + instance.connectionTTL = getConfigValue(configKey, "connection-ttl", Integer.class); + instance.connectionPoolSize = getConfigValue(configKey, "connection-pool-size", Integer.class); + instance.maxRedirects = getConfigValue(configKey, "max-redirects", Integer.class); + + return instance; + } + + public static RestClientConfig load(Class interfaceClass) { + final RestClientConfig instance = new RestClientConfig(); + + instance.url = getConfigValue(interfaceClass, "url", String.class); + instance.uri = getConfigValue(interfaceClass, "uri", String.class); + instance.scope = getConfigValue(interfaceClass, "scope", String.class); + instance.providers = getConfigValue(interfaceClass, "providers", String.class); + instance.connectTimeout = getConfigValue(interfaceClass, "connect-timeout", Long.class); + instance.readTimeout = getConfigValue(interfaceClass, "read-timeout", Long.class); + instance.followRedirects = getConfigValue(interfaceClass, "follow-redirects", Boolean.class); + instance.proxyAddress = getConfigValue(interfaceClass, "proxy-address", String.class); + instance.queryParamStyle = getConfigValue(interfaceClass, "query-param-style", QueryParamStyle.class); + instance.trustStore = getConfigValue(interfaceClass, "trust-store", String.class); + instance.trustStorePassword = getConfigValue(interfaceClass, "trust-store-password", String.class); + instance.trustStoreType = getConfigValue(interfaceClass, "trust-store-type", String.class); + instance.keyStore = getConfigValue(interfaceClass, "key-store", String.class); + instance.keyStorePassword = getConfigValue(interfaceClass, "key-store-password", String.class); + instance.keyStoreType = getConfigValue(interfaceClass, "key-store-type", String.class); + instance.hostnameVerifier = getConfigValue(interfaceClass, "hostname-verifier", String.class); + instance.connectionTTL = getConfigValue(interfaceClass, "connection-ttl", Integer.class); + instance.connectionPoolSize = getConfigValue(interfaceClass, "connection-pool-size", Integer.class); + instance.maxRedirects = getConfigValue(interfaceClass, "max-redirects", Integer.class); + + return instance; + } + + private static Optional getConfigValue(String configKey, String fieldName, Class type) { + final Config config = ConfigProvider.getConfig(); + Optional optional = config.getOptionalValue(composePropertyKey(configKey, fieldName), type); + if (optional.isEmpty()) { // try to find property with quoted configKey + optional = config.getOptionalValue(composePropertyKey('"' + configKey + '"', fieldName), type); + } + return optional; + } + + private static Optional getConfigValue(Class clientInterface, String fieldName, Class type) { + final Config config = ConfigProvider.getConfig(); + // first try interface full name + Optional optional = config.getOptionalValue(composePropertyKey('"' + clientInterface.getName() + '"', fieldName), + type); + if (optional.isEmpty()) { // then interface simple name + optional = config.getOptionalValue(composePropertyKey(clientInterface.getSimpleName(), fieldName), type); + } + if (optional.isEmpty()) { // lastly quoted interface simple name + optional = config.getOptionalValue(composePropertyKey('"' + clientInterface.getSimpleName() + '"', fieldName), + type); + } + return optional; + } + + private static String composePropertyKey(String key, String fieldName) { + return Constants.QUARKUS_CONFIG_PREFIX + key + "." + fieldName; + } } diff --git a/extensions/resteasy-classic/rest-client/config/src/main/java/io/quarkus/restclient/config/RestClientsConfig.java b/extensions/resteasy-classic/rest-client/config/src/main/java/io/quarkus/restclient/config/RestClientsConfig.java index dbafddd32c1c3..4ca3df58413fc 100644 --- a/extensions/resteasy-classic/rest-client/config/src/main/java/io/quarkus/restclient/config/RestClientsConfig.java +++ b/extensions/resteasy-classic/rest-client/config/src/main/java/io/quarkus/restclient/config/RestClientsConfig.java @@ -1,8 +1,11 @@ package io.quarkus.restclient.config; +import java.util.HashMap; import java.util.Map; import java.util.Optional; +import org.wildfly.common.annotation.NotNull; + import io.quarkus.runtime.annotations.ConfigItem; import io.quarkus.runtime.annotations.ConfigPhase; import io.quarkus.runtime.annotations.ConfigRoot; @@ -17,8 +20,7 @@ public class RestClientsConfig { * a class bearing that annotation, in which case it is possible to use the short name, as well as fully qualified * name. */ - @ConfigItem(name = ConfigItem.PARENT) - public Map configs; + private final Map configs = new HashMap<>(); /** * By default, REST Client Reactive uses text/plain content type for String values @@ -47,4 +49,23 @@ public class RestClientsConfig { public RestClientLoggingConfig logging; + public RestClientConfig getClientConfig(String configKey) { + if (configKey == null) { + return RestClientConfig.EMPTY; + } + return configs.computeIfAbsent(configKey, RestClientConfig::load); + } + + public RestClientConfig getClientConfig(@NotNull Class clientInterface) { + return configs.computeIfAbsent(clientInterface.getName(), name -> RestClientConfig.load(clientInterface)); + } + + public void putClientConfig(String configKey, RestClientConfig clientConfig) { + configs.put(configKey, clientConfig); + } + + public void putClientConfig(Class clientInterface, RestClientConfig clientConfig) { + configs.put(clientInterface.getName(), clientConfig); + } + } diff --git a/extensions/resteasy-classic/rest-client/config/src/main/resources/META-INF/services/org.eclipse.microprofile.config.spi.Converter b/extensions/resteasy-classic/rest-client/config/src/main/resources/META-INF/services/org.eclipse.microprofile.config.spi.Converter new file mode 100644 index 0000000000000..cd5453d3541f8 --- /dev/null +++ b/extensions/resteasy-classic/rest-client/config/src/main/resources/META-INF/services/org.eclipse.microprofile.config.spi.Converter @@ -0,0 +1 @@ +io.quarkus.restclient.config.QueryParamStyleConverter \ No newline at end of file diff --git a/extensions/resteasy-classic/rest-client/config/src/test/java/io/quarkus/restclient/config/RestClientConfigTest.java b/extensions/resteasy-classic/rest-client/config/src/test/java/io/quarkus/restclient/config/RestClientConfigTest.java new file mode 100644 index 0000000000000..f59f1bb2db1df --- /dev/null +++ b/extensions/resteasy-classic/rest-client/config/src/test/java/io/quarkus/restclient/config/RestClientConfigTest.java @@ -0,0 +1,88 @@ +package io.quarkus.restclient.config; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.IOException; +import java.net.URL; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.Optional; + +import org.eclipse.microprofile.config.Config; +import org.eclipse.microprofile.config.ConfigProvider; +import org.eclipse.microprofile.config.spi.ConfigBuilder; +import org.eclipse.microprofile.config.spi.ConfigProviderResolver; +import org.eclipse.microprofile.rest.client.ext.QueryParamStyle; +import org.junit.jupiter.api.Test; + +import io.smallrye.config.ConfigLogging; +import io.smallrye.config.PropertiesConfigSource; + +public class RestClientConfigTest { + + @Test + public void testLoadRestClientConfig() throws IOException { + setupMPConfig(); + + Config config = ConfigProvider.getConfig(); + Optional optionalValue = config.getOptionalValue("quarkus.rest-client.test-client.url", String.class); + assertThat(optionalValue).isPresent(); + + RestClientConfig configForKey = RestClientConfig.load("test-client"); + verifyConfig(configForKey); + RestClientConfig configForClassName = RestClientConfig.load(RestClientConfigTest.class); + verifyConfig(configForClassName); + } + + private void verifyConfig(RestClientConfig config) { + assertThat(config.url).isPresent(); + assertThat(config.url.get()).isEqualTo("http://localhost:8080"); + assertThat(config.uri).isPresent(); + assertThat(config.uri.get()).isEqualTo("http://localhost:8081"); + assertThat(config.scope).isPresent(); + assertThat(config.scope.get()).isEqualTo("Singleton"); + assertThat(config.providers).isPresent(); + assertThat(config.providers.get()).isEqualTo("io.quarkus.restclient.configuration.MyResponseFilter"); + assertThat(config.connectTimeout).isPresent(); + assertThat(config.connectTimeout.get()).isEqualTo(5000); + assertThat(config.readTimeout).isPresent(); + assertThat(config.readTimeout.get()).isEqualTo(6000); + assertThat(config.followRedirects).isPresent(); + assertThat(config.followRedirects.get()).isEqualTo(true); + assertThat(config.proxyAddress).isPresent(); + assertThat(config.proxyAddress.get()).isEqualTo("localhost:8080"); + assertThat(config.queryParamStyle).isPresent(); + assertThat(config.queryParamStyle.get()).isEqualTo(QueryParamStyle.COMMA_SEPARATED); + assertThat(config.hostnameVerifier).isPresent(); + assertThat(config.hostnameVerifier.get()).isEqualTo("io.quarkus.restclient.configuration.MyHostnameVerifier"); + assertThat(config.connectionTTL).isPresent(); + assertThat(config.connectionTTL.get()).isEqualTo(30000); + assertThat(config.connectionPoolSize).isPresent(); + assertThat(config.connectionPoolSize.get()).isEqualTo(10); + } + + private static void setupMPConfig() throws IOException { + ConfigProviderResolver resolver = ConfigProviderResolver.instance(); + ConfigBuilder configBuilder = resolver.getBuilder(); + URL propertyFile = RestClientConfigTest.class.getClassLoader().getResource("application.properties"); + assertThat(propertyFile).isNotNull(); + configBuilder.withSources(new PropertiesConfigSource(propertyFile)); + resolver.registerConfig(configBuilder.build(), getContextClassLoader()); + } + + static ClassLoader getContextClassLoader() { + if (System.getSecurityManager() == null) { + return Thread.currentThread().getContextClassLoader(); + } else { + return AccessController.doPrivileged((PrivilegedAction) () -> { + ClassLoader tccl = null; + try { + tccl = Thread.currentThread().getContextClassLoader(); + } catch (SecurityException ex) { + ConfigLogging.log.failedToRetrieveClassloader(ex); + } + return tccl; + }); + } + } +} diff --git a/extensions/resteasy-classic/rest-client/config/src/test/resources/application.properties b/extensions/resteasy-classic/rest-client/config/src/test/resources/application.properties new file mode 100644 index 0000000000000..e4f04634edd40 --- /dev/null +++ b/extensions/resteasy-classic/rest-client/config/src/test/resources/application.properties @@ -0,0 +1,25 @@ +quarkus.rest-client.test-client.url=http://localhost:8080 +quarkus.rest-client.test-client.uri=http://localhost:8081 +quarkus.rest-client.test-client.scope=Singleton +quarkus.rest-client.test-client.providers=io.quarkus.restclient.configuration.MyResponseFilter +quarkus.rest-client.test-client.connect-timeout=5000 +quarkus.rest-client.test-client.read-timeout=6000 +quarkus.rest-client.test-client.follow-redirects=true +quarkus.rest-client.test-client.proxy-address=localhost:8080 +quarkus.rest-client.test-client.query-param-style=COMMA_SEPARATED +quarkus.rest-client.test-client.hostname-verifier=io.quarkus.restclient.configuration.MyHostnameVerifier +quarkus.rest-client.test-client.connection-ttl=30000 +quarkus.rest-client.test-client.connection-pool-size=10 + +quarkus.rest-client."io.quarkus.restclient.config.RestClientConfigTest".url=http://localhost:8080 +quarkus.rest-client."RestClientConfigTest".uri=http://localhost:8081 +quarkus.rest-client.RestClientConfigTest.scope=Singleton +quarkus.rest-client."io.quarkus.restclient.config.RestClientConfigTest".providers=io.quarkus.restclient.configuration.MyResponseFilter +quarkus.rest-client."io.quarkus.restclient.config.RestClientConfigTest".connect-timeout=5000 +quarkus.rest-client."io.quarkus.restclient.config.RestClientConfigTest".read-timeout=6000 +quarkus.rest-client."io.quarkus.restclient.config.RestClientConfigTest".follow-redirects=true +quarkus.rest-client."io.quarkus.restclient.config.RestClientConfigTest".proxy-address=localhost:8080 +quarkus.rest-client."io.quarkus.restclient.config.RestClientConfigTest".query-param-style=COMMA_SEPARATED +quarkus.rest-client."io.quarkus.restclient.config.RestClientConfigTest".hostname-verifier=io.quarkus.restclient.configuration.MyHostnameVerifier +quarkus.rest-client."io.quarkus.restclient.config.RestClientConfigTest".connection-ttl=30000 +quarkus.rest-client."io.quarkus.restclient.config.RestClientConfigTest".connection-pool-size=10 diff --git a/extensions/resteasy-classic/rest-client/deployment/src/test/java/io/quarkus/restclient/configuration/QuarkusConfigurationTest.java b/extensions/resteasy-classic/rest-client/deployment/src/test/java/io/quarkus/restclient/configuration/QuarkusConfigurationTest.java index ac6f5479b54f3..8295269d7a971 100644 --- a/extensions/resteasy-classic/rest-client/deployment/src/test/java/io/quarkus/restclient/configuration/QuarkusConfigurationTest.java +++ b/extensions/resteasy-classic/rest-client/deployment/src/test/java/io/quarkus/restclient/configuration/QuarkusConfigurationTest.java @@ -35,12 +35,6 @@ public class QuarkusConfigurationTest { @Inject RestClientsConfig configRoot; - @Test - public void shouldConnect() { - // TODO move to separate test - //Assertions.assertEquals("Hello", client.echo("Hello")); - } - @Test void shouldHaveSingletonScope() { BeanManager beanManager = Arc.container().beanManager(); @@ -51,13 +45,11 @@ void shouldHaveSingletonScope() { @Test void configurationsShouldBeLoaded() { - assertThat(configRoot.configs.size()).isEqualTo(5); - - verifyClientConfig(configRoot.configs.get("echo-client"), true); - verifyClientConfig(configRoot.configs.get("io.quarkus.restclient.configuration.EchoClient"), true); - verifyClientConfig(configRoot.configs.get("EchoClient"), true); - verifyClientConfig(configRoot.configs.get("mp-client"), false); // non-standard properties cannot be set via MP style config - verifyClientConfig(configRoot.configs.get("a.b.c.Client"), false); + verifyClientConfig(configRoot.getClientConfig("echo-client"), true); + verifyClientConfig(configRoot.getClientConfig("io.quarkus.restclient.configuration.EchoClient"), true); + verifyClientConfig(configRoot.getClientConfig("EchoClient"), true); + verifyClientConfig(configRoot.getClientConfig("mp-client"), false); // non-standard properties cannot be set via MP style config + verifyClientConfig(configRoot.getClientConfig("a.b.c.Client"), false); } void verifyClientConfig(RestClientConfig clientConfig, boolean verifyNonStandardProperties) { diff --git a/extensions/resteasy-classic/rest-client/deployment/src/test/java/io/quarkus/restclient/configuration/RestClientConfigNotationTest.java b/extensions/resteasy-classic/rest-client/deployment/src/test/java/io/quarkus/restclient/configuration/RestClientConfigNotationTest.java new file mode 100644 index 0000000000000..98d30635cbae8 --- /dev/null +++ b/extensions/resteasy-classic/rest-client/deployment/src/test/java/io/quarkus/restclient/configuration/RestClientConfigNotationTest.java @@ -0,0 +1,108 @@ +package io.quarkus.restclient.configuration; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Collections; +import java.util.Map; +import java.util.Set; + +import org.eclipse.microprofile.config.ConfigProvider; +import org.eclipse.microprofile.config.spi.ConfigSource; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.spec.JavaArchive; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import com.google.common.collect.Iterators; + +import io.quarkus.restclient.config.RestClientConfig; +import io.quarkus.restclient.config.RestClientsConfig; +import io.quarkus.test.QuarkusUnitTest; +import io.smallrye.config.common.AbstractConfigSource; + +public class RestClientConfigNotationTest { + + private static final String URL = "localhost:8080"; + + @RegisterExtension + static final QuarkusUnitTest TEST = new QuarkusUnitTest().setArchiveProducer( + () -> ShrinkWrap.create(JavaArchive.class) + .addClasses(EchoClient.class, TestConfigSource.class) + .addAsServiceProvider("org.eclipse.microprofile.config.spi.ConfigSource", + "io.quarkus.restclient.configuration.RestClientConfigNotationTest$TestConfigSource")); + + @ParameterizedTest + @ValueSource(strings = { + "quarkus.rest-client.\"io.quarkus.restclient.configuration.EchoClient\".url", + "quarkus.rest-client.\"EchoClient\".url", + "quarkus.rest-client.EchoClient.url", + "io.quarkus.restclient.configuration.EchoClient/mp-rest/url" + }) + public void testInterfaceConfiguration(final String urlPropertyName) { + TestConfigSource.urlPropertyName = urlPropertyName; + + RestClientsConfig configRoot = new RestClientsConfig(); + RestClientConfig clientConfig = configRoot.getClientConfig(EchoClient.class); + verifyConfig(clientConfig, urlPropertyName); + } + + @ParameterizedTest + @ValueSource(strings = { + "quarkus.rest-client.\"echo-client\".url", + "quarkus.rest-client.echo-client.url", + "echo-client/mp-rest/url" + }) + public void testConfigKeyConfiguration(final String urlPropertyName) { + TestConfigSource.urlPropertyName = urlPropertyName; + RestClientsConfig configRoot = new RestClientsConfig(); + RestClientConfig clientConfig = configRoot.getClientConfig("echo-client"); + + verifyConfig(clientConfig, urlPropertyName); + } + + private void verifyConfig(final RestClientConfig clientConfig, final String urlPropertyName) { + ConfigSource configSource = Iterators.find(ConfigProvider.getConfig().getConfigSources().iterator(), + c -> c.getName().equals(TestConfigSource.SOURCE_NAME)); + assertThat(configSource.getPropertyNames()).containsOnly(urlPropertyName); + assertThat(configSource.getValue(urlPropertyName)).isEqualTo(URL); + + assertThat(clientConfig.url).isPresent(); + assertThat(clientConfig.url.get()).isEqualTo(URL); + } + + public static class TestConfigSource extends AbstractConfigSource { + + public static final String SOURCE_NAME = "Test config source"; + + public static String urlPropertyName; + + public TestConfigSource() { + super(SOURCE_NAME, Integer.MAX_VALUE); + } + + @Override + public Map getProperties() { + if (urlPropertyName != null) { + return Collections.singletonMap(urlPropertyName, URL); + } + return Collections.emptyMap(); + } + + @Override + public Set getPropertyNames() { + if (urlPropertyName != null) { + return Set.of(urlPropertyName); + } + return Collections.emptySet(); + } + + @Override + public String getValue(String propertyName) { + if (propertyName.equals(urlPropertyName)) { + return URL; + } + return null; + } + } +} diff --git a/extensions/resteasy-classic/rest-client/deployment/src/test/java/io/quarkus/restclient/configuration/RestClientOverrideRuntimeConfigTest.java b/extensions/resteasy-classic/rest-client/deployment/src/test/java/io/quarkus/restclient/configuration/RestClientOverrideRuntimeConfigTest.java index ed09ebb2dc1d9..4fdbd5cf067b6 100644 --- a/extensions/resteasy-classic/rest-client/deployment/src/test/java/io/quarkus/restclient/configuration/RestClientOverrideRuntimeConfigTest.java +++ b/extensions/resteasy-classic/rest-client/deployment/src/test/java/io/quarkus/restclient/configuration/RestClientOverrideRuntimeConfigTest.java @@ -41,9 +41,6 @@ void overrideConfig() { assertTrue(specifiedDefaultValues.isPresent()); assertTrue(specifiedDefaultValues.get().getPropertyNames() .contains("io.quarkus.restclient.configuration.EchoClient/mp-rest/url")); - // This config key comes from the interceptor and it is recorded with an empty value. This allow the user to still override using the original key - assertEquals("", specifiedDefaultValues.get() - .getValue("quarkus.rest-client.\"io.quarkus.restclient.configuration.EchoClient\".url")); ConfigValue mpValue = config.getConfigValue("io.quarkus.restclient.configuration.EchoClient/mp-rest/url"); // Fallbacks from runtime to the override build time value diff --git a/extensions/resteasy-classic/rest-client/deployment/src/test/java/io/quarkus/restclient/configuration/VaultScenarioRestClientConfigTest.java b/extensions/resteasy-classic/rest-client/deployment/src/test/java/io/quarkus/restclient/configuration/VaultScenarioRestClientConfigTest.java new file mode 100644 index 0000000000000..52508979e6560 --- /dev/null +++ b/extensions/resteasy-classic/rest-client/deployment/src/test/java/io/quarkus/restclient/configuration/VaultScenarioRestClientConfigTest.java @@ -0,0 +1,73 @@ +package io.quarkus.restclient.configuration; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Collections; +import java.util.Map; +import java.util.Set; + +import javax.inject.Inject; + +import org.eclipse.microprofile.config.spi.ConfigSource; +import org.eclipse.microprofile.rest.client.inject.RestClient; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.spec.JavaArchive; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.test.QuarkusUnitTest; +import io.smallrye.config.common.AbstractConfigSource; + +/** + * This test makes sure that the rest client configuration is loaded even if it's provided by a ConfigSource which doesn't + * list its contents via {@link ConfigSource#getPropertyNames()} (e.g. {@link VaultLikeConfigSource}). + * + * This wasn't working when the configuration was accessed through a ConfigSource map - rest client initialization would fail + * because no URI/URL configuration was obtained. + */ +public class VaultScenarioRestClientConfigTest { + + @RegisterExtension + static final QuarkusUnitTest TEST = new QuarkusUnitTest().setArchiveProducer( + () -> ShrinkWrap.create(JavaArchive.class) + .addClasses(EchoResource.class, EchoClient.class, VaultLikeConfigSource.class) + .addAsServiceProvider("org.eclipse.microprofile.config.spi.ConfigSource", + "io.quarkus.restclient.configuration.VaultScenarioRestClientConfigTest$VaultLikeConfigSource")); + + @Inject + @RestClient + EchoClient echoClient; + + @Test + public void testClient() { + assertThat(echoClient.echo("Hello")).isEqualTo("Hello"); + } + + /** + * Vaults do not allow to list their contents via {@link #getProperties()} or {@link #getPropertyNames()}. + */ + public static class VaultLikeConfigSource extends AbstractConfigSource { + + public VaultLikeConfigSource() { + super("Test config source", Integer.MAX_VALUE); + } + + @Override + public Map getProperties() { + return Collections.emptyMap(); + } + + @Override + public Set getPropertyNames() { + return Collections.emptySet(); + } + + @Override + public String getValue(String propertyName) { + if ("quarkus.rest-client.\"io.quarkus.restclient.configuration.EchoClient\".url".equals(propertyName)) { + return "http://localhost:${quarkus.http.test-port:8081}"; + } + return null; + } + } +} diff --git a/extensions/resteasy-classic/rest-client/runtime/src/main/java/io/quarkus/restclient/runtime/RestClientBase.java b/extensions/resteasy-classic/rest-client/runtime/src/main/java/io/quarkus/restclient/runtime/RestClientBase.java index 9ef6e41090afc..a36e4840026d9 100644 --- a/extensions/resteasy-classic/rest-client/runtime/src/main/java/io/quarkus/restclient/runtime/RestClientBase.java +++ b/extensions/resteasy-classic/rest-client/runtime/src/main/java/io/quarkus/restclient/runtime/RestClientBase.java @@ -324,20 +324,11 @@ private static RestClientsConfig getConfigRoot() { } private RestClientConfig clientConfigByConfigKey() { - if (configKey != null) { - return this.configRoot.configs.getOrDefault(configKey, RestClientConfig.EMPTY); - } - return RestClientConfig.EMPTY; + return this.configRoot.getClientConfig(this.configKey); } private RestClientConfig clientConfigByClassName() { - if (this.configRoot.configs.containsKey(proxyType.getName())) { - return this.configRoot.configs.get(proxyType.getName()); - } - if (this.configRoot.configs.containsKey(proxyType.getSimpleName())) { - return this.configRoot.configs.get(proxyType.getSimpleName()); - } - return RestClientConfig.EMPTY; + return this.configRoot.getClientConfig(this.proxyType); } private static Optional oneOf(Optional o1, Optional o2) { diff --git a/extensions/resteasy-classic/rest-client/runtime/src/test/java/io/quarkus/restclient/runtime/RestClientBaseTest.java b/extensions/resteasy-classic/rest-client/runtime/src/test/java/io/quarkus/restclient/runtime/RestClientBaseTest.java index 56bcb027760f8..b8d330756d2c0 100644 --- a/extensions/resteasy-classic/rest-client/runtime/src/test/java/io/quarkus/restclient/runtime/RestClientBaseTest.java +++ b/extensions/resteasy-classic/rest-client/runtime/src/test/java/io/quarkus/restclient/runtime/RestClientBaseTest.java @@ -9,7 +9,6 @@ import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; import java.util.Arrays; -import java.util.HashMap; import java.util.Optional; import java.util.concurrent.TimeUnit; @@ -131,8 +130,7 @@ private static RestClientsConfig createSampleConfiguration() { RestClientsConfig configRoot = new RestClientsConfig(); configRoot.multipartPostEncoderMode = Optional.of("HTML5"); configRoot.disableSmartProduces = Optional.of(true); - configRoot.configs = new HashMap<>(); - configRoot.configs.put("test-client", clientConfig); + configRoot.putClientConfig("test-client", clientConfig); return configRoot; } diff --git a/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/ConfigurationTest.java b/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/ConfigurationTest.java index 1b8541f3f7079..d2bc39d87cdb1 100644 --- a/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/ConfigurationTest.java +++ b/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/ConfigurationTest.java @@ -53,21 +53,20 @@ void configurationShouldBeLoaded() { assertThat(configRoot.disableSmartProduces.get()).isTrue(); assertThat(configRoot.multipartPostEncoderMode).isPresent(); assertThat(configRoot.multipartPostEncoderMode.get()).isEqualTo("HTML5"); - assertThat(configRoot.configs.size()).isEqualTo(4); - RestClientConfig clientConfig = configRoot.configs.get("io.quarkus.rest.client.reactive.HelloClientWithBaseUri"); + RestClientConfig clientConfig = RestClientConfig.load(io.quarkus.rest.client.reactive.HelloClientWithBaseUri.class); verifyClientConfig(clientConfig, true); - clientConfig = configRoot.configs.get("client-prefix"); + clientConfig = RestClientConfig.load("client-prefix"); verifyClientConfig(clientConfig, true); assertThat(clientConfig.proxyAddress.isPresent()).isTrue(); assertThat(clientConfig.proxyAddress.get()).isEqualTo("localhost:8080"); - clientConfig = configRoot.configs.get("quoted-client-prefix"); + clientConfig = RestClientConfig.load("quoted-client-prefix"); assertThat(clientConfig.url.isPresent()).isTrue(); assertThat(clientConfig.url.get()).endsWith("/hello"); - clientConfig = configRoot.configs.get("mp-client-prefix"); + clientConfig = RestClientConfig.load("mp-client-prefix"); verifyClientConfig(clientConfig, false); assertThat(clientConfig.maxRedirects.isPresent()).isTrue(); assertThat(clientConfig.maxRedirects.get()).isEqualTo(4); diff --git a/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/LegacyConfigurationTest.java b/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/LegacyConfigurationTest.java index a519aa5e8ea53..f7854fa0c446a 100644 --- a/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/LegacyConfigurationTest.java +++ b/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/LegacyConfigurationTest.java @@ -17,7 +17,7 @@ public class LegacyConfigurationTest { @RegisterExtension static final QuarkusUnitTest TEST = new QuarkusUnitTest() .withApplicationRoot((jar) -> jar - .addClasses(HelloClientWithBaseUri.class, EchoResource.class)) + .addClasses(HelloClientWithBaseUri.class, EchoResource.class, HelloClient.class)) .withConfigurationResource("legacy-configuration-test-application.properties"); @Inject @@ -29,13 +29,12 @@ void configurationShouldBeLoaded() { assertThat(configRoot.disableSmartProduces.get()).isTrue(); assertThat(configRoot.multipartPostEncoderMode).isPresent(); assertThat(configRoot.multipartPostEncoderMode.get()).isEqualTo("RFC3986"); - assertThat(configRoot.configs.size()).isEqualTo(2); - RestClientConfig clientConfig = configRoot.configs.get("a.b.c.RestClient"); + RestClientConfig clientConfig = RestClientConfig.load(io.quarkus.rest.client.reactive.HelloClient.class); assertThat(clientConfig.maxRedirects).isPresent(); assertThat(clientConfig.maxRedirects.get()).isEqualTo(4); - clientConfig = configRoot.configs.get("client-prefix"); + clientConfig = RestClientConfig.load("client-prefix"); assertThat(clientConfig.maxRedirects).isPresent(); assertThat(clientConfig.maxRedirects.get()).isEqualTo(4); } diff --git a/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/resources/legacy-configuration-test-application.properties b/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/resources/legacy-configuration-test-application.properties index de9c445ccd568..7dac0b60d9a2e 100644 --- a/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/resources/legacy-configuration-test-application.properties +++ b/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/resources/legacy-configuration-test-application.properties @@ -5,4 +5,4 @@ quarkus.rest.client.multipart-post-encoder-mode=RFC3986 client-prefix/mp-rest/url=http://localhost:${quarkus.http.test-port:8081}/hello -a.b.c.RestClient/mp-rest/url=http://localhost:${quarkus.http.test-port:8081}/hello +io.quarkus.rest.client.reactive.HelloClient/mp-rest/url=http://localhost:${quarkus.http.test-port:8081}/hello 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 a43318d192056..bc0106ac8d99c 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 @@ -333,20 +333,11 @@ private static RestClientsConfig getConfigRoot() { } private RestClientConfig clientConfigByConfigKey() { - if (configKey != null) { - return this.configRoot.configs.getOrDefault(configKey, RestClientConfig.EMPTY); - } - return RestClientConfig.EMPTY; + return this.configRoot.getClientConfig(configKey); } private RestClientConfig clientConfigByClassName() { - if (this.configRoot.configs.containsKey(jaxrsInterface.getName())) { - return this.configRoot.configs.get(jaxrsInterface.getName()); - } - if (this.configRoot.configs.containsKey(jaxrsInterface.getSimpleName())) { - return this.configRoot.configs.get(jaxrsInterface.getSimpleName()); - } - return RestClientConfig.EMPTY; + return this.configRoot.getClientConfig(jaxrsInterface); } private static Optional oneOf(Optional o1, Optional o2) { 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 f4c42ed7e56fb..f80d41ebff3a8 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 @@ -8,7 +8,6 @@ import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; -import java.util.HashMap; import java.util.Optional; import java.util.concurrent.TimeUnit; @@ -123,8 +122,7 @@ private static RestClientsConfig createSampleConfiguration() { RestClientsConfig configRoot = new RestClientsConfig(); configRoot.multipartPostEncoderMode = Optional.of("HTML5"); configRoot.disableSmartProduces = Optional.of(true); - configRoot.configs = new HashMap<>(); - configRoot.configs.put("test-client", clientConfig); + configRoot.putClientConfig("test-client", clientConfig); return configRoot; }