Dependency injection with AWS Lambdas in java
Tags: serverless, java, aws
Published: 2023-02-11 19:42:23

*Disclaimer: for those who wants to see the solution, the github is [here](https://github.com/alvessteve/dagger-aws-lambda)*

No need to present the [AWS Lambdas](https://aws.amazon.com/lambda/) ; those have been disruptive innovations and they made the app development process smoother and more flexible. In this article, I will expose a way to add [dependency injection](https://en.wikipedia.org/wiki/Dependency_injection) within your lambdas.

**Why dependency injection with [nanoservices](https://dzone.com/articles/rise-of-the-nanoservice-how-aws-application-reposi) ?**

The question is fair. Indeed, as each function is independent from the other, why bother yourself adding a new level of abstraction and complexity ?

In fact, if you you want to follow the good practices of scalable code, some parts of your code is shared between functions. For instance, the services querying the database. Thus, your source code grows in complexity and becomes similar to a more « classic » web application, inviting you to follow the [SOLID](https://en.wikipedia.org/wiki/SOLID) acronym.

Off course, depending on your needs and situation, it would be better to not do it but if you target the long run, it would be suicide to unfollow the good practices (exponential growth of maintenance costs…).

As said in the title, we will focus on the dependency inversion principle and one of its application : dependency injection. For production-ready applications, it would be better to rely on a framework and not implement its own container. For it, the java ecosystem have 3 frameworks available : [Spring](https://spring.io/), [Guice](https://github.com/google/guice) and [Dagger](https://dagger.dev/).

**Spring and Guice**

In the java world, Spring is THE most-used solution. Proven, maintained at a constant pace, it became the standard. However, its ecosystem is too large (IOC, MVC…) for our needs so we’ll have to install a lot of useless frameworks just for dependency injection making the package size not optimal. Moreover, all the injection is done at **runtime** making your cold start even longer ! Needless to say that all the binding errors will be detected at runtime so when the lambda is launched. Thus, Spring is not a good choice.

On the other hand, Guice is another dependency injection framework created by Google. It a good alternative because :

* Framework package size much lighter than Spring

* No external configuration file to setup (no properties or xml files)

However, it wouldn’t feet our needs because like Spring all the injection is done at **runtime.**

Then, is there a good solution ? yes and it is Dagger !

**Dagger ?**

Dagger is a dependency injection framework developed by Square and forked by Google. It is widely used in the Android ecosystem. Its key points are :

* **Lightness** : juste dependency injection

* Use of [**java.inject ](http://javax-inject.github.io/javax-inject/)annotation**

* Last but not least, the injection is done at **compilation.** No more binding errors at runtime ! Thus, all the injection is done at the packaging of our lambda bringing the cold start to its bare minimum.

Let’s deep dive a little.

**Short overview of Dagger**

Dagger is built around 2 concepts : *Modules *and *Components.*

A module is a container, represented by a class, where you declare your classes and define the dependency relationship between them. An example :
{% gist https://gist.github.com/alvessteve/04a150389f8065c8d20a2b6d5cd42ee5.js %}
A component is an interface used as the entry point of the application. It also links the modules needed to make the application run. Here goes an example :
{% gist https://gist.github.com/alvessteve/27e3d5569b147842b6a105bb9052dd79.js %}
From there, Dagger will generate factories from modules and Builders from components.

**Use case**

The example is quite simple. We have 3 services : *AService*, *BService*, *AgregateService*. Each one has a print function which returns the eponym letter. The *AgregateService* similarly returns « ABC ».

All the plue-value is at the ***LambdaDispatcher ***class. This is a dispatcher acting as an entry-point and allowing to :

* Generate the component and the dependency tree

* Forward the request to the related service

* Bring an abstract lawyer splitting the business code from the infrastructure one (ie AWS and Dagger librairies) making the code more maintable and testable.

Here is the implementation :
{% gist https://gist.github.com/alvessteve/c8af95e07f79f6c4b6c20d53aa953ef6.js %}
And the component :
{% gist https://gist.github.com/alvessteve/27e3d5569b147842b6a105bb9052dd79.js %}
Module :
{% gist https://gist.github.com/alvessteve/04a150389f8065c8d20a2b6d5cd42ee5.js %}
As an image worth 1000 words :

![The class diagram](https://cdn-images-1.medium.com/max/2000/1*0eNvJGqohM-BBQg8K9hVNg.jpeg)


Here is the **[github](https://github.com/alvessteve/dagger-aws-lambda)**.