From d8973fccfbb747f2f0e71009f3d78c37542c16ed Mon Sep 17 00:00:00 2001 From: Marcin Czeczko Date: Wed, 9 Oct 2019 11:20:45 +0200 Subject: [PATCH] Dynamodb - URL connection http client support --- bom/runtime/pom.xml | 5 + docs/src/main/asciidoc/dynamodb-guide.adoc | 2 +- .../deployment/DynamodbProcessor.java | 46 ++-- ...modbSyncApacheClientBrokenConfigTest.java} | 4 +- ...yncApacheClientBrokenProxyConfigTest.java} | 4 +- ...namodbSyncApacheClientFullConfigTest.java} | 4 +- ...namodbSyncUrlConnClientFullConfigTest.java | 27 +++ ...s => sync-apache-broken-config.properties} | 1 + ...ync-apache-broken-proxy-config.properties} | 1 + ...ies => sync-apache-full-config.properties} | 6 +- .../sync-urlconn-full-config.properties | 13 ++ extensions/amazon-dynamodb/runtime/pom.xml | 4 + .../runtime/ApacheHttpClientConfig.java | 135 ----------- .../runtime/DynamodbClientProducer.java | 56 +++-- .../dynamodb/runtime/DynamodbConfig.java | 4 +- .../runtime/SyncHttpClientConfig.java | 211 ++++++++++++++++++ integration-tests/amazon-dynamodb/pom.xml | 5 - .../src/main/resources/application.properties | 2 +- 18 files changed, 341 insertions(+), 189 deletions(-) rename extensions/amazon-dynamodb/deployment/src/test/java/io/quarkus/dynamodb/deployment/{DynamodbSyncClientBrokenConfigTest.java => DynamodbSyncApacheClientBrokenConfigTest.java} (85%) rename extensions/amazon-dynamodb/deployment/src/test/java/io/quarkus/dynamodb/deployment/{DynamodbSyncClientBrokenProxyConfigTest.java => DynamodbSyncApacheClientBrokenProxyConfigTest.java} (83%) rename extensions/amazon-dynamodb/deployment/src/test/java/io/quarkus/dynamodb/deployment/{DynamodbSyncClientFullConfigTest.java => DynamodbSyncApacheClientFullConfigTest.java} (81%) create mode 100644 extensions/amazon-dynamodb/deployment/src/test/java/io/quarkus/dynamodb/deployment/DynamodbSyncUrlConnClientFullConfigTest.java rename extensions/amazon-dynamodb/deployment/src/test/resources/{sync-broken-config.properties => sync-apache-broken-config.properties} (55%) rename extensions/amazon-dynamodb/deployment/src/test/resources/{sync-broken-proxy-config.properties => sync-apache-broken-proxy-config.properties} (75%) rename extensions/amazon-dynamodb/deployment/src/test/resources/{sync-full-config.properties => sync-apache-full-config.properties} (96%) create mode 100644 extensions/amazon-dynamodb/deployment/src/test/resources/sync-urlconn-full-config.properties delete mode 100644 extensions/amazon-dynamodb/runtime/src/main/java/io/quarkus/dynamodb/runtime/ApacheHttpClientConfig.java create mode 100644 extensions/amazon-dynamodb/runtime/src/main/java/io/quarkus/dynamodb/runtime/SyncHttpClientConfig.java diff --git a/bom/runtime/pom.xml b/bom/runtime/pom.xml index ad01dd2335a12..5dbf86a891c2d 100644 --- a/bom/runtime/pom.xml +++ b/bom/runtime/pom.xml @@ -2177,6 +2177,11 @@ apache-client ${awssdk.version} + + software.amazon.awssdk + url-connection-client + ${awssdk.version} + com.microsoft.azure.functions diff --git a/docs/src/main/asciidoc/dynamodb-guide.adoc b/docs/src/main/asciidoc/dynamodb-guide.adoc index 5897f16987826..d1f67c3750729 100644 --- a/docs/src/main/asciidoc/dynamodb-guide.adoc +++ b/docs/src/main/asciidoc/dynamodb-guide.adoc @@ -19,7 +19,7 @@ Keep in mind it's actively developed and does not support yet all the features a The Quarkus extension supports two programming models: -* Blocking access using the Apache HTTP Client +* Blocking access using URL Connection HTTP client (by default) or the Apache HTTP Client * https://docs.aws.amazon.com/sdk-for-java/v2/developer-guide/basics-async.html[Asynchronous programming] based on JDK's `CompletableFuture` objects and the Netty HTTP client. In this guide, we see how you can get your REST services to use the DynamoDB locally and on AWS. diff --git a/extensions/amazon-dynamodb/deployment/src/main/java/io/quarkus/dynamodb/deployment/DynamodbProcessor.java b/extensions/amazon-dynamodb/deployment/src/main/java/io/quarkus/dynamodb/deployment/DynamodbProcessor.java index 1b1f7f54528d2..00b35b509d078 100644 --- a/extensions/amazon-dynamodb/deployment/src/main/java/io/quarkus/dynamodb/deployment/DynamodbProcessor.java +++ b/extensions/amazon-dynamodb/deployment/src/main/java/io/quarkus/dynamodb/deployment/DynamodbProcessor.java @@ -27,12 +27,13 @@ import io.quarkus.deployment.builditem.substrate.SubstrateProxyDefinitionBuildItem; import io.quarkus.deployment.builditem.substrate.SubstrateResourceBuildItem; import io.quarkus.deployment.configuration.ConfigurationError; -import io.quarkus.dynamodb.runtime.ApacheHttpClientConfig; import io.quarkus.dynamodb.runtime.AwsCredentialsProviderType; import io.quarkus.dynamodb.runtime.DynamodbClientProducer; import io.quarkus.dynamodb.runtime.DynamodbConfig; import io.quarkus.dynamodb.runtime.DynamodbRecorder; import io.quarkus.dynamodb.runtime.NettyHttpClientConfig; +import io.quarkus.dynamodb.runtime.SyncHttpClientConfig; +import io.quarkus.dynamodb.runtime.SyncHttpClientConfig.SyncClientType; import io.quarkus.dynamodb.runtime.TlsManagersProviderConfig; import io.quarkus.dynamodb.runtime.TlsManagersProviderType; import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; @@ -40,6 +41,7 @@ import software.amazon.awssdk.http.apache.ApacheSdkHttpService; import software.amazon.awssdk.http.async.SdkAsyncHttpService; import software.amazon.awssdk.http.nio.netty.NettySdkAsyncHttpService; +import software.amazon.awssdk.http.urlconnection.UrlConnectionSdkHttpService; import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient; import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.awssdk.utils.StringUtils; @@ -112,14 +114,20 @@ DynamodbClientBuildItem analyzeDynamodbClientInjectionPoints(BeanRegistrationPha } if (createSyncClient) { - //Register Apache client as sync client - proxyDefinition - .produce(new SubstrateProxyDefinitionBuildItem("org.apache.http.conn.HttpClientConnectionManager", - "org.apache.http.pool.ConnPoolControl", - "software.amazon.awssdk.http.apache.internal.conn.Wrapped")); - - serviceProvider.produce( - new ServiceProviderBuildItem(SdkHttpService.class.getName(), ApacheSdkHttpService.class.getName())); + if (config.syncClient.type == SyncClientType.APACHE) { + //Register Apache client as sync client + proxyDefinition + .produce(new SubstrateProxyDefinitionBuildItem("org.apache.http.conn.HttpClientConnectionManager", + "org.apache.http.pool.ConnPoolControl", + "software.amazon.awssdk.http.apache.internal.conn.Wrapped")); + + serviceProvider.produce( + new ServiceProviderBuildItem(SdkHttpService.class.getName(), ApacheSdkHttpService.class.getName())); + } else { + serviceProvider.produce( + new ServiceProviderBuildItem(SdkHttpService.class.getName(), + UrlConnectionSdkHttpService.class.getName())); + } } if (createAsyncClient) { @@ -193,17 +201,19 @@ private static void checkConfig(DynamodbConfig config, List knownInterce } } - private static void checkSyncClientConfig(ApacheHttpClientConfig syncClient) { - if (syncClient.maxConnections <= 0) { - throw new ConfigurationError("quarkus.dynamodb.sync-client.max-connections may not be negative or zero."); - } - if (syncClient.proxy != null && syncClient.proxy.enabled) { - URI proxyEndpoint = syncClient.proxy.endpoint; - if (proxyEndpoint != null) { - validateProxyEndpoint(proxyEndpoint, "sync"); + private static void checkSyncClientConfig(SyncHttpClientConfig syncClient) { + if (syncClient.type == SyncClientType.APACHE) { + if (syncClient.apacheHttp.maxConnections <= 0) { + throw new ConfigurationError("quarkus.dynamodb.sync-client.max-connections may not be negative or zero."); + } + if (syncClient.apacheHttp.proxy != null && syncClient.apacheHttp.proxy.enabled) { + URI proxyEndpoint = syncClient.apacheHttp.proxy.endpoint; + if (proxyEndpoint != null) { + validateProxyEndpoint(proxyEndpoint, "sync"); + } } + validateTlsManagersProvider(syncClient.apacheHttp.tlsManagersProvider, "sync"); } - validateTlsManagersProvider(syncClient.tlsManagersProvider, "sync"); } private static void checkAsyncClientConfig(NettyHttpClientConfig asyncClient) { diff --git a/extensions/amazon-dynamodb/deployment/src/test/java/io/quarkus/dynamodb/deployment/DynamodbSyncClientBrokenConfigTest.java b/extensions/amazon-dynamodb/deployment/src/test/java/io/quarkus/dynamodb/deployment/DynamodbSyncApacheClientBrokenConfigTest.java similarity index 85% rename from extensions/amazon-dynamodb/deployment/src/test/java/io/quarkus/dynamodb/deployment/DynamodbSyncClientBrokenConfigTest.java rename to extensions/amazon-dynamodb/deployment/src/test/java/io/quarkus/dynamodb/deployment/DynamodbSyncApacheClientBrokenConfigTest.java index 7d441fbb81df2..00c747bc16b35 100644 --- a/extensions/amazon-dynamodb/deployment/src/test/java/io/quarkus/dynamodb/deployment/DynamodbSyncClientBrokenConfigTest.java +++ b/extensions/amazon-dynamodb/deployment/src/test/java/io/quarkus/dynamodb/deployment/DynamodbSyncApacheClientBrokenConfigTest.java @@ -12,7 +12,7 @@ import io.quarkus.test.QuarkusUnitTest; import software.amazon.awssdk.services.dynamodb.DynamoDbClient; -public class DynamodbSyncClientBrokenConfigTest { +public class DynamodbSyncApacheClientBrokenConfigTest { @Inject DynamoDbClient client; @@ -21,7 +21,7 @@ public class DynamodbSyncClientBrokenConfigTest { static final QuarkusUnitTest config = new QuarkusUnitTest() .setExpectedException(ConfigurationError.class) .setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class) - .addAsResource("sync-broken-config.properties", "application.properties")); + .addAsResource("sync-apache-broken-config.properties", "application.properties")); @Test public void test() { diff --git a/extensions/amazon-dynamodb/deployment/src/test/java/io/quarkus/dynamodb/deployment/DynamodbSyncClientBrokenProxyConfigTest.java b/extensions/amazon-dynamodb/deployment/src/test/java/io/quarkus/dynamodb/deployment/DynamodbSyncApacheClientBrokenProxyConfigTest.java similarity index 83% rename from extensions/amazon-dynamodb/deployment/src/test/java/io/quarkus/dynamodb/deployment/DynamodbSyncClientBrokenProxyConfigTest.java rename to extensions/amazon-dynamodb/deployment/src/test/java/io/quarkus/dynamodb/deployment/DynamodbSyncApacheClientBrokenProxyConfigTest.java index dbfda30aa76ed..dc786d20a4512 100644 --- a/extensions/amazon-dynamodb/deployment/src/test/java/io/quarkus/dynamodb/deployment/DynamodbSyncClientBrokenProxyConfigTest.java +++ b/extensions/amazon-dynamodb/deployment/src/test/java/io/quarkus/dynamodb/deployment/DynamodbSyncApacheClientBrokenProxyConfigTest.java @@ -12,7 +12,7 @@ import io.quarkus.test.QuarkusUnitTest; import software.amazon.awssdk.services.dynamodb.DynamoDbClient; -public class DynamodbSyncClientBrokenProxyConfigTest { +public class DynamodbSyncApacheClientBrokenProxyConfigTest { @Inject DynamoDbClient client; @@ -21,7 +21,7 @@ public class DynamodbSyncClientBrokenProxyConfigTest { static final QuarkusUnitTest config = new QuarkusUnitTest() .setExpectedException(ConfigurationError.class) .setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class) - .addAsResource("sync-broken-proxy-config.properties", "application.properties")); + .addAsResource("sync-apache-broken-proxy-config.properties", "application.properties")); @Test public void test() { diff --git a/extensions/amazon-dynamodb/deployment/src/test/java/io/quarkus/dynamodb/deployment/DynamodbSyncClientFullConfigTest.java b/extensions/amazon-dynamodb/deployment/src/test/java/io/quarkus/dynamodb/deployment/DynamodbSyncApacheClientFullConfigTest.java similarity index 81% rename from extensions/amazon-dynamodb/deployment/src/test/java/io/quarkus/dynamodb/deployment/DynamodbSyncClientFullConfigTest.java rename to extensions/amazon-dynamodb/deployment/src/test/java/io/quarkus/dynamodb/deployment/DynamodbSyncApacheClientFullConfigTest.java index a9a01aea4cb70..e2359f8881ad2 100644 --- a/extensions/amazon-dynamodb/deployment/src/test/java/io/quarkus/dynamodb/deployment/DynamodbSyncClientFullConfigTest.java +++ b/extensions/amazon-dynamodb/deployment/src/test/java/io/quarkus/dynamodb/deployment/DynamodbSyncApacheClientFullConfigTest.java @@ -10,7 +10,7 @@ import io.quarkus.test.QuarkusUnitTest; import software.amazon.awssdk.services.dynamodb.DynamoDbClient; -public class DynamodbSyncClientFullConfigTest { +public class DynamodbSyncApacheClientFullConfigTest { @Inject DynamoDbClient client; @@ -18,7 +18,7 @@ public class DynamodbSyncClientFullConfigTest { @RegisterExtension static final QuarkusUnitTest config = new QuarkusUnitTest() .setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class) - .addAsResource("sync-full-config.properties", "application.properties")); + .addAsResource("sync-apache-full-config.properties", "application.properties")); @Test public void test() { diff --git a/extensions/amazon-dynamodb/deployment/src/test/java/io/quarkus/dynamodb/deployment/DynamodbSyncUrlConnClientFullConfigTest.java b/extensions/amazon-dynamodb/deployment/src/test/java/io/quarkus/dynamodb/deployment/DynamodbSyncUrlConnClientFullConfigTest.java new file mode 100644 index 0000000000000..60f4541539333 --- /dev/null +++ b/extensions/amazon-dynamodb/deployment/src/test/java/io/quarkus/dynamodb/deployment/DynamodbSyncUrlConnClientFullConfigTest.java @@ -0,0 +1,27 @@ +package io.quarkus.dynamodb.deployment; + +import javax.inject.Inject; + +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 software.amazon.awssdk.services.dynamodb.DynamoDbClient; + +public class DynamodbSyncUrlConnClientFullConfigTest { + + @Inject + DynamoDbClient client; + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest() + .setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class) + .addAsResource("sync-urlconn-full-config.properties", "application.properties")); + + @Test + public void test() { + // Application should start with full config. + } +} diff --git a/extensions/amazon-dynamodb/deployment/src/test/resources/sync-broken-config.properties b/extensions/amazon-dynamodb/deployment/src/test/resources/sync-apache-broken-config.properties similarity index 55% rename from extensions/amazon-dynamodb/deployment/src/test/resources/sync-broken-config.properties rename to extensions/amazon-dynamodb/deployment/src/test/resources/sync-apache-broken-config.properties index 59f15da63db07..cbf663f84a3e3 100644 --- a/extensions/amazon-dynamodb/deployment/src/test/resources/sync-broken-config.properties +++ b/extensions/amazon-dynamodb/deployment/src/test/resources/sync-apache-broken-config.properties @@ -1,3 +1,4 @@ +quarkus.dynamodb.sync-client.type = APACHE quarkus.dynamodb.sync-client.max-connections = -10 diff --git a/extensions/amazon-dynamodb/deployment/src/test/resources/sync-broken-proxy-config.properties b/extensions/amazon-dynamodb/deployment/src/test/resources/sync-apache-broken-proxy-config.properties similarity index 75% rename from extensions/amazon-dynamodb/deployment/src/test/resources/sync-broken-proxy-config.properties rename to extensions/amazon-dynamodb/deployment/src/test/resources/sync-apache-broken-proxy-config.properties index 7c2cbb0657ab5..6b7ba246a0e57 100644 --- a/extensions/amazon-dynamodb/deployment/src/test/resources/sync-broken-proxy-config.properties +++ b/extensions/amazon-dynamodb/deployment/src/test/resources/sync-apache-broken-proxy-config.properties @@ -1,3 +1,4 @@ +quarkus.dynamodb.sync-client.type = APACHE quarkus.dynamodb.sync-client.proxy.enabled = true quarkus.dynamodb.sync-client.proxy.endpoint = http://user:name@127.1.1.1?foo=bar diff --git a/extensions/amazon-dynamodb/deployment/src/test/resources/sync-full-config.properties b/extensions/amazon-dynamodb/deployment/src/test/resources/sync-apache-full-config.properties similarity index 96% rename from extensions/amazon-dynamodb/deployment/src/test/resources/sync-full-config.properties rename to extensions/amazon-dynamodb/deployment/src/test/resources/sync-apache-full-config.properties index 6e2d315e514ec..afed8f4b7aee2 100644 --- a/extensions/amazon-dynamodb/deployment/src/test/resources/sync-full-config.properties +++ b/extensions/amazon-dynamodb/deployment/src/test/resources/sync-apache-full-config.properties @@ -6,11 +6,13 @@ quarkus.dynamodb.aws.credentials.type=STATIC quarkus.dynamodb.aws.credentials.static-provider.access-key-id=test-key quarkus.dynamodb.aws.credentials.static-provider.secret-access-key=test-secret +quarkus.dynamodb.sync-client.type = APACHE +quarkus.dynamodb.sync-client.socket-timeout = 0.100S +quarkus.dynamodb.sync-client.connection-timeout = 0.100S + quarkus.dynamodb.sync-client.connection-acquisition-timeout = 0.100S quarkus.dynamodb.sync-client.connection-max-idle-time = 0.100S -quarkus.dynamodb.sync-client.connection-timeout = 0.100S quarkus.dynamodb.sync-client.connection-time-to-live = 0.100S -quarkus.dynamodb.sync-client.socket-timeout = 0.100S quarkus.dynamodb.sync-client.max-connections = 10 quarkus.dynamodb.sync-client.expect-continue-enabled = true quarkus.dynamodb.sync-client.use-idle-connection-reaper = true diff --git a/extensions/amazon-dynamodb/deployment/src/test/resources/sync-urlconn-full-config.properties b/extensions/amazon-dynamodb/deployment/src/test/resources/sync-urlconn-full-config.properties new file mode 100644 index 0000000000000..be217010ffed5 --- /dev/null +++ b/extensions/amazon-dynamodb/deployment/src/test/resources/sync-urlconn-full-config.properties @@ -0,0 +1,13 @@ +quarkus.dynamodb.enable-endpoint-discovery=false +quarkus.dynamodb.endpoint-override=http://localhost:8000 + +quarkus.dynamodb.aws.region=us-east-2 +quarkus.dynamodb.aws.credentials.type=STATIC +quarkus.dynamodb.aws.credentials.static-provider.access-key-id=test-key +quarkus.dynamodb.aws.credentials.static-provider.secret-access-key=test-secret + +quarkus.dynamodb.sync-client.type = URL +quarkus.dynamodb.sync-client.socket-timeout = 0.100S +quarkus.dynamodb.sync-client.connection-timeout = 0.100S + + diff --git a/extensions/amazon-dynamodb/runtime/pom.xml b/extensions/amazon-dynamodb/runtime/pom.xml index a2f79a5b2ed5d..3e605efcb1710 100644 --- a/extensions/amazon-dynamodb/runtime/pom.xml +++ b/extensions/amazon-dynamodb/runtime/pom.xml @@ -35,6 +35,10 @@ software.amazon.awssdk netty-nio-client + + software.amazon.awssdk + url-connection-client + software.amazon.awssdk apache-client diff --git a/extensions/amazon-dynamodb/runtime/src/main/java/io/quarkus/dynamodb/runtime/ApacheHttpClientConfig.java b/extensions/amazon-dynamodb/runtime/src/main/java/io/quarkus/dynamodb/runtime/ApacheHttpClientConfig.java deleted file mode 100644 index c7304e570f224..0000000000000 --- a/extensions/amazon-dynamodb/runtime/src/main/java/io/quarkus/dynamodb/runtime/ApacheHttpClientConfig.java +++ /dev/null @@ -1,135 +0,0 @@ -package io.quarkus.dynamodb.runtime; - -import java.net.URI; -import java.time.Duration; -import java.util.List; -import java.util.Optional; - -import io.quarkus.runtime.annotations.ConfigGroup; -import io.quarkus.runtime.annotations.ConfigItem; - -@ConfigGroup -public class ApacheHttpClientConfig { - - /** - * The maximum amount of time to establish a connection before timing out. - */ - @ConfigItem(defaultValue = "2S") - public Duration connectionTimeout; - - /** - * The amount of time to wait when acquiring a connection from the pool before giving up and timing out. - */ - @ConfigItem(defaultValue = "10S") - public Duration connectionAcquisitionTimeout; - - /** - * The maximum amount of time that a connection should be allowed to remain open while idle. - */ - @ConfigItem(defaultValue = "60S") - public Duration connectionMaxIdleTime; - - /** - * The maximum amount of time that a connection should be allowed to remain open, regardless of usage frequency. - */ - @ConfigItem - public Optional connectionTimeToLive; - - /** - * The amount of time to wait for data to be transferred over an established, open connection before the connection is timed - * out. - */ - @ConfigItem(defaultValue = "30S") - public Duration socketTimeout; - - /** - * The maximum number of connections allowed in the connection pool. - *

- * Each built HTTP client has its own private connection pool. - */ - @ConfigItem(defaultValue = "50") - public int maxConnections; - - /** - * Whether the client should send an HTTP expect-continue handshake before each request. - */ - @ConfigItem(defaultValue = "true") - public boolean expectContinueEnabled; - - /** - * Whether the idle connections in the connection pool should be closed asynchronously. - *

- * When enabled, connections left idling for longer than `quarkus.dynamodb.sync-client.connection-max-idle-time` will be - * closed. - * This will not close connections currently in use. - */ - @ConfigItem(defaultValue = "true") - public boolean useIdleConnectionReaper; - - /** - * HTTP proxy configuration - */ - @ConfigItem - public HttpClientProxyConfiguration proxy; - - /** - * TLS Managers provider configuration - */ - @ConfigItem - public TlsManagersProviderConfig tlsManagersProvider; - - @ConfigGroup - public static class HttpClientProxyConfiguration { - - /** - * Enable HTTP proxy - */ - @ConfigItem - public boolean enabled; - - /** - * The endpoint of the proxy server that the SDK should connect through. - *

- * Currently, the endpoint is limited to a host and port. Any other URI components will result in an exception being - * raised. - */ - @ConfigItem - public URI endpoint; - - /** - * The username to use when connecting through a proxy. - */ - @ConfigItem - public Optional username; - - /** - * The password to use when connecting through a proxy. - */ - @ConfigItem - public Optional password; - - /** - * For NTLM proxies - the Windows domain name to use when authenticating with the proxy. - */ - @ConfigItem - public Optional ntlmDomain; - - /** - * For NTLM proxies - the Windows workstation name to use when authenticating with the proxy. - */ - @ConfigItem - public Optional ntlmWorkstation; - - /** - * Whether to attempt to authenticate preemptively against the proxy server using basic authentication. - */ - @ConfigItem - public Optional preemptiveBasicAuthenticationEnabled; - - /** - * The hosts that the client is allowed to access without going through the proxy. - */ - @ConfigItem - public List nonProxyHosts; - } -} diff --git a/extensions/amazon-dynamodb/runtime/src/main/java/io/quarkus/dynamodb/runtime/DynamodbClientProducer.java b/extensions/amazon-dynamodb/runtime/src/main/java/io/quarkus/dynamodb/runtime/DynamodbClientProducer.java index e51af99d30a4d..c94040ae7b408 100644 --- a/extensions/amazon-dynamodb/runtime/src/main/java/io/quarkus/dynamodb/runtime/DynamodbClientProducer.java +++ b/extensions/amazon-dynamodb/runtime/src/main/java/io/quarkus/dynamodb/runtime/DynamodbClientProducer.java @@ -11,9 +11,10 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import io.quarkus.dynamodb.runtime.SyncHttpClientConfig.ApacheHttpClientConfig; +import io.quarkus.dynamodb.runtime.SyncHttpClientConfig.SyncClientType; import software.amazon.awssdk.awscore.client.builder.AwsClientBuilder; import software.amazon.awssdk.core.client.builder.SdkClientBuilder; -import software.amazon.awssdk.core.client.builder.SdkSyncClientBuilder; import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; import software.amazon.awssdk.http.apache.ApacheHttpClient; @@ -21,6 +22,7 @@ import software.amazon.awssdk.http.apache.ProxyConfiguration; import software.amazon.awssdk.http.nio.netty.NettyNioAsyncHttpClient; import software.amazon.awssdk.http.nio.netty.SdkEventLoopGroup; +import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient; import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient; import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClientBuilder; import software.amazon.awssdk.services.dynamodb.DynamoDbBaseClientBuilder; @@ -101,40 +103,56 @@ private void initSdkClient(SdkClientBuilder builder, SdkConfig config) { } } - private void initHttpClient(SdkSyncClientBuilder builder, ApacheHttpClientConfig config) { - builder.httpClientBuilder(createApacheClientBuilder(config)); + private void initHttpClient(DynamoDbClientBuilder builder, SyncHttpClientConfig config) { + if (config.type == SyncClientType.APACHE) { + builder.httpClientBuilder(createApacheClientBuilder(config)); + } else { + builder.httpClientBuilder(createUrlConnectionClientBuilder(config)); + } } private void initHttpClient(DynamoDbAsyncClientBuilder builder, NettyHttpClientConfig config) { builder.httpClientBuilder(createNettyClientBuilder(config)); } - private ApacheHttpClient.Builder createApacheClientBuilder(ApacheHttpClientConfig config) { + private UrlConnectionHttpClient.Builder createUrlConnectionClientBuilder(SyncHttpClientConfig config) { + UrlConnectionHttpClient.Builder builder = UrlConnectionHttpClient.builder(); + builder.connectionTimeout(config.connectionTimeout); + builder.socketTimeout(config.socketTimeout); + return builder; + } + + private ApacheHttpClient.Builder createApacheClientBuilder(SyncHttpClientConfig config) { Builder builder = ApacheHttpClient.builder(); builder.connectionTimeout(config.connectionTimeout); - builder.connectionAcquisitionTimeout(config.connectionAcquisitionTimeout); - builder.connectionMaxIdleTime(config.connectionMaxIdleTime); - config.connectionTimeToLive.ifPresent(builder::connectionTimeToLive); - builder.expectContinueEnabled(config.expectContinueEnabled); - builder.maxConnections(config.maxConnections); builder.socketTimeout(config.socketTimeout); - builder.useIdleConnectionReaper(config.useIdleConnectionReaper); - if (config.proxy.enabled) { - ProxyConfiguration.Builder proxyBuilder = ProxyConfiguration.builder().endpoint(config.proxy.endpoint); - config.proxy.username.ifPresent(proxyBuilder::username); - config.proxy.password.ifPresent(proxyBuilder::password); - config.proxy.nonProxyHosts.forEach(proxyBuilder::addNonProxyHost); - config.proxy.ntlmDomain.ifPresent(proxyBuilder::ntlmDomain); - config.proxy.ntlmWorkstation.ifPresent(proxyBuilder::ntlmWorkstation); - config.proxy.preemptiveBasicAuthenticationEnabled + ApacheHttpClientConfig apacheHttpClientConfig = config.apacheHttp; + + builder.connectionAcquisitionTimeout(apacheHttpClientConfig.connectionAcquisitionTimeout); + builder.connectionMaxIdleTime(apacheHttpClientConfig.connectionMaxIdleTime); + apacheHttpClientConfig.connectionTimeToLive.ifPresent(builder::connectionTimeToLive); + builder.expectContinueEnabled(apacheHttpClientConfig.expectContinueEnabled); + builder.maxConnections(apacheHttpClientConfig.maxConnections); + builder.useIdleConnectionReaper(apacheHttpClientConfig.useIdleConnectionReaper); + + if (apacheHttpClientConfig.proxy.enabled) { + ProxyConfiguration.Builder proxyBuilder = ProxyConfiguration.builder() + .endpoint(apacheHttpClientConfig.proxy.endpoint); + apacheHttpClientConfig.proxy.username.ifPresent(proxyBuilder::username); + apacheHttpClientConfig.proxy.password.ifPresent(proxyBuilder::password); + apacheHttpClientConfig.proxy.nonProxyHosts.forEach(proxyBuilder::addNonProxyHost); + apacheHttpClientConfig.proxy.ntlmDomain.ifPresent(proxyBuilder::ntlmDomain); + apacheHttpClientConfig.proxy.ntlmWorkstation.ifPresent(proxyBuilder::ntlmWorkstation); + apacheHttpClientConfig.proxy.preemptiveBasicAuthenticationEnabled .ifPresent(proxyBuilder::preemptiveBasicAuthenticationEnabled); builder.proxyConfiguration(proxyBuilder.build()); } - builder.tlsKeyManagersProvider(config.tlsManagersProvider.type.create(config.tlsManagersProvider)); + builder.tlsKeyManagersProvider( + apacheHttpClientConfig.tlsManagersProvider.type.create(apacheHttpClientConfig.tlsManagersProvider)); return builder; } diff --git a/extensions/amazon-dynamodb/runtime/src/main/java/io/quarkus/dynamodb/runtime/DynamodbConfig.java b/extensions/amazon-dynamodb/runtime/src/main/java/io/quarkus/dynamodb/runtime/DynamodbConfig.java index 2cc94c57b21e2..385dc2125247f 100644 --- a/extensions/amazon-dynamodb/runtime/src/main/java/io/quarkus/dynamodb/runtime/DynamodbConfig.java +++ b/extensions/amazon-dynamodb/runtime/src/main/java/io/quarkus/dynamodb/runtime/DynamodbConfig.java @@ -26,10 +26,10 @@ public class DynamodbConfig { public AwsConfig aws; /** - * Apache HTTP client transport configuration + * Sync client transport configuration */ @ConfigItem - public ApacheHttpClientConfig syncClient; + public SyncHttpClientConfig syncClient; /** * Netty HTTP client transport configuration diff --git a/extensions/amazon-dynamodb/runtime/src/main/java/io/quarkus/dynamodb/runtime/SyncHttpClientConfig.java b/extensions/amazon-dynamodb/runtime/src/main/java/io/quarkus/dynamodb/runtime/SyncHttpClientConfig.java new file mode 100644 index 0000000000000..909e62a51bb37 --- /dev/null +++ b/extensions/amazon-dynamodb/runtime/src/main/java/io/quarkus/dynamodb/runtime/SyncHttpClientConfig.java @@ -0,0 +1,211 @@ +package io.quarkus.dynamodb.runtime; + +import java.net.URI; +import java.time.Duration; +import java.util.List; +import java.util.Optional; + +import io.quarkus.runtime.annotations.ConfigGroup; +import io.quarkus.runtime.annotations.ConfigItem; + +@ConfigGroup +public class SyncHttpClientConfig { + + /** + * Type of the sync HTTP client implementation + */ + @ConfigItem(defaultValue = "url") + public SyncClientType type; + + /** + * The maximum amount of time to establish a connection before timing out. + * + *

+ * Used by `URL` and `APACHE` clients + */ + @ConfigItem(defaultValue = "2S") + public Duration connectionTimeout; + + /** + * The amount of time to wait for data to be transferred over an established, open connection before the connection is + * timed + * out. + * + *

+ * Used by `URL` and `APACHE` clients + */ + @ConfigItem(defaultValue = "30S") + public Duration socketTimeout; + + /** + * Apache HTTP client additional configuration + */ + @ConfigItem(name = ConfigItem.PARENT) + public ApacheHttpClientConfig apacheHttp; + + @ConfigGroup + public static class ApacheHttpClientConfig { + + /** + * The amount of time to wait when acquiring a connection from the pool before giving up and timing out. + * + *

+ * Used by `APACHE` client only + */ + @ConfigItem(defaultValue = "10S") + public Duration connectionAcquisitionTimeout; + + /** + * The maximum amount of time that a connection should be allowed to remain open while idle. + * + *

+ * Used by `APACHE` client only + */ + @ConfigItem(defaultValue = "60S") + public Duration connectionMaxIdleTime; + + /** + * The maximum amount of time that a connection should be allowed to remain open, regardless of usage frequency. + * + *

+ * Used by `APACHE` client only + */ + @ConfigItem + public Optional connectionTimeToLive; + + /** + * The maximum number of connections allowed in the connection pool. + *

+ * Each built HTTP client has its own private connection pool. + * + *

+ * Used by `APACHE` client only + */ + @ConfigItem(defaultValue = "50") + public int maxConnections; + + /** + * Whether the client should send an HTTP expect-continue handshake before each request. + * + *

+ * Used by `APACHE` client only + */ + @ConfigItem(defaultValue = "true") + public boolean expectContinueEnabled; + + /** + * Whether the idle connections in the connection pool should be closed asynchronously. + *

+ * When enabled, connections left idling for longer than `quarkus.dynamodb.sync-client.connection-max-idle-time` will be + * closed. + * This will not close connections currently in use. + * + *

+ * Used by `APACHE` client only + */ + @ConfigItem(defaultValue = "true") + public boolean useIdleConnectionReaper; + + /** + * HTTP proxy configuration + * + *

+ * Used by `APACHE` client only + */ + @ConfigItem + public HttpClientProxyConfiguration proxy; + + /** + * TLS Managers provider configuration + * + *

+ * Used by `APACHE` client only + */ + @ConfigItem + public TlsManagersProviderConfig tlsManagersProvider; + + @ConfigGroup + public static class HttpClientProxyConfiguration { + + /** + * Enable HTTP proxy + * + *

+ * Used by `APACHE` client only + */ + @ConfigItem + public boolean enabled; + + /** + * The endpoint of the proxy server that the SDK should connect through. + *

+ * Currently, the endpoint is limited to a host and port. Any other URI components will result in an exception being + * raised. + * + *

+ * Used by `APACHE` client only + */ + @ConfigItem + public URI endpoint; + + /** + * The username to use when connecting through a proxy. + * + *

+ * Used by `APACHE` client only + */ + @ConfigItem + public Optional username; + + /** + * The password to use when connecting through a proxy. + * + *

+ * Used by `APACHE` client only + */ + @ConfigItem + public Optional password; + + /** + * For NTLM proxies - the Windows domain name to use when authenticating with the proxy. + * + *

+ * Used by `APACHE` client only + */ + @ConfigItem + public Optional ntlmDomain; + + /** + * For NTLM proxies - the Windows workstation name to use when authenticating with the proxy. + * + *

+ * Used by `APACHE` client only + */ + @ConfigItem + public Optional ntlmWorkstation; + + /** + * Whether to attempt to authenticate preemptively against the proxy server using basic authentication. + * + *

+ * Used by `APACHE` client only + */ + @ConfigItem + public Optional preemptiveBasicAuthenticationEnabled; + + /** + * The hosts that the client is allowed to access without going through the proxy. + * + *

+ * Used by `APACHE` client only + */ + @ConfigItem + public List nonProxyHosts; + } + } + + public enum SyncClientType { + URL, + APACHE + } +} diff --git a/integration-tests/amazon-dynamodb/pom.xml b/integration-tests/amazon-dynamodb/pom.xml index 0cdcc82c56583..1efbccece9f7d 100644 --- a/integration-tests/amazon-dynamodb/pom.xml +++ b/integration-tests/amazon-dynamodb/pom.xml @@ -49,11 +49,6 @@ quarkus-junit5 test - - org.glassfish - javax.json - test - io.rest-assured rest-assured diff --git a/integration-tests/amazon-dynamodb/src/main/resources/application.properties b/integration-tests/amazon-dynamodb/src/main/resources/application.properties index 1f38bea809410..f1ee803f3215d 100644 --- a/integration-tests/amazon-dynamodb/src/main/resources/application.properties +++ b/integration-tests/amazon-dynamodb/src/main/resources/application.properties @@ -5,4 +5,4 @@ quarkus.dynamodb.aws.credentials.type=STATIC quarkus.dynamodb.aws.credentials.static-provider.access-key-id=test-key quarkus.dynamodb.aws.credentials.static-provider.secret-access-key=test-secret -quarkus.dynamodb.interceptors=io.quarkus.it.dynamodb.DynamoDBModifyResponse \ No newline at end of file +quarkus.dynamodb.interceptors=io.quarkus.it.dynamodb.DynamoDBModifyResponse