Skip to content

Commit

Permalink
Ability to specify different HTTP clients
Browse files Browse the repository at this point in the history
  • Loading branch information
musketyr committed Oct 10, 2024
1 parent c88ba54 commit 00820c4
Show file tree
Hide file tree
Showing 25 changed files with 309 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@ dependencies {
api "software.amazon.awssdk:sts:$project.awsSdk2Version"
api "software.amazon.awssdk:aws-query-protocol:$project.awsSdk2Version"

// HTTP clients
api "software.amazon.awssdk:aws-crt-client:$project.awsSdk2Version"
api "software.amazon.awssdk:url-connection-client:$project.awsSdk2Version"
api "software.amazon.awssdk:netty-nio-client:$project.awsSdk2Version"
api "software.amazon.awssdk:apache-client:$project.awsSdk2Version"

api group: 'com.amazonaws', name: 'amazon-dax-client', version: '1.0.230341.0'
api group: 'com.amazonaws', name: 'aws-lambda-java-events', version: awsLambdaEventsVersion
api group: 'com.fasterxml.jackson.dataformat', name: 'jackson-dataformat-cbor', version: project['jackson.datatype.version']
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
*/
package com.agorapulse.micronaut.amazon.awssdk.cloudwatch;

import com.agorapulse.micronaut.amazon.awssdk.core.client.ClientBuilderProvider;
import io.micronaut.context.annotation.Bean;
import io.micronaut.context.annotation.Factory;
import io.micronaut.context.annotation.Requires;
Expand Down Expand Up @@ -44,10 +45,11 @@ public class CloudWatchFactory {
CloudWatchClient cloudWatch(
AwsCredentialsProvider credentialsProvider,
AwsRegionProvider awsRegionProvider,
ClientBuilderProvider builderProvider,
CloudWatchConfiguration configuration
) {
return configuration
.configure(CloudWatchClient.builder().credentialsProvider(credentialsProvider), awsRegionProvider)
.configure(CloudWatchClient.builder().credentialsProvider(credentialsProvider), awsRegionProvider, builderProvider)
.build();
}

Expand All @@ -58,10 +60,11 @@ CloudWatchAsyncClient cloudWatchAsync(
AwsCredentialsProvider credentialsProvider,
AwsRegionProvider awsRegionProvider,
CloudWatchConfiguration configuration,
ClientBuilderProvider builderProvider,
Optional<SdkAsyncHttpClient> httpClient
) {
CloudWatchAsyncClientBuilder builder = configuration
.configure(CloudWatchAsyncClient.builder().credentialsProvider(credentialsProvider), awsRegionProvider);
.configure(CloudWatchAsyncClient.builder().credentialsProvider(credentialsProvider), awsRegionProvider, builderProvider);
httpClient.ifPresent(builder::httpClient);
return builder.build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
*/
package com.agorapulse.micronaut.amazon.awssdk.cloudwatchlogs;

import com.agorapulse.micronaut.amazon.awssdk.core.client.ClientBuilderProvider;
import io.micronaut.aws.sdk.v2.service.cloudwatchlogs.CloudwatchLogsClientFactory;
import io.micronaut.context.annotation.Bean;
import io.micronaut.context.annotation.Factory;
Expand Down Expand Up @@ -47,10 +48,11 @@ public class CloudWatchLogsFactory {
CloudWatchLogsClient cloudWatchLogs(
AwsCredentialsProvider credentialsProvider,
AwsRegionProvider awsRegionProvider,
ClientBuilderProvider builderProvider,
CloudWatchLogsConfiguration configuration
) {
return configuration
.configure(CloudWatchLogsClient.builder().credentialsProvider(credentialsProvider), awsRegionProvider)
.configure(CloudWatchLogsClient.builder().credentialsProvider(credentialsProvider), awsRegionProvider, builderProvider)
.build();
}

Expand All @@ -61,11 +63,12 @@ CloudWatchLogsClient cloudWatchLogs(
CloudWatchLogsAsyncClient cloudWatchAsync(
AwsCredentialsProvider credentialsProvider,
AwsRegionProvider awsRegionProvider,
ClientBuilderProvider builderProvider,
CloudWatchLogsConfiguration configuration,
Optional<SdkAsyncHttpClient> httpClient
) {
CloudWatchLogsAsyncClientBuilder builder = configuration
.configure(CloudWatchLogsAsyncClient.builder().credentialsProvider(credentialsProvider), awsRegionProvider);
.configure(CloudWatchLogsAsyncClient.builder().credentialsProvider(credentialsProvider), awsRegionProvider, builderProvider);
httpClient.ifPresent(builder::httpClient);
return builder.build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,15 @@
*/
dependencies {
api 'software.amazon.awssdk:aws-core'

// HTTP clients
compileOnly "software.amazon.awssdk:aws-crt-client:$project.awsSdk2Version"
compileOnly "software.amazon.awssdk:url-connection-client:$project.awsSdk2Version"
compileOnly "software.amazon.awssdk:netty-nio-client:$project.awsSdk2Version"
compileOnly "software.amazon.awssdk:apache-client:$project.awsSdk2Version"

testImplementation "software.amazon.awssdk:aws-crt-client:$project.awsSdk2Version"
testImplementation "software.amazon.awssdk:url-connection-client:$project.awsSdk2Version"
testImplementation "software.amazon.awssdk:netty-nio-client:$project.awsSdk2Version"
testImplementation "software.amazon.awssdk:apache-client:$project.awsSdk2Version"
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,25 @@ public void setEndpoint(String endpoint) {
this.endpoint = endpoint;
}

public String getClient() {
return client;
}

public void setClient(String client) {
this.client = client;
}

public String getAsyncClient() {
return asyncClient;
}

public void setAsyncClient(String asyncClient) {
this.asyncClient = asyncClient;
}

@Nullable private String region;
@Nullable private String endpoint;
@Nullable private String client;
@Nullable private String asyncClient;

}
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,11 @@
*/
package com.agorapulse.micronaut.amazon.awssdk.core;

import com.agorapulse.micronaut.amazon.awssdk.core.client.ClientBuilderProvider;
import software.amazon.awssdk.awscore.client.builder.AwsAsyncClientBuilder;
import software.amazon.awssdk.awscore.client.builder.AwsClientBuilder;
import software.amazon.awssdk.awscore.presigner.SdkPresigner;
import software.amazon.awssdk.core.client.builder.SdkSyncClientBuilder;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.regions.providers.AwsRegionProvider;

Expand All @@ -32,7 +35,11 @@ public interface RegionAndEndpointConfiguration {

String getEndpoint();

default <C, B extends AwsClientBuilder<B, C>> B configure(B builder, AwsRegionProvider awsRegionProvider) {
String getClient();

String getAsyncClient();

default <C, B extends AwsClientBuilder<B, C>> B configure(B builder, AwsRegionProvider awsRegionProvider, ClientBuilderProvider builderProvider) {
builder.region(Optional.ofNullable(getRegion()).map(Region::of).orElseGet(awsRegionProvider::getRegion));

if (getEndpoint() != null) {
Expand All @@ -43,6 +50,14 @@ default <C, B extends AwsClientBuilder<B, C>> B configure(B builder, AwsRegionPr
}
}

if (getClient() != null && builder instanceof SdkSyncClientBuilder<?,?> clientBuilder) {
builderProvider.findHttpClientBuilder(getClient()).ifPresent(clientBuilder::httpClientBuilder);
}

if (getAsyncClient() != null && builder instanceof AwsAsyncClientBuilder<?,?> clientBuilder) {
builderProvider.findAsyncHttpClientBuilder(getClient()).ifPresent(clientBuilder::httpClientBuilder);
}

return builder;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.agorapulse.micronaut.amazon.awssdk.core.client;

import io.micronaut.context.annotation.Bean;
import io.micronaut.context.annotation.Factory;
import io.micronaut.context.annotation.Requires;
import jakarta.inject.Named;
import jakarta.inject.Singleton;
import software.amazon.awssdk.http.SdkHttpClient;
import software.amazon.awssdk.http.apache.ApacheHttpClient;

@Factory
@Requires(classes = ApacheHttpClient.class)
public class ApacheHttpClientBuilderFactory {

@Bean
@Singleton
@Named("apache")
public SdkHttpClient.Builder<ApacheHttpClient.Builder> awsCrtHttpClientBuilder() {
return ApacheHttpClient.builder();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.agorapulse.micronaut.amazon.awssdk.core.client;

import io.micronaut.context.annotation.Bean;
import io.micronaut.context.annotation.Factory;
import io.micronaut.context.annotation.Requires;
import jakarta.inject.Named;
import jakarta.inject.Singleton;
import software.amazon.awssdk.http.SdkHttpClient;
import software.amazon.awssdk.http.async.SdkAsyncHttpClient;
import software.amazon.awssdk.http.crt.AwsCrtAsyncHttpClient;
import software.amazon.awssdk.http.crt.AwsCrtHttpClient;

@Factory
@Requires(classes = {AwsCrtHttpClient.class, AwsCrtAsyncHttpClient.class})
public class AwsCrtHttpClientBuilderFactory {

@Bean
@Singleton
@Named("aws-crt")
public SdkAsyncHttpClient.Builder<AwsCrtAsyncHttpClient.Builder> awsCrtHttpAsyncClientBuilder() {
return AwsCrtAsyncHttpClient.builder();
}

@Bean
@Singleton
@Named("aws-crt")
public SdkHttpClient.Builder<AwsCrtHttpClient.Builder> awsCrtHttpClientBuilder() {
return AwsCrtHttpClient.builder();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.agorapulse.micronaut.amazon.awssdk.core.client;

import software.amazon.awssdk.http.SdkHttpClient;
import software.amazon.awssdk.http.async.SdkAsyncHttpClient;

import java.util.Optional;

public interface ClientBuilderProvider {

String APACHE = "apache";
String AWS_CRT = "aws-crt";
String URL_CONNECTION = "url-connection";
String NETTY = "netty";

<B extends SdkHttpClient.Builder<B>> Optional<SdkHttpClient.Builder<B>> findHttpClientBuilder(String implementation);

<B extends SdkAsyncHttpClient.Builder<B>> Optional<SdkAsyncHttpClient.Builder<B>> findAsyncHttpClientBuilder(String implementation);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.agorapulse.micronaut.amazon.awssdk.core.client;

import io.micronaut.context.annotation.Bean;
import software.amazon.awssdk.http.SdkHttpClient;
import software.amazon.awssdk.http.async.SdkAsyncHttpClient;

import java.util.Map;
import java.util.Optional;

@Bean
public class DefaultClientBuilderProvider implements ClientBuilderProvider {

private final Map<String, SdkHttpClient.Builder<?>> httpClientBuilders;
private final Map<String, SdkAsyncHttpClient.Builder<?>> httpAsyncClientBuilders;

public DefaultClientBuilderProvider(Map<String, SdkHttpClient.Builder<?>> httpClientBuilders, Map<String, SdkAsyncHttpClient.Builder<?>> httpAsyncClientBuilders) {
this.httpClientBuilders = httpClientBuilders;
this.httpAsyncClientBuilders = httpAsyncClientBuilders;
}

@Override
public <B extends SdkHttpClient.Builder<B>> Optional<SdkHttpClient.Builder<B>> findHttpClientBuilder(String implementation) {
return Optional.ofNullable((SdkHttpClient.Builder<B>) httpClientBuilders.get(implementation));
}

@Override
public <B extends SdkAsyncHttpClient.Builder<B>> Optional<SdkAsyncHttpClient.Builder<B>> findAsyncHttpClientBuilder(String implementation) {
return Optional.ofNullable((SdkAsyncHttpClient.Builder<B>) httpAsyncClientBuilders.get(implementation));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.agorapulse.micronaut.amazon.awssdk.core.client;

import io.micronaut.context.annotation.Bean;
import io.micronaut.context.annotation.Factory;
import io.micronaut.context.annotation.Requires;
import jakarta.inject.Named;
import jakarta.inject.Singleton;
import software.amazon.awssdk.http.async.SdkAsyncHttpClient;
import software.amazon.awssdk.http.nio.netty.NettyNioAsyncHttpClient;

@Factory
@Requires(classes = NettyNioAsyncHttpClient.class)
public class NettyHttpClientBuilderFactory {

@Bean
@Singleton
@Named("netty")
public SdkAsyncHttpClient.Builder<NettyNioAsyncHttpClient.Builder> nettyHttpAsyncClientBuilder() {
return NettyNioAsyncHttpClient.builder();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.agorapulse.micronaut.amazon.awssdk.core.client;

import io.micronaut.context.annotation.Bean;
import io.micronaut.context.annotation.Factory;
import io.micronaut.context.annotation.Requires;
import jakarta.inject.Named;
import jakarta.inject.Singleton;
import software.amazon.awssdk.http.SdkHttpClient;
import software.amazon.awssdk.http.async.SdkAsyncHttpClient;
import software.amazon.awssdk.http.crt.AwsCrtAsyncHttpClient;
import software.amazon.awssdk.http.crt.AwsCrtHttpClient;
import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient;

@Factory
@Requires(classes = UrlConnectionHttpClient.class)
public class UrlConnectionHttpClientBuilderFactory {

@Bean
@Singleton
@Named("url-connection")
public SdkHttpClient.Builder<UrlConnectionHttpClient.Builder> awsCrtHttpClientBuilder() {
return UrlConnectionHttpClient.builder();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.agorapulse.micronaut.amazon.awssdk.core.client

import io.micronaut.test.extensions.spock.annotation.MicronautTest
import jakarta.inject.Inject
import spock.lang.Specification

@MicronautTest
class ClientBuilderProviderSpec extends Specification {

@Inject ClientBuilderProvider provider

void 'known providers found'() {
expect:
verifyAll(provider) {
findHttpClientBuilder(ClientBuilderProvider.APACHE).present
findHttpClientBuilder(ClientBuilderProvider.AWS_CRT).present
findHttpClientBuilder(ClientBuilderProvider.URL_CONNECTION).present

findAsyncHttpClientBuilder(ClientBuilderProvider.NETTY).present
findAsyncHttpClientBuilder(ClientBuilderProvider.AWS_CRT).present
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ dependencies {
testImplementation project(':micronaut-amazon-awssdk-integration-testing')
testImplementation 'io.micronaut.rxjava2:micronaut-rxjava2'
testImplementation 'io.micronaut:micronaut-jackson-databind'

testImplementation "software.amazon.awssdk:aws-crt-client:$project.awsSdk2Version"
testImplementation "software.amazon.awssdk:url-connection-client:$project.awsSdk2Version"
testImplementation "software.amazon.awssdk:netty-nio-client:$project.awsSdk2Version"
testImplementation "software.amazon.awssdk:apache-client:$project.awsSdk2Version"
}

if (project.findProperty('test.aws.dynamodb.v2') == 'async') {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
*/
package com.agorapulse.micronaut.amazon.awssdk.dynamodb;

import com.agorapulse.micronaut.amazon.awssdk.core.client.ClientBuilderProvider;
import io.micronaut.aws.sdk.v2.service.dynamodb.DynamoDbClientFactory;
import io.micronaut.context.annotation.Bean;
import io.micronaut.context.annotation.Factory;
Expand Down Expand Up @@ -45,10 +46,11 @@ public class DynamoDBClientsFactory {
public DynamoDbClient dynamoDbClient(
DynamoDBConfiguration configuration,
AwsCredentialsProvider awsCredentialsProvider,
AwsRegionProvider awsRegionProvider
AwsRegionProvider awsRegionProvider,
ClientBuilderProvider builderProvider
) {
DynamoDbClientBuilder builder = DynamoDbClient.builder().credentialsProvider(awsCredentialsProvider);
configuration.configure(builder, awsRegionProvider);
configuration.configure(builder, awsRegionProvider, builderProvider);
return builder.build();
}

Expand All @@ -59,10 +61,11 @@ public DynamoDbAsyncClient dynamoDbAsyncClient(
DynamoDBConfiguration configuration,
AwsCredentialsProvider awsCredentialsProvider,
AwsRegionProvider awsRegionProvider,
ClientBuilderProvider builderProvider,
Optional<SdkAsyncHttpClient> httpClient
) {
DynamoDbAsyncClientBuilder builder = DynamoDbAsyncClient.builder().credentialsProvider(awsCredentialsProvider);
configuration.configure(builder, awsRegionProvider);
configuration.configure(builder, awsRegionProvider, builderProvider);
httpClient.ifPresent(builder::httpClient);
return builder.build();
}
Expand Down
Loading

0 comments on commit 00820c4

Please sign in to comment.