takarajapaneseramen.com

Creating a Serverless Greetings Function with AWS and Spring Boot

Written on

Chapter 1: Introduction

In this guide, we will develop a serverless AWS Lambda function designed to return a greeting message. When provided with a name, the function will respond with "Hello <name>!!!". We’ll create a Spring Boot application called Greetings Lambda Function, leveraging Spring Cloud Function and the AWS Adapter to prepare the application for AWS Lambda deployment.

To facilitate testing, we will generate a Lambda Function URL that can be accessed using curl. For a smoother development experience, we will utilize LocalStack to simulate essential AWS services on our local environment.

Project Overview

So, let’s dive in!

Prerequisites

Before starting, ensure that you have Java 17+, Docker, and jq installed on your machine.

Creating the Greetings Lambda Function

We will initiate a Spring Boot application using Spring Initializr, naming it greetings-lambda-function without any additional dependencies for now. We will incorporate those later. We will use Spring Boot version 3.2.4 and Java 17. You can find the setup instructions linked here.

After clicking the GENERATE button, download the zip file, extract it to your preferred directory, and open the greetings-lambda-function project in your IDE.

Updating the pom.xml File

Next, let's modify the pom.xml to include the necessary dependencies. Below is the updated configuration:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>

<parent>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-parent</artifactId>

<version>3.2.4</version>

<relativePath/> <!-- lookup parent from repository -->

</parent>

<groupId>com.example</groupId>

<artifactId>greetings-lambda-function</artifactId>

<version>0.0.1-SNAPSHOT</version>

<name>greetings-lambda-function</name>

<description>Demo project for Spring Boot</description>

<properties>

<java.version>17</java.version>

<spring-cloud.version>2023.0.0</spring-cloud.version>

</properties>

<dependencies>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter</artifactId>

</dependency>

<dependency>

<groupId>org.springframework.cloud</groupId>

<artifactId>spring-cloud-function-adapter-aws</artifactId>

</dependency>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-test</artifactId>

<scope>test</scope>

</dependency>

</dependencies>

<dependencyManagement>

<dependencies>

<dependency>

<groupId>org.springframework.cloud</groupId>

<artifactId>spring-cloud-dependencies</artifactId>

<version>${spring-cloud.version}</version>

<type>pom</type>

<scope>import</scope>

</dependency>

</dependencies>

</dependencyManagement>

<build>

<plugins>

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-deploy-plugin</artifactId>

<configuration>

<skip>true</skip>

</configuration>

</plugin>

<plugin>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-maven-plugin</artifactId>

<configuration>

<layout>thin</layout>

</configuration>

</plugin>

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-shade-plugin</artifactId>

<executions>

<execution>

<phase>package</phase>

<goals>

<goal>shade</goal>

</goals>

<configuration>

<outputFile>${project.build.directory}/${project.artifactId}-${project.version}-aws.jar</outputFile>

</configuration>

</execution>

</executions>

</plugin>

</plugins>

</build>

</project>

We have introduced new properties to define the versions for Spring Cloud and the Spring Boot Thin Layout. A dependency for the Spring Cloud Function adapter for AWS Lambda has been added. This setup will allow us to manage dependencies more effectively.

Creating the Handler Package

To maintain an organized code structure, let’s create a handler package within the com.example.greetingslambdafunction root package.

Creating the Handler Class

In the handler package, we will create the GreetingsHandler class, which will contain the logic to process incoming messages and return formatted greetings.

package com.example.greetingslambdafunction.handler;

import java.util.function.Function;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.messaging.Message;

@Configuration

public class GreetingsHandler {

private static final Logger log = LoggerFactory.getLogger(GreetingsHandler.class);

@Bean

public Function<Message<String>, String> greetings() {

return message -> {

log.info("==> Headers: {}", message.getHeaders());

log.info("==> Payload: {}", message.getPayload());

return String.format("Hello %s!!!", message.getPayload());

};

}

}

The GreetingsHandler class is a configuration class that defines a function bean to process incoming messages, logging the headers and payload while returning a greeting message.

Creating the JAR Package Script

In the root directory of greetings-lambda-function, create the jar-package.sh script with the following content:

#!/usr/bin/env bash

./mvnw clean package -DskipTests

mkdir -p shared

cp target/greetings-lambda-function-java17-aws.jar shared

This script uses Maven to clean, compile, and package the project while skipping tests. It then creates a shared directory and copies the generated JAR file into it.

chmod +x jar-package.sh

Creating Docker Compose File

In the root directory of greetings-lambda-function, create the docker-compose.yml file with the following content:

version: "3.8"

services:

localstack:

container_name: localstack

image: localstack/localstack:3.2.0

ports:

  • "127.0.0.1:4510-4559:4510-4559"
  • "127.0.0.1:4566:4566"

environment:

  • LOCALSTACK_HOSTNAME=localhost.localstack.cloud
  • AWS_ACCESS_KEY_ID=key
  • AWS_SECRET_ACCESS_KEY=secret
  • AWS_DEFAULT_REGION=eu-west-1
  • SERVICES=lambda
  • DEBUG=${DEBUG-}

volumes:

  • "$PWD/tmp/localstack:/var/lib/localstack"
  • "$PWD/shared:/shared"
  • "/var/run/docker.sock:/var/run/docker.sock"

networks:

default:

aliases:

  • localhost.localstack.cloud

This file is based on LocalStack's official documentation, configuring Lambda as a service and mapping necessary volumes for shared access.

Creating LocalStack Initialization Script

In the greetings-lambda-function root folder, create the init-localstack.sh script with the following content:

#!/usr/bin/env bash

if ! [[ $(docker ps -q -f name=localstack) ]]; then

echo "WARNING: The localstack Docker container is not running. Please, start it first."

exit 1

fi

echo "Initializing LocalStack"

echo "======================="

echo "Creating Lambda Function called GreetingsLambdaFunction"

docker exec -t localstack aws --endpoint-url=http://localhost:4566 lambda create-function

--function-name GreetingsLambdaFunction

—runtime java17

--memory-size 512

—handler org.springframework.cloud.function.adapter.aws.FunctionInvoker::handleRequest

--zip-file fileb:///shared/greetings-lambda-function-java17-aws.jar

—environment "Variables={AWS_REGION=eu-west-1,AWS_ACCESS_KEY_ID=key,AWS_SECRET_ACCESS_KEY=secret}"

--role arn:aws:iam::000000000000:role/service-role/irrelevant

—timeout 60

echo "Creating a Function URL to GreetingsLambdaFunction"

docker exec -t localstack aws --endpoint-url=http://localhost:4566 lambda create-function-url-config

--function-name GreetingsLambdaFunction

—auth-type NONE

echo "LocalStack initialized successfully"

This script initializes LocalStack and creates the Lambda function, setting up the necessary configurations.

chmod +x init-localstack.sh

Packaging the Greetings Lambda Function JAR

Ensure you are in the greetings-lambda-function root folder. Run the jar-package.sh script:

./jar-package.sh

The greetings-lambda-function-java17-aws.jar file should now be present in the shared folder.

Starting the Environment

In a terminal, navigate to the greetings-lambda-function root folder and run:

DEBUG=1 docker compose up -d

Then, execute the init-localstack.sh script:

./init-localstack.sh

If everything is set up correctly, you should see confirmation messages in the terminal regarding the creation of the Lambda function and its URL.

Testing Endpoints

To interact with the Greetings Lambda function endpoint, retrieve the Function URL using the AWS CLI:

GREETINGS_LAMBDA_FUNCTION_URL=$(docker exec -t localstack aws --endpoint-url=http://localhost:4566 lambda get-function-url-config --function-name GreetingsLambdaFunction | jq -r '.FunctionUrl')

echo $GREETINGS_LAMBDA_FUNCTION_URL

You can then send a greeting request using curl:

curl -i -X POST $GREETINGS_LAMBDA_FUNCTION_URL

-H 'Content-Type: application/json'

-d 'Ivan'

The expected response should be:

HTTP/1.1 200

...

"Hello Ivan!!!"

Note that the first request may take some time as Docker initializes the container for the Greetings Lambda Function.

Shutdown

To stop LocalStack and the Greetings Lambda Function Docker containers, run:

docker compose down -v

Conclusion

In this article, we successfully built a serverless AWS Lambda function for greetings. We developed a Spring Boot application named Greetings Lambda Function, adapted it for AWS Lambda using Spring Cloud Function and the AWS Adapter, and deployed it to AWS LocalStack. Finally, we tested the endpoint and received a personalized greeting.

Additional Readings

Support and Engagement

If you found this article helpful, consider the following actions:

👏 Engage by clapping, highlighting, and replying to my story. I'm happy to answer your questions.

🌐 Share this article on social media.

🔔 Follow me on: Medium | LinkedIn | Twitter | GitHub.

✉️ Subscribe to my newsletter to stay updated with my latest posts.

Chapter 2: Videos and More Resources

This video provides an overview of using Spring Cloud Function on AWS Lambda with API Gateway, which aligns with the concepts discussed in this guide.

In this video, learn how to deploy serverless functions across various platforms using Spring Cloud Function, expanding upon the topics we've covered.

Share the page:

Twitter Facebook Reddit LinkIn

-----------------------

Recent Post:

Reviving Your Dreams: The Journey Back to Acting

Exploring the significance of pursuing dreams and personal growth through the lens of acting.

Innovative Approaches to Tooth Regrowth: A New Hope

Exploring new advancements in tooth regeneration that could change dental health for many.

Navigating Spring Data: From JDBC to JPA and Beyond

Explore the differences between Spring Data JPA, JDBC, and MyBatis, and discover which to choose for your project.