Skip to content

Commit 462851b

Browse files
committed
aws: add aws-sdk-v2 module
- fix #3516
1 parent c4f7ea6 commit 462851b

6 files changed

Lines changed: 300 additions & 8 deletions

File tree

modules/jooby-awssdk-v1/src/main/java/io/jooby/awssdkv1/AwsModule.java

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,7 @@
55
*/
66
package io.jooby.awssdkv1;
77

8-
import java.util.ArrayList;
9-
import java.util.Collection;
10-
import java.util.List;
11-
import java.util.Objects;
8+
import java.util.*;
129
import java.util.function.Consumer;
1310
import java.util.function.Function;
1411
import java.util.stream.Stream;
@@ -26,7 +23,6 @@
2623
import io.jooby.Extension;
2724
import io.jooby.Jooby;
2825
import io.jooby.ServiceRegistry;
29-
import io.jooby.internal.awssdkv1.ConfigCredentialsProvider;
3026
import io.jooby.internal.awssdkv1.ServiceShutdown;
3127

3228
/**
@@ -64,6 +60,15 @@
6460
public class AwsModule implements Extension {
6561

6662
private final List<Function<AWSCredentialsProvider, Object>> factoryList = new ArrayList<>();
63+
private final AWSCredentialsProvider credentialsProvider;
64+
65+
public AwsModule(@NonNull AWSCredentialsProvider credentialsProvider) {
66+
this.credentialsProvider = credentialsProvider;
67+
}
68+
69+
public AwsModule() {
70+
this.credentialsProvider = null;
71+
}
6772

6873
/**
6974
* Setup a new AWS service. Supported outputs are:
@@ -83,7 +88,9 @@ public class AwsModule implements Extension {
8388

8489
@Override
8590
public void install(@NonNull Jooby application) throws Exception {
86-
AWSCredentialsProvider credentialsProvider = newCredentialsProvider(application.getConfig());
91+
var credentialsProvider =
92+
Optional.ofNullable(this.credentialsProvider)
93+
.orElseGet(() -> newCredentialsProvider(application.getConfig()));
8794
List<Object> serviceList = new ArrayList<>(factoryList.size());
8895
for (Function<AWSCredentialsProvider, Object> factory : factoryList) {
8996
Object value = factory.apply(credentialsProvider);

modules/jooby-awssdk-v1/src/main/java/io/jooby/internal/awssdkv1/ConfigCredentialsProvider.java renamed to modules/jooby-awssdk-v1/src/main/java/io/jooby/awssdkv1/ConfigCredentialsProvider.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* Apache License Version 2.0 https://jooby.io/LICENSE.txt
44
* Copyright 2014 Edgar Espina
55
*/
6-
package io.jooby.internal.awssdkv1;
6+
package io.jooby.awssdkv1;
77

88
import static com.amazonaws.SDKGlobalConfiguration.ACCESS_KEY_SYSTEM_PROPERTY;
99
import static com.amazonaws.SDKGlobalConfiguration.SECRET_KEY_SYSTEM_PROPERTY;
@@ -17,7 +17,7 @@
1717

1818
public class ConfigCredentialsProvider implements AWSCredentialsProvider {
1919

20-
private Config config;
20+
private final Config config;
2121

2222
public ConfigCredentialsProvider(Config config) {
2323
this.config = config;

modules/jooby-awssdk-v2/pom.xml

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
5+
6+
<parent>
7+
<groupId>io.jooby</groupId>
8+
<artifactId>modules</artifactId>
9+
<version>3.3.1-SNAPSHOT</version>
10+
</parent>
11+
12+
<modelVersion>4.0.0</modelVersion>
13+
<artifactId>jooby-awssdk-v2</artifactId>
14+
15+
<properties>
16+
<aws.java.sdk.version>2.20.43</aws.java.sdk.version>
17+
18+
<Module-Name>io.jooby.awssdkv2</Module-Name>
19+
</properties>
20+
21+
<dependencies>
22+
<dependency>
23+
<groupId>io.jooby</groupId>
24+
<artifactId>jooby</artifactId>
25+
<version>${jooby.version}</version>
26+
</dependency>
27+
28+
<dependency>
29+
<groupId>software.amazon.awssdk</groupId>
30+
<artifactId>sdk-core</artifactId>
31+
</dependency>
32+
33+
<dependency>
34+
<groupId>software.amazon.awssdk</groupId>
35+
<artifactId>s3</artifactId>
36+
<optional>true</optional>
37+
</dependency>
38+
39+
<dependency>
40+
<groupId>software.amazon.awssdk</groupId>
41+
<artifactId>s3-transfer-manager</artifactId>
42+
<optional>true</optional>
43+
</dependency>
44+
45+
<!-- Test dependencies -->
46+
<dependency>
47+
<groupId>org.junit.jupiter</groupId>
48+
<artifactId>junit-jupiter-engine</artifactId>
49+
<scope>test</scope>
50+
</dependency>
51+
52+
<dependency>
53+
<groupId>org.jacoco</groupId>
54+
<artifactId>org.jacoco.agent</artifactId>
55+
<classifier>runtime</classifier>
56+
<scope>test</scope>
57+
</dependency>
58+
59+
<dependency>
60+
<groupId>io.jooby</groupId>
61+
<artifactId>jooby-test</artifactId>
62+
<scope>test</scope>
63+
</dependency>
64+
</dependencies>
65+
66+
<dependencyManagement>
67+
<dependencies>
68+
<dependency>
69+
<groupId>software.amazon.awssdk</groupId>
70+
<artifactId>bom</artifactId>
71+
<version>${aws.java.sdk.version}</version>
72+
<type>pom</type>
73+
<scope>import</scope>
74+
</dependency>
75+
</dependencies>
76+
</dependencyManagement>
77+
<build>
78+
<plugins>
79+
<plugin>
80+
<groupId>org.apache.maven.plugins</groupId>
81+
<artifactId>maven-jar-plugin</artifactId>
82+
<version>${maven-jar-plugin.version}</version>
83+
<configuration>
84+
<archive>
85+
<manifestEntries>
86+
<Automatic-Module-Name>${Module-Name}</Automatic-Module-Name>
87+
</manifestEntries>
88+
</archive>
89+
</configuration>
90+
</plugin>
91+
</plugins>
92+
</build>
93+
</project>
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
/*
2+
* Jooby https://jooby.io
3+
* Apache License Version 2.0 https://jooby.io/LICENSE.txt
4+
* Copyright 2014 Edgar Espina
5+
*/
6+
package io.jooby.awssdkv2;
7+
8+
import java.util.*;
9+
import java.util.function.Function;
10+
import java.util.stream.Stream;
11+
12+
import com.typesafe.config.Config;
13+
import edu.umd.cs.findbugs.annotations.NonNull;
14+
import io.jooby.Extension;
15+
import io.jooby.Jooby;
16+
import io.jooby.ServiceRegistry;
17+
import software.amazon.awssdk.auth.credentials.*;
18+
import software.amazon.awssdk.utils.SdkAutoCloseable;
19+
20+
/**
21+
* Aws module for aws-java-sdk 2.x. This module:
22+
*
23+
* <p>- Integrates AWS credentials within application properties.
24+
*
25+
* <p>- Register AWS services as application services (so they can be used by require calls or DI).
26+
*
27+
* <p>- Add graceful shutdown to any {@link SdkAutoCloseable} instance.
28+
*
29+
* <p>Usage:
30+
*
31+
* <pre>{@code
32+
* {
33+
* install(
34+
* new AwsModule()
35+
* .setup(credentials -> {
36+
* var s3 = S3Client.builder().region(Region.US_EAST_1).build();
37+
* var s3transfer = S3TransferManager.builder().s3Client(s3).build()
38+
* return Stream.of(s3, s3transfer);
39+
* })
40+
* );
41+
* }
42+
* }</pre>
43+
*
44+
* <p>Previous example register AmazonS3Client and TransferManager services
45+
*
46+
* <p>NOTE: You need to add the service dependencies to your project.
47+
*
48+
* @author edgar
49+
* @since 3.3.1
50+
*/
51+
public class AwsModule implements Extension {
52+
private final AwsCredentialsProvider credentialsProvider;
53+
private final List<Function<AwsCredentialsProvider, Object>> factoryList = new ArrayList<>();
54+
55+
public AwsModule(@NonNull AwsCredentialsProvider credentialsProvider) {
56+
this.credentialsProvider = credentialsProvider;
57+
}
58+
59+
public AwsModule() {
60+
this.credentialsProvider = null;
61+
}
62+
63+
/**
64+
* Setup a new AWS service. Supported outputs are:
65+
*
66+
* <p>- Single amazon service - Stream of amazon services - Collection of amazon services
67+
*
68+
* <p>Each of the services returned by this function are added to the application service registry
69+
* and shutdown at application shutdown time.
70+
*
71+
* @param provider Service provider/factory.
72+
* @return AWS service.
73+
*/
74+
public @NonNull AwsModule setup(@NonNull Function<AwsCredentialsProvider, Object> provider) {
75+
factoryList.add(provider);
76+
return this;
77+
}
78+
79+
@Override
80+
public void install(@NonNull Jooby application) throws Exception {
81+
var config = application.getConfig();
82+
var credentialsProvider =
83+
Optional.ofNullable(this.credentialsProvider)
84+
.orElseGet(() -> newCredentialsProvider(config));
85+
86+
var serviceList = new ArrayList<>(factoryList.size());
87+
for (var factory : factoryList) {
88+
Object value = factory.apply(credentialsProvider);
89+
if (value instanceof Stream values) {
90+
values.forEach(serviceList::add);
91+
} else if (value instanceof Iterable values) {
92+
values.forEach(serviceList::add);
93+
} else {
94+
serviceList.add(value);
95+
}
96+
}
97+
ServiceRegistry services = application.getServices();
98+
// for each service
99+
for (Object service : serviceList) {
100+
Stream.of(
101+
service.getClass(),
102+
Stream.of(service.getClass().getInterfaces()).findFirst().orElse(null))
103+
.filter(Objects::nonNull)
104+
.forEach(serviceType -> services.putIfAbsent((Class) serviceType, service));
105+
}
106+
serviceList.stream()
107+
.filter(SdkAutoCloseable.class::isInstance)
108+
.map(SdkAutoCloseable.class::cast)
109+
.forEach(application::onStop);
110+
serviceList.clear();
111+
factoryList.clear();
112+
}
113+
114+
/**
115+
* Creates a credentials provider, exactly like {@link DefaultCredentialsProvider#create()}
116+
* appending the application properties provider.
117+
*
118+
* @param config Application properties.
119+
* @return Credentials provider.
120+
*/
121+
public static @NonNull AwsCredentialsProvider newCredentialsProvider(@NonNull Config config) {
122+
return AwsCredentialsProviderChain.of(
123+
DefaultCredentialsProvider.create(), new ConfigCredentialsProvider(config));
124+
}
125+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*
2+
* Jooby https://jooby.io
3+
* Apache License Version 2.0 https://jooby.io/LICENSE.txt
4+
* Copyright 2014 Edgar Espina
5+
*/
6+
package io.jooby.awssdkv2;
7+
8+
import com.typesafe.config.Config;
9+
import edu.umd.cs.findbugs.annotations.NonNull;
10+
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
11+
import software.amazon.awssdk.auth.credentials.AwsCredentials;
12+
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
13+
import software.amazon.awssdk.auth.credentials.AwsSessionCredentials;
14+
import software.amazon.awssdk.core.SdkSystemSetting;
15+
import software.amazon.awssdk.core.exception.SdkClientException;
16+
import software.amazon.awssdk.utils.StringUtils;
17+
18+
public class ConfigCredentialsProvider implements AwsCredentialsProvider {
19+
private final Config config;
20+
21+
public ConfigCredentialsProvider(@NonNull Config config) {
22+
this.config = config;
23+
}
24+
25+
@Override
26+
public AwsCredentials resolveCredentials() {
27+
String accessKey =
28+
config.hasPath(SdkSystemSetting.AWS_ACCESS_KEY_ID.property())
29+
? config.getString(SdkSystemSetting.AWS_ACCESS_KEY_ID.property())
30+
: null;
31+
String secretKey =
32+
config.hasPath(SdkSystemSetting.AWS_SECRET_ACCESS_KEY.property())
33+
? config.getString(SdkSystemSetting.AWS_SECRET_ACCESS_KEY.property())
34+
: null;
35+
String sessionToken =
36+
config.hasPath(SdkSystemSetting.AWS_SESSION_TOKEN.property())
37+
? config.getString(SdkSystemSetting.AWS_SESSION_TOKEN.property())
38+
: null;
39+
40+
if (accessKey == null) {
41+
throw SdkClientException.builder()
42+
.message(
43+
String.format(
44+
"Unable to load credentials from system settings. Access key must be"
45+
+ " specified either via environment variable (%s) or system property (%s).",
46+
SdkSystemSetting.AWS_ACCESS_KEY_ID.environmentVariable(),
47+
SdkSystemSetting.AWS_ACCESS_KEY_ID.property()))
48+
.build();
49+
}
50+
51+
if (secretKey == null) {
52+
throw SdkClientException.builder()
53+
.message(
54+
String.format(
55+
"Unable to load credentials from system settings. Secret key must be"
56+
+ " specified either via environment variable (%s) or system property (%s).",
57+
SdkSystemSetting.AWS_SECRET_ACCESS_KEY.environmentVariable(),
58+
SdkSystemSetting.AWS_SECRET_ACCESS_KEY.property()))
59+
.build();
60+
}
61+
62+
return StringUtils.isBlank(sessionToken)
63+
? AwsBasicCredentials.create(accessKey, secretKey)
64+
: AwsSessionCredentials.create(accessKey, secretKey, sessionToken);
65+
}
66+
}

modules/pom.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
<module>jooby-db-scheduler</module>
6464
<module>jooby-quartz</module>
6565
<module>jooby-awssdk-v1</module>
66+
<module>jooby-awssdk-v2</module>
6667

6768
<module>jooby-avaje-inject</module>
6869
<module>jooby-guice</module>

0 commit comments

Comments
 (0)