Improving Java Lambdas with Dagger Dependency Injection

Ryan Pope
3 min readFeb 5, 2019

Motivation

If you’re reading this then you probably have already done some of your own research into Lambda + Dagger so I’ll keep motivation brief.

When I started writing some AWS Lambdas for interfacing with DynamoDB I quickly noticed that I had a lot of duplicate code for creating the DynamoDB client.

Duplication

Method Chaining

These blocks of code starting appearing throughout all the Lambdas I wrote and they really bugged me. I started thinking about ways to improve this and Dependency Injection was at the top of my list. I started researching DI to use with Lambda — the obvious biggest consideration in choosing a DI for a serverless application is going to be the cold start time. Spring is fairly heavy weight and likely not a good option. Guice and Dagger are both good options.

Dagger is a DI typically used with Android, however that is not a hard limitation as it can be used with any native Java app. I felt there was some similarities between Android activities and Lambdas — they both have this sort of Context god object that is used during the life of the activity (or request) and it felt like the perfect fit for Dagger.

tl;dr

  • Reduce duplication across Lambdas
  • Ensure that the clients to AWS Services are only created once per request

Implementation

Usage

In the examples above we are creating the Dynamo client in each request. What we want to do is @Inject the client into the Handler. I’ve seen it done a couple different ways. One way I don’t really care for is building the entire Component in the constructor of each Lambda like so.

and then referencing each required Object as mComponent.logger().log() because this hasn’t really solved any of the the problems that I set out to fix. I still have duplication and chaining.

The solution I came up with was to separate out a static class to properly inject the members of the Handler on each handleRequest. To do this I created a static helper class called Injector.

Now for each handleRequest I simply call the inject function with the Context which injects all the members of the Handler. Here is a simple logger example that takes a String request and returns a Boolean response while logging the request.

Of course this is just a simple example where you could just reference the LambdaLogger via Context.

This brings us to the Component.

Component

Your component is the interface where you define what can be injected into the Object graph. For our example we will have something like this,

If you look at the generated code, you can see that what is happening behind the scenes when you callInjector.getInjector(context).inject(this) is not all that complicated.

Modules

The Modules are pretty straight-forward. I typically like to separate them by responsibility. For example, if I wanted to inject the logger or other Objects contained in the Lambda context I might make one called LambdaModule.

Notice that the Lambda context is passed as an argument to the constructor here. We can also provide any other Objects from the Context, such as the CognitoIdentity.

Here is another example for providing the DynamoDB clients.

Here is where you can start to get really fancy. You can really start to loosely couple your code with Dagger features such as @Named.

Bringing It Together

Consider an example like this for fetching a feed of some sort of activity for a given user.

This is fairly hard to follow. Let’s now apply what we’ve just done with Dagger given the Modules we created above.

This is starting to look better but let’s go ahead and add one more Module FeedTableModule.

And lastly the new final revision of the Handler

Notice how I’m no longer even injecting the Dynamo client into the Handler. I’m injecting only what I need, the index. I’ve also extracted out the QuerySpec so you can keep those in their own file and re-use them across Handlers if you desire.

Resources

I’ve bundled up the simple examples into a template that can be used to write your own Lambdas with Dagger 2. It can be found here.

--

--