Creating a Spring Boot Lambda on AWS
Learn how to build and deploy a simple spring boot based AWS lambda and then automate its deployment with Terraform.
full courseNow we’re going to add some code. I’m going to follow my ports and adapters method of building a DTO and value object that I’ve used previously. Yes, its a bit of overkill for this project (especially a hello world example), but if you’re using this course as a springboard to build another project, I think its a good habit to get into. Especially since lambda functional code supplied by spring introduces some code you may not want in your service layer.
Build the Service Layer
create a class in a new service
package for the service:
package com.bullyrooks.helloworldlambda.service;
import com.bullyrooks.helloworldlambda.service.vo.HelloWorld;
import org.springframework.stereotype.Component;
@Component
public class HelloWorldService {
public HelloWorld helloWorld(String name) {
return HelloWorld.builder()
.response("Hello, " + name)
.build();
}
}
Create a new value object to handle the response in a new package service/vo
package com.bullyrooks.helloworldlambda.service.vo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class HelloWorld {
private String response;
}
We’ll need to import some libraries to support the function features, so add these libraries to your pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
...
<properties>
<java.version>11</java.version>
<aws-lambda-java-events.version>3.1.0</aws-lambda-java-events.version>
<aws-lambda-java-core.version>1.2.0</aws-lambda-java-core.version>
<spring-cloud.version>Hoxton.SR6</spring-cloud.version>
<wrapper.version>1.0.11.RELEASE</wrapper.version>
</properties>
...
<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>
...
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-function-adapter-aws</artifactId>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-events</artifactId>
<version>${aws-lambda-java-events.version}</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-core</artifactId>
<version>${aws-lambda-java-core.version}</version>
</dependency>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<archive>
<manifest>
<mainClass>com.bullyrooks.helloworldlambda.HelloworldLambdaApplication</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<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>
<dependencies>
<dependency>
<groupId>org.springframework.boot.experimental</groupId>
<artifactId>spring-boot-thin-layout</artifactId>
<version>${wrapper.version}</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<shadedArtifactAttached>true</shadedArtifactAttached>
<shadedClassifierName>aws</shadedClassifierName>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
<finalName>${project.name}</finalName>
First off, I’m downgrading the version of spring boot parent. I thought I had some trouble with java 11, the spring boot parent and the version of the spring cloud that I was bringing in and this combination worked. Second, I’m setting up the properties for the versions of the dependencies I’m bringing in. Next, setting up spring cloud dependency management because I have one spring cloud dependency. Also, adding a bunch of new dependencies.
The plugins need more explanation:
- maven jar plugin is identifying the spring boot application class so that the command line startup can find it quickly
- spring boot maven is adding a thin layout to try and keep the size of the jar down
- maven shade plugin identifies our dependencies and pulls them into an uber jar which allows the .jar to operate without any jars on (external) classpath
We’re going to want uber jars (that contain all of their dependencies) that are very small (because this helps with keeping storage costs down and improves transfer speeds).
Add the Function
First, create a new package function
and add this class:
@Component
public class HelloWorldFunction implements Function<String, String> {
@Autowired
HelloWorldService helloWorldService;
@Override
public String apply(String input) {
return helloWorldService.helloWorld(input).getResponse();
}
}
That’s all you need. We’re going to use some spring magic to wire this up. But first, rebuild so we can deploy
$ mvn clean package
...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 8.505 s
[INFO] Finished at:
[INFO] ------------------------------------------------------------------------
Create the Lambda
Now log into aws console and navigate to the Lambda
section
Click Create Function
Choose Author from scratch
Name the lambda and choose the java 11 runtime
In code source, click upload from
Choose the helloworld-lambda-0.0.1-SNAPSHOT-aws.jar
which is the shaded uber jar (which has also been slimmed down).
Edit the runtime settings to use the built in aws function invoker
Finally, go to the configuration tab, select environment variables and add an environment variable for a key of FUNCTION_NAME
and a value of your function class HelloWorldFunction
Test the Lambda
Go to the Test
tab, use the hello-world template and add a test that looks like this:
and hit test. You should see a succeeded output:
Commit and Finish
We’ve got a working lambda! Its not very useful at this point though. We’ll add an API to it next.
Let’s commit and merge.
$ git status
On branch function
Your branch is up to date with 'origin/function'.
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: pom.xml
modified: src/main/java/com/bullyrooks/helloworldlambda/HelloworldLambdaApplication.java
Untracked files:
(use "git add <file>..." to include in what will be committed)
src/main/java/com/bullyrooks/helloworldlambda/function/
no changes added to commit (use "git add" and/or "git commit -a")
$ git add .
$ git commit -m "working lambda"
[function ced0de0] working lambda
3 files changed, 144 insertions(+), 86 deletions(-)
rewrite pom.xml (97%)
create mode 100644 src/main/java/com/bullyrooks/helloworldlambda/function/HelloWorldFunction.java
$ git push
Logon failed, use ctrl+c to cancel basic credential prompt.
Username for 'https://github.com': bullyrooks
Password for 'https://[email protected]':
Enumerating objects: 21, done.
Counting objects: 100% (21/21), done.
Delta compression using up to 4 threads
Compressing objects: 100% (9/9), done.
Writing objects: 100% (12/12), 2.12 KiB | 2.12 MiB/s, done.
Total 12 (delta 2), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (2/2), completed with 2 local objects.
To https://github.com/bullyrooks/helloworld-lambda.git
0420e4f..ced0de0 function -> function
$ git checkout main
$ git merge function
$ git push
0 comments on “Spring Boot Lambda Implementation”Add yours →