Deploying and running services on Function-as-a-Service (FaaS) compute platforms like AWS Lambda has some compelling benefits for appropriate use-cases (short running workloads), including true (low-latency) elastic scalability, at finer granularity, with significant cost-savings based on scaling to zero.
At the same time, the Spring application framework (and more recently Spring Boot) has long encouraged and helped accelerate building modern, flexible enterprise apps that run on the JVM, that are easy to test, by abstracting away generic code (‘plumbing’) for integrating an app with its libraries and APIs; using familiar design/programming patterns (IoC/DI, proxies, Template methods etc); and providing valuable features (declarative transaction management, environment specific config, etc).
In an ideal world we’d use all these technologies – building Java/JVM functions with the help of Spring that are deployed and run on AWS Lambda – to realise their combined benefits.
But can these technologies be made to work together effectively? Or do we need to accept that when it comes to designing and building services to run on FaaS platforms like AWS Lambda, tech stacks (programming languages and application framework) offer than Java and Spring may offer a better solution?
FaaS functions that require a JVM to be launched and rely on a stateful Spring IoC container (an Application Context) don’t (at first glance) appear to be a naturally good fit for running on FaaS platforms. How can developers and their business’ continue to benefit from building enterprise apps using Spring, and also now profit from running those apps on a FaaS platform? Which, if any, use-cases does it make sense to deploy a FaaS solution built using Spring? What solutions are available to support the combination of these technologies, and how do they compare in terms of developer usability/experience and quality (performance, etc)? These are some the questions I’ve set out to investigate and answer.
This blog post and associated code, along with possible future posts, outlines my research into solutions for deploying and running enterprise services, built using Spring Boot, on the AWS Lambda platform – i.e. solutions for Spring-based AWS Lambda functions. In this post I outline the first solution I trialled.
Solution 1 – AWS Serverless Java Container Library
The AWS Serverless Java Container library is an AWS (Labs) provided solution for running stateful Java web-apps built using popular frameworks, such as Spring, on AWS Lambda, in an efficient manner (avoiding the need to re-launch the app / restart the Java web container across every execution of a Lambda function).
The solution entails packaging and deploying a Java web-app as an AWS serverless app – an app that is built and deployed using a combination of the AWS API Gateway and AWS Lambda services. The AWS API Gateway is used to proxy HTTP requests to the app/service’s web API endpoints in order to make use of AWS Lambda’s support for invoking Lambda functions in response to HTTP request events received via the AWS API Gateway service.
The AWS Serverless Java Container library provides a Spring (Boot) / Spring MVC specific implementation of the AWS LambdaContainerHandler class, which provides integration (‘glue’) code to facilitate running a Spring web-app on AWS Lambda, in the context of a single AWS Lambda function. The LambdaContainerHandler class knows how to bootstrap a Spring web-app (create and load its web application context). It also provides a request handler method that a Lambda function can delegate to. This handler method adapts an invocation of a Lambda function, that originates from an HTTP request event received via an AWS API Gateway endpoint, to the Servlet API used by Spring MVC.
If you’re Interested in finding out more about this solution, including how it can be used to re-engineer (port) an existing backend (micro) service built using (Java and) Spring Boot to run on the AWS Lambda platform, you can find more details and example code in my aws-serverless-java-container service project on GitHub.