DEV Community

Paul Eggerling-Boeck
Paul Eggerling-Boeck

Posted on • Originally published at awstip.com on

Configure your AWS Lambda function with Spring Boot

Spring Boot is a Java framework that offers a lot of benefits for developers. It provides a streamlined development experience and reduces the amount of boilerplate code needed. It comes with built-in support for monitoring and management tools, caching, data validation, and security. The framework has a large and active community of developers who provide support and resources. Overall, Spring Boot is a powerful and flexible framework that can help you build robust, scalable, and maintainable applications quickly and consistently. In this article, I’ll walk you through the steps necessary to configure an AWS Lambda function as a Spring Boot application.


Photo by Sole Montaner

Using the Spring Initializr wizard is a great way to have all the pieces put in place for you so you can get started quickly. For now, I’m going to show you how to add Spring Boot to a Lambda function step-by-step so you can see how all the pieces fit together. As with my other articles, You’ll be using Gradle. AWS announced official Lambda runtime support for Java 17 on April 27, 2023 (two days before I started writing this article) which will finally allow you to use a JDK version above Java 11 and also will allow you to use Spring 3 in a Lambda function! I had to upgrade Gradle and AWS SAM CLI in order to make this example work so I’ll list the relevant tool versions that I used below.

  • OpenJDK 17.0.7
  • Spring 3.0.6
  • Gradle 7.5.1
  • AWS SAM CLI 1.82.0

Now that you have all the tooling versions worked out, you can get started. The first thing you’ll need to do is add the needed Spring Boot dependencies to your application. In your build.gradle file, declare that you’ll be using the following two Spring plugins (in addition to the Java plugin) like so:

plugins {
    id 'java'
    id 'org.springframework.boot' version '3.0.6'
    id 'io.spring.dependency-management' version '1.1.0'
}
Enter fullscreen mode Exit fullscreen mode

Then in in the dependencies block of your build.gradle file, add the basic Spring Boot dependencies:

dependencies {
    // Spring dependencies
    implementation 'org.springframework.boot:spring-boot-starter'

    // Unit testing.
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
Enter fullscreen mode Exit fullscreen mode

Adding the spring-boot-starter-test dependency allows you to use JUnit 5 for unit testing along with all the other Spring Boot testing capabilities. In order to get Gradle to actually run your JUnit tests, you’ll need to add the following Groovy test task configuration at the bottom of your build.gradle file:

tasks.named('test') {
    // Use junit platform for unit tests.
    useJUnitPlatform()
}
Enter fullscreen mode Exit fullscreen mode

Congratulations! You now have the build configuration done! You can now add the Java code needed to start your application as a Spring Boot application and begin working with all the Spring Boot goodness. After much trial and error, I learned that when working in the context of an AWS Lambda function, it’s much better to create a separate class to serve as your SpringBootApplication class. So create the following two classes, and that’s all you need to get going. Notice that the class you annotate with @SpringBootApplication doesn’t need any actual code, it’s just a way for you to get Spring Boot running and is only used as the argument to SpringApplication.run().

@SpringBootApplication
public class SpringAppForLambda {
}

public class Handler {
    private static ConfigurableApplicationContext applicationContext;
    private static String appName;

    static {
        applicationContext = SpringApplication.run(SpringAppForLambda.class);
        appName = applicationContext.getEnvironment().getProperty("spring.application.name");
    }

    /**
     * Lambda handler method
     * @param context the Lambda request context
     * @return a string containing a message
     */
    public String handleRequest(Context context) {
        return Handler.appName;
    }

    public static void main(String[] args) {
        System.out.println("Main Method");
    }
}
Enter fullscreen mode Exit fullscreen mode

By default, Spring looks in the application’s classpath for a file called application.properties. For this example, I placed an application.properties file with the following contents in src/main/resources so that it ends up on the classpath.

spring.application.name=WeatherTracker
Enter fullscreen mode Exit fullscreen mode

Notice that the second line in the static initialization block pulls the value of the spring.application.name property from an instance of the Config glass which was retrieved from the application context and stores it in a static String variable that the handleRequest() method then returns. How did the value get into that instance of the Config class? Well, that’s part of the magic of Spring Boot. You can read more about it here. In fact, there’s a TON of Spring and Spring Boot information at baeldung.com.

The Handler class needs a main() method due to the way that the SAM CLI uses Gradle to build the Lambda deployment package so I’ve included a simple example in the code listing above. If you know of a better way to get around that requirement, please let me know. If you haven’t already, you can read my article on deploying an AWS Lambda function in order to help you get this code deployed to AWS so you can see it in action.

Once you get your Lambda function deployed, you can test it with the built-in test capability in the AWS console. You should see something similar to this output if you look at the CloudWatch log for your Lambda.

Here you can see that SpringBoot is started when the Lambda function is initialized (i.e. during cold start). If you created your handler class using the example Java code from above and started the SpringApplication in a static block, you’ll only see Spring being initialized once as long as AWS keeps your Lambda’s JVM loaded in memory. Subsequent invocations of the Lambda function will not re-start Spring. That’s exactly what you want! As your application grows and you configure more beans in the Spring application context, starting the spring application will take longer and longer and you definitely don’t want to have that happening during normal lambda event handling.

I’ve given you the basics that you need to get an AWS Lambda function up and running as a Spring Boot application. You’re a big kid now, and it’s time to take the training wheels off. Go ahead and give it a try, you can do it! If you want a look at how I did it, you can have a look at the GitHub repo for my little weather tracker application to get you started. If you want some more personalized help, send me a message or leave a comment. I’d love to help you get up and running!

Was this article helpful? Did you learn something? Was it worth your time, or a waste of time? I’d love to hear from you if you have questions or feedback on this article and/or if I can help you get past any stumbling blocks you may have encountered along the way!


Top comments (0)