Using Guice with AWS Lambda
AWS Lambda's java runtime environment takes a handler string like "my.package.MyClass::handleRequest" which tells it to
Annoyingly, there is no hook in the runtime for inserting a dependency injection mechanism (like guice) meaning lambda will only create your object if it has a default construct.
The direct result is a lot of lambda implementations just directly create all their dependencies right inline including many examples in the AWS documentation
public class Example1 {
public void handleRequest(S3ObjectLambdaEvent event, Context context) throws Exception {
//hardcoded client #1
AmazonS3 s3Client = AmazonS3Client.builder().build();
...
//Another hardcoded client :/
HttpClient httpClient = HttpClient.newBuilder().build();
var presignedResponse = httpClient.send(
HttpRequest.newBuilder(new URI(event.inputS3Url())).GET().build(),
HttpResponse.BodyHandlers.ofInputStream());
s3Client.writeGetObjectResponse(new WriteGetObjectResponseRequest()
.withRequestRoute(event.outputRoute())
.withRequestToken(event.outputToken())
.withInputStream(presignedResponse.body()));
}
}
aws-lambda-guice allows you to define a Guice Module and a lambda, and a RequestHandler with a non-default constructor.
aws-lambda-guice will now use the provided module to create your handler.
public class ExampleModule extends AbstractModule {
@Provides
public S3Client s3() {
return AmazonS3Client.builder().build();
}
@Provides
public HttpClient http() {
return HttpClient.newBuilder().build();
}
public Example example(S3Client s3,
HttpClient http) {
return new Example(s3, http);
}
}
public class Example implements RequestHandler<S3ObjectLambdaEvent, Void>{
private final S3Client s3;
private final HttpClient http;
public Example(S3Client s3, HttpClient http) {
this.s3 = s3;
this.http = http;
}
@Override
public Void handleRequest(S3ObjectLambdaEvent event,
Context context) {
...
var presignedResponse = http.send(
HttpRequest.newBuilder(new URI(event.inputS3Url())).GET().build(),
HttpResponse.BodyHandlers.ofInputStream());
s3.writeGetObjectResponse(new WriteGetObjectResponseRequest()
.withRequestRoute(event.outputRoute())
.withRequestToken(event.outputToken())
.withInputStream(presignedResponse.body()));
return null;
}
}
With the following configuration: