Partner – Microsoft – NPI EA (cat = Baeldung)
announcement - icon

Azure Container Apps is a fully managed serverless container service that enables you to build and deploy modern, cloud-native Java applications and microservices at scale. It offers a simplified developer experience while providing the flexibility and portability of containers.

Of course, Azure Container Apps has really solid support for our ecosystem, from a number of build options, managed Java components, native metrics, dynamic logger, and quite a bit more.

To learn more about Java features on Azure Container Apps, visit the documentation page.

You can also ask questions and leave feedback on the Azure Container Apps GitHub page.

Partner – Microsoft – NPI EA (cat= Spring Boot)
announcement - icon

Azure Container Apps is a fully managed serverless container service that enables you to build and deploy modern, cloud-native Java applications and microservices at scale. It offers a simplified developer experience while providing the flexibility and portability of containers.

Of course, Azure Container Apps has really solid support for our ecosystem, from a number of build options, managed Java components, native metrics, dynamic logger, and quite a bit more.

To learn more about Java features on Azure Container Apps, you can get started over on the documentation page.

And, you can also ask questions and leave feedback on the Azure Container Apps GitHub page.

Partner – Orkes – NPI EA (cat=Spring)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

Partner – Orkes – NPI EA (tag=Microservices)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

eBook – Guide Spring Cloud – NPI EA (cat=Spring Cloud)
announcement - icon

Let's get started with a Microservice Architecture with Spring Cloud:

>> Join Pro and download the eBook

eBook – Mockito – NPI EA (tag = Mockito)
announcement - icon

Mocking is an essential part of unit testing, and the Mockito library makes it easy to write clean and intuitive unit tests for your Java code.

Get started with mocking and improve your application tests using our Mockito guide:

Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Reactive – NPI EA (cat=Reactive)
announcement - icon

Spring 5 added support for reactive programming with the Spring WebFlux module, which has been improved upon ever since. Get started with the Reactor project basics and reactive programming in Spring Boot:

>> Join Pro and download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Jackson – NPI EA (cat=Jackson)
announcement - icon

Do JSON right with Jackson

Download the E-book

eBook – HTTP Client – NPI EA (cat=Http Client-Side)
announcement - icon

Get the most out of the Apache HTTP Client

Download the E-book

eBook – Maven – NPI EA (cat = Maven)
announcement - icon

Get Started with Apache Maven:

Download the E-book

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

eBook – RwS – NPI EA (cat=Spring MVC)
announcement - icon

Building a REST API with Spring?

Download the E-book

Course – LS – NPI EA (cat=Jackson)
announcement - icon

Get started with Spring and Spring Boot, through the Learn Spring course:

>> LEARN SPRING
Course – RWSB – NPI EA (cat=REST)
announcement - icon

Explore Spring Boot 3 and Spring 6 in-depth through building a full REST API with the framework:

>> The New “REST With Spring Boot”

Course – LSS – NPI EA (cat=Spring Security)
announcement - icon

Yes, Spring Security can be complex, from the more advanced functionality within the Core to the deep OAuth support in the framework.

I built the security material as two full courses - Core and OAuth, to get practical with these more complex scenarios. We explore when and how to use each feature and code through it on the backing project.

You can explore the course here:

>> Learn Spring Security

Course – LSD – NPI EA (tag=Spring Data JPA)
announcement - icon

Spring Data JPA is a great way to handle the complexity of JPA with the powerful simplicity of Spring Boot.

Get started with Spring Data JPA through the guided reference course:

>> CHECK OUT THE COURSE

Partner – MongoDB – NPI EA (tag=MongoDB)
announcement - icon

Traditional keyword-based search methods rely on exact word matches, often leading to irrelevant results depending on the user's phrasing.

By comparison, using a vector store allows us to represent the data as vector embeddings, based on meaningful relationships. We can then compare the meaning of the user’s query to the stored content, and retrieve more relevant, context-aware results.

Explore how to build an intelligent chatbot using MongoDB Atlas, Langchain4j and Spring Boot:

>> Building an AI Chatbot in Java With Langchain4j and MongoDB Atlas

Partner – LambdaTest – NPI EA (cat=Testing)
announcement - icon

Accessibility testing is a crucial aspect to ensure that your application is usable for everyone and meets accessibility standards that are required in many countries.

By automating these tests, teams can quickly detect issues related to screen reader compatibility, keyboard navigation, color contrast, and other aspects that could pose a barrier to using the software effectively for people with disabilities.

Learn how to automate accessibility testing with Selenium and the LambdaTest cloud-based testing platform that lets developers and testers perform accessibility automation on over 3000+ real environments:

Automated Accessibility Testing With Selenium

eBook – Guide Spring Cloud – NPI (cat=Cloud/Spring Cloud)
announcement - icon

Let's get started with a Microservice Architecture with Spring Cloud:

>> Join Pro and download the eBook

1. Overview

In this tutorial, we’ll explore how to deploy a Spring Boot application to AWS Lambda using the Serverless Application Model (SAM) framework.

We may find this approach useful for migrating an existing API server to serverless.

By doing so, we can take advantage of AWS Lambda’s scalability and pay-per-execution pricing model to run our application efficiently and cost-effectively.

2. Understanding Lamdba

AWS Lambda is a serverless computing service provided by Amazon Web Services (AWS). It allows us to run our code without having to provision or manage servers.

One of the key differences between Lambda functions and traditional servers is that Lambda functions are event-driven and have a very short lifespan.

Instead of running continuously like a server, Lambda functions only run in response to specific events, such as an API request, a message on a queue, or a file upload to S3.

We should note that lambdas take time to start up for the first request they serve. This is called a “cold start”.

If the next request comes within a short time, the same lambda runtime may be used, which is called a “warm start”. If more than one request comes concurrently, multiple Lambda runtimes are started.

As Spring Boot has a relatively long startup time compared with the ideal milliseconds for a Lambda, we’ll discuss how this affects performance.

3. Project Setup

So, let’s migrate an existing Spring Boot project by modifying the pom.xml and adding some configuration.

The supported versions of Spring Boot are 2.2.x, 2.3.x, 2.4.x, 2.5.x, 2.6.x and 2.7.x.

3.1. Example Spring Boot API

Our application is composed of a simple API that handles any GET request to the api/v1/users endpoint:

@RestController
@RequestMapping("/api/v1/")
public class ProfileController {

    @GetMapping(value = "users", produces = MediaType.APPLICATION_JSON_VALUE)
    public List<User> getUser() {
        return List.of(new User("John", "Doe", "[email protected]"), 
                       new User("John", "Doe", "[email protected]"));
    }
}

That responds with a list of User objects:

public class User {

    private String name;
    private String surname;
    private String emailAddress;

    //standard constructor, getters and setters
}

Let’s start our application and invoke the API:

$ java -jar app.jar
$ curl -X GET http://localhost:8080/api/v1/users -H "Content-Type: application/json"

The API response is:

[
   {
      "name":"John",
      "surname":"Doe",
      "email":"[email protected]"
   },
   {
      "name":"John",
      "surname":"Doe",
      "email":"[email protected]"
   }
]

3.2. Convert the Spring Boot Application to Lambda via Maven

In order to run our application on Lambda, let’s add the aws-serverless-java-container-springboot2 dependency to our pom.xml file:

<dependency>
    <groupId>com.amazonaws.serverless</groupId>
    <artifactId>aws-serverless-java-container-springboot2</artifactId>
    <version>${springboot2.aws.version}</version>
</dependency>

Then, we’ll add the maven-shade-plugin and remove the spring-boot-maven-plugin.

The Maven Shade Plugin is used to create a shaded (or uber) JAR file. A shaded JAR file is a self-contained executable JAR file that includes all of its dependencies within the JAR itself so that it can be run independently:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-shade-plugin</artifactId>
    <version>3.3.0</version>
    <configuration>
        <createDependencyReducedPom>false</createDependencyReducedPom>
    </configuration>
    <executions>
        <execution>
            <phase>package</phase>
            <goals>
                <goal>shade</goal>
            </goals>
            <configuration>
                <artifactSet>
                    <excludes>
                        <exclude>org.apache.tomcat.embed:*</exclude>
                    </excludes>
                 </artifactSet>
            </configuration>
         </execution>
     </executions>
 </plugin>

Overall, this configuration will produce a shaded JAR file during the package phase of the Maven build.

The JAR file will include all the classes and resources that Spring Boot would normally package, with the exception of those from Tomcat. We don’t need to run an embedded web container for use with AWS Lambda.

4. Lambda Handler

The next step is to create a class that implements a RequestHandler.

RequestHandler is an interface that defines a single method, handleRequest. There are a few different ways to handle requests, depending on the type of Lambda we’re building.

In this case, we’re processing a request from API Gateway, so we can use the RequestHandler<AwsProxyRequest, AwsProxyResponse> version, where the input is an API Gateway request, and the response is an API Gateway response.

The Spring Boot serverless library, provided by AWS, gives us a special SpringBootLambdaContainerHandler class, which is used to process API calls through Spring, thus enabling a Spring Boot API server codebase to act like a Lambda.

4.1. Startup Timing

We should note that in AWS Lambda, the initialization phase is time-limited to 10 seconds.

If our application takes longer than this to start up, AWS Lambda will timeout and try to start a new Lambda runtime.

Depending on how quickly our Spring Boot Application starts up, we can choose between two ways to initialize our Lambda handler:

  • Synchronous – where the start-up time of our application is much less than the time limit
  • Asynchronous – where the start-up time of our application is likely to take longer

4.2. Synchronous Initialization

Let’s define a new handler in our Spring Boot project:

public class LambdaHandler implements RequestHandler<AwsProxyRequest, AwsProxyResponse> {
    private static SpringBootLambdaContainerHandler<AwsProxyRequest, AwsProxyResponse> handler;

    static {
        try {
            handler = SpringBootLambdaContainerHandler.getAwsProxyHandler(Application.class); }
        catch (ContainerInitializationException ex){
            throw new RuntimeException("Unable to load spring boot application",ex); }
    }

    @Override
    public AwsProxyResponse handleRequest(AwsProxyRequest input, Context context) {
        return handler.proxy(input, context);
    }
}

We’re using the SpringBootLambdaContainerHandler to process API Gateway requests and pass them through our application context. We initialize this handler in the static constructor of the LambaHandler class, and we call it from the handleRequest function.

The handler object then invokes the appropriate method in the Spring Boot application to process the request and generate a response. Finally, it returns the response back to the Lambda runtime for passing back to the API Gateway.

Let’s invoke our API via the Lambda handler:

@Test
void whenTheUsersPathIsInvokedViaLambda_thenShouldReturnAList() throws IOException {
    LambdaHandler lambdaHandler = new LambdaHandler();
    AwsProxyRequest req = new AwsProxyRequestBuilder("/api/v1/users", "GET").build();
    AwsProxyResponse resp = lambdaHandler.handleRequest(req, lambdaContext);
    Assertions.assertNotNull(resp.getBody());
    Assertions.assertEquals(200, resp.getStatusCode());
}

4.3. Asynchronous Initialization

Sometimes Spring Boot Application may be slow to start. That’s because, during the start-up phase, the Spring engine builds its context, scanning and initializing all the beans in the codebase.

This process may impact the start-up time and can create a lot of problems in a serverless context.

To solve this problem, we can define a new handler:

public class AsynchronousLambdaHandler implements RequestHandler<AwsProxyRequest, AwsProxyResponse> {
    private SpringBootLambdaContainerHandler<AwsProxyRequest, AwsProxyResponse> handler;

    public AsynchronousLambdaHandler() throws ContainerInitializationException {
        handler = (SpringBootLambdaContainerHandler<AwsProxyRequest, AwsProxyResponse>) 
          new SpringBootProxyHandlerBuilder()
            .springBootApplication(Application.class)
            .asyncInit()
            .buildAndInitialize();
    }

    @Override
    public AwsProxyResponse handleRequest(AwsProxyRequest input, Context context) {
        return handler.proxy(input, context);
    }
}

This method is similar to the previous one. In this instance, the SpringBootLambdaContainerHandler is constructed in the object constructor of the request handler, rather than the static constructor. As such, it’s executed in a different phase of the Lambda’s start-up.

5. Deploy the Application

AWS SAM (Serverless Application Model) is an open-source framework for building serverless applications on AWS.

After defining a Lambda handler for our Spring Boot Application, we need to prepare all the components for deploying using SAM.

5.1. SAM Template

The SAM template (SAM YAML) is a YAML-formatted file that defines the AWS resources needed to deploy a serverless application. Basically, it provides a declarative way to specify the configuration of our serverless application.

So, let’s define our template.yaml:

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31

Globals:
  Function:
    Timeout: 30

Resources:
  ProfileApiFunction:
    Type: AWS::Serverless::Function 
    Properties:
      CodeUri: .
      Handler: com.baeldung.aws.handler.LambdaHandler::handleRequest
      Runtime: java11
      AutoPublishAlias: production
      SnapStart:
        ApplyOn: PublishedVersions
      Architectures:
        - x86_64
      MemorySize: 2048
      Environment: 
        Variables:
          JAVA_TOOL_OPTIONS: -XX:+TieredCompilation -XX:TieredStopAtLevel=1 
      Events:
        HelloWorld:
          Type: Api 
          Properties:
            Path: /{proxy+}
            Method: ANY

Let’s discuss some of the fields in our configuration:

  • type – indicates that this resource is an AWS Lambda function defined using the AWS::Serverless::Function resource type.
  • coreUri – specifies the location of the code for the function.
  • AutoPublishAlias – specifies the alias that AWS Lambda should use when automatically publishing a new version of the function.
  • Handler – specifies the lambda handler class.
  • Events – specifies the events that trigger the Lambda function.
  • Type – specifies that this is an Api event source.
  • Properties – for an API event, this defines the HTTP method and paths that the API Gateway should respond to.

5.2. SAM Deploy

It’s time to deploy our application as an AWS Lambda.

The first step is to download and install AWS CLI and then AWS SAM CLI.

Let’s run AWS SAM CLI on the path where the template.yaml is located and execute the command:

$ sam build

When we run this command, AWS SAM CLI will package and build our Lambda function’s source code and dependencies into a ZIP file that serves as our deployment package.

Let’s deploy our application locally:

$ sam local start-api

Next, let’s trigger our Spring Boot service while it’s running via sam local:

$ curl localhost:3000/api/v1/users

The API response is the same as before:

[
   {
      "name":"John",
      "surname":"Doe",
      "email":"[email protected]"
   },
   {
      "name":"John",
      "surname":"Doe",
      "email":"[email protected]"
   }
]

We can also deploy it to AWS:

$ sam deploy

6. Limitations of Using Spring in a Lambda

Although Spring is a powerful and flexible framework for building complex and scalable applications, it may not always be the best choice for use in a Lambda context.

The primary reason for this is that Lambdas are designed to be small, single-purpose functions that execute quickly and efficiently.

6.1. Cold Start

The cold start time of AWS Lambda functions is the time it takes to initialize the function environment before processing an event.

There are several factors that can impact cold start performance for a Lambda function:

  • Package size – a larger package size can result in longer initialization times and lead to slower cold starts.
  • Initialization time – the amount of time it takes for the Spring Framework to initialize and set up the application context.
    This includes initializing any dependencies, such as database connections, HTTP clients, or caching frameworks.
  • Custom initialization logic – it’s important to minimize the amount of custom initialization logic and ensure it’s optimized for cold starts.

We can improve our start-up time using Lambda SnapStart.

6.2. Database Connection Pool

In a serverless environment like AWS Lambda, where functions are executed on-demand, maintaining a connection pool can be challenging.

When an event triggers a Lambda, the AWS Lambda engine can create a new instance of the application. In between requests, the runtime is parked or may be terminated.

Many connection pools hold open connections. This can cause confusion or errors as the pool is reused after a warm start, and it can cause resource leaks for some database engines. In short, standard connection pooling relies on the server continuously running and maintaining the connections.

To address this issue, AWS provides a solution called RDS Proxy, which provides a connection pooling service for Lambda functions.

By using RDS Proxy, Lambda functions can connect to a database without the need for maintaining their own connection pools.

7. Conclusion

In this article, we learned how to convert an existing Spring Boot API Application into an AWS Lambda.

We looked at the library provided by AWS to help with this. Also, we considered how the slower startup time of Spring Boot may affect the way we set things up.

Then we looked at how to deploy the Lambda and test it using the SAM CLI.

The code backing this article is available on GitHub. Once you're logged in as a Baeldung Pro Member, start learning and coding on the project.
Baeldung Pro – NPI EA (cat = Baeldung)
announcement - icon

Baeldung Pro comes with both absolutely No-Ads as well as finally with Dark Mode, for a clean learning experience:

>> Explore a clean Baeldung

Once the early-adopter seats are all used, the price will go up and stay at $33/year.

Partner – Microsoft – NPI EA (cat = Baeldung)
announcement - icon

Azure Container Apps is a fully managed serverless container service that enables you to build and deploy modern, cloud-native Java applications and microservices at scale. It offers a simplified developer experience while providing the flexibility and portability of containers.

Of course, Azure Container Apps has really solid support for our ecosystem, from a number of build options, managed Java components, native metrics, dynamic logger, and quite a bit more.

To learn more about Java features on Azure Container Apps, visit the documentation page.

You can also ask questions and leave feedback on the Azure Container Apps GitHub page.

Partner – Microsoft – NPI EA (cat = Spring Boot)
announcement - icon

Azure Container Apps is a fully managed serverless container service that enables you to build and deploy modern, cloud-native Java applications and microservices at scale. It offers a simplified developer experience while providing the flexibility and portability of containers.

Of course, Azure Container Apps has really solid support for our ecosystem, from a number of build options, managed Java components, native metrics, dynamic logger, and quite a bit more.

To learn more about Java features on Azure Container Apps, visit the documentation page.

You can also ask questions and leave feedback on the Azure Container Apps GitHub page.

Partner – Orkes – NPI EA (cat = Spring)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

Partner – Orkes – NPI EA (tag = Microservices)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

eBook – HTTP Client – NPI EA (cat=HTTP Client-Side)
announcement - icon

The Apache HTTP Client is a very robust library, suitable for both simple and advanced use cases when testing HTTP endpoints. Check out our guide covering basic request and response handling, as well as security, cookies, timeouts, and more:

>> Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

Partner – MongoDB – NPI EA (tag=MongoDB)
announcement - icon

Traditional keyword-based search methods rely on exact word matches, often leading to irrelevant results depending on the user's phrasing.

By comparison, using a vector store allows us to represent the data as vector embeddings, based on meaningful relationships. We can then compare the meaning of the user’s query to the stored content, and retrieve more relevant, context-aware results.

Explore how to build an intelligent chatbot using MongoDB Atlas, Langchain4j and Spring Boot:

>> Building an AI Chatbot in Java With Langchain4j and MongoDB Atlas

Course – LS – NPI EA (cat=REST)

announcement - icon

Get started with Spring Boot and with core Spring, through the Learn Spring course:

>> CHECK OUT THE COURSE

Partner – Microsoft – NPI (cat=Spring)
announcement - icon

Azure Container Apps is a fully managed serverless container service that enables you to build and deploy modern, cloud-native Java applications and microservices at scale. It offers a simplified developer experience while providing the flexibility and portability of containers.

Of course, Azure Container Apps has really solid support for our ecosystem, from a number of build options, managed Java components, native metrics, dynamic logger, and quite a bit more.

To learn more about Java features on Azure Container Apps, visit the documentation page.

You can also ask questions and leave feedback on the Azure Container Apps GitHub page.

eBook Jackson – NPI EA – 3 (cat = Jackson)
eBook – eBook Guide Spring Cloud – NPI (cat=Cloud/Spring Cloud)
7 Comments
Oldest
Newest
Inline Feedbacks
View all comments