DI for AWS Java Lambda

@Anil's Notes
4 min readNov 13, 2017

Dependency injection is providing the objects that an object needs (its dependencies) instead of having it construct them itself. An IoC( Inversion of Control) container will be used to wire up the dependencies.

Benefits:

  • Enables loosely-coupled design.
  • Easily swap in mocks/fake objects for developing tests.
  • Easily re-configure different types of dependencies.
  • Parallel development on the dependencies
  • Can be used to do different types of wiring.

As DI or IoC is language-agnostic pattern popular pattern, Let‘s directly jump in to DI for Serverless Applications. We will consider AWS Lambda as the compute system behind Serverless application i.e. we will rely on AWS Cloud Platform.

AWS Lambda Best Practices notes about DI

http://docs.aws.amazon.com/lambda/latest/dg/best-practices.html

Minimize the complexity of your dependencies. Prefer simpler frameworks that load quickly on container startup. For example, prefer simpler Java dependency injection (IoC) frameworks like Dagger or Guice, over more complex ones like Spring Framework.

Spring Framework is a popular DI/IoC container, Spring provides different ways of wiring dependencies (constructor, setter etc) to the original object. It also provides different mechanisms to configure wirings (XML, annotation etc). It is the best IoC framework for building Server-based microservices which are deployed to a web-container or other use-cases where application boot-time is not really an issue.

Building a FAAS (Lambda) based applications using Spring Framework. It works just fine but requires good amount of time to boot-up and wire dependencies.

Why not Spring Framework for FAAS?

  • Spring is heavy-weight framework with lot of integrations
  • Configuration: Xml Configuration loses “compile time safety” i.e. You need to run the application to see wiring issues in XML configuration. After Spring introduced annotation-driven programming it is better but still you have no idea about the correctness of wiring until you run the application.
  • Primarily suitable for an enterprise application, It may be challenging to isolate the small subset of features that you want to use in the application.
  • Increases Package Size by bringing in lot of other non-required dependencies.
  • High container startup time for a FAAS application.
  • Extensive use of Reflection
  • Configuration Debugging may be harder

Why Dagger 2?

  • Dagger is light-weight framework with very few integrations, Java interface/annotation configuration and compile-time code generated bindings.
  • Very small (<100kb), vs Guice (~500kb) and Spring (~800kb)
  • Performance: As fast as hand-written code and no coding around the framework.
  • Fail as early as possible ( compile-time, not runtime)
  • Traceability: Navigate entire application with “find usages” and “open declaration”
  • Development and debugging easier and faster
  • Eliminates reflection on methods, fields and annotations.

Dagger 2 — Strategy

  • Generate simple Java at compile time for the entire stack that looks as close as hand-written DI code as possible
  • Validate all framework/configuration at compile time
  • Unify user-defined types with generated types through well defined entry points.

Dagger 2 API

  • @Module + @Provides : Mechanism for providing dependencies

Modules are classes whose methods provide dependencies. Modules are designed to be partitioned and composed together (It is recommended not to use single module to provide all dependencies, Best practice is to go with different modules based on logical grouping).@Provides is annotated on method inside a module to wire up dependencies.

  • @Inject : mechanism for requesting dependencies

Inject annotation can be used in constructor, field and method injection.

  • @Component : Bridge between modules and injections

Annotation Processing:

Note: Eclipse requires enabling annotation processor support installed
and enabled! The m2e-apt plugin can be downloaded from the Eclipse
Marketplace or https://marketplace.eclipse.org/content/m2e-apt
Ensure that Preferences ->
Maven -> Annotation Processing is set to "Automatically configure JDT
APT"

Simple AWS Lambda:

Sample code:

--

--

@Anil's Notes

Thoughts I add here are my personal notes and learnings only