Please check out my previous tutorial which provides a basic introduction on using Spring Cloud Function.
This time, we will integrate Spring Cloud Function with AWS Lambda which is a serverless compute service that lets you run code without provisioning or managing servers, creating workload-aware cluster scaling logic, maintaining event integrations, or managing runtimes.
You can check this reference for the complete guide on how to setup AWS Lambda with Spring Cloud Functions.
Note: We will use the traditional bean definitions instead of the functional bean style for this tutorial.
The main goal of Spring Cloud Function is to make your application code to be cloud-agnostic. Our entry-point SpringcloudfuncApplication.class
@SpringBootApplication
public class SpringcloudfuncApplication {
public static void main(String[] args) {
SpringApplication.run(SpringcloudfuncApplication.class, args);
}
@Bean
public CreateAccount createAccount() {
return new CreateAccount();
}
@Bean
public ReadAccount readAccount() {
return new ReadAccount();
}
}
The interesting part of the code above is that we do not see any AWS-related configuration to setup our application to AWS Lambda. In fact, we just have to add the needed dependencies and deploy our package!
In order to run Spring Cloud Function applications on AWS Lambda, we need to add below dependency.
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-function-adapter-aws</artifactId>
</dependency>
We need a shaded JAR in order to upload our code to AWS Lambda. A shaded artifact means it has all the dependencies exploded out as individual class files instead of jars. One can use the Maven Shade Plugin for such.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<shadedArtifactAttached>true</shadedArtifactAttached>
<shadedClassifierName>aws</shadedClassifierName>
</configuration>
</plugin>
In addition, we can use spring-boot-thin-layout dependency to help us reduce the size of the artifact by excluding some dependencies that are not needed:
<dependency>
<groupId>org.springframework.boot.experimental</groupId>
<artifactId>spring-boot-thin-layout</artifactId>
<version>${spring-boot-thin-layout.version}</version>
</dependency>
Please check our pom.xml for the complete configuration to achieve the deployable JAR to AWS Lambda.
Now, one can just run below command to generate the AWS deployable JAR:
./mvnw clean package
There will be three JARs under the target folder. Select the one with the name springcloudfunc-0.0.1-SNAPSHOT-aws.jar. Take note of this file as we will need this in the succeeding steps involving AWS Lambda creation.
- Go to AWS Lambda then create a function by providing a unique name (e.g., MyCreateAccountFunc) and runtime environment (e.g., Java 11)
- Once successfully created, let's setup the configuration by uploading the AWS deployable JAR (springcloudfunc-0.0.1-SNAPSHOT-aws.jar) under the Function Code section
- Update the Handler field under Runtime settings section and paste below default handler provided by Spring Cloud Function
org.springframework.cloud.function.adapter.aws.FunctionInvoker::handleRequest
- Let's edit the Environment variables and add a new entry SPRING_CLOUD_FUNCTION_DEFINITION with the value based on your bean method name. Take note that AWS Lambda can process ONLY ONE function at a time hence, if your code has more than one bean functions then create a new AWS lambda for that. For our case, we have two traditional bean definitions thus, we select only one. For this step, we select the createAccount bean which will result to:
SPRING_CLOUD_FUNCTION_DEFINITION=createAccount
Let's now test the AWS Lambda function by creating a test event and supplying a sample json body.
- Select your newly created function then click Test or select from the dropdown beside it Configure test events
- Continue with the default "hello-world" template and fill in the needed items. See sample json body below:
{
"name": "Jun King Minon",
"balance": 12000
}
- Now make sure that the newly created test event is selected on the Saved Test Events dropdown then click Test.
This will trigger the AWS Lambda Function you have just created. It will display a loading icon during the cold starts (if initial trigget it may take some time). One should be notified with Execution result: succeeded message and can click Details to see something similar to below logs:
START RequestId: 14d9a92f-9730-452e-a2b1-341b3dd6a951 Version: $LATEST
2021-03-01 03:48:50.531 INFO 8 --- [ main] o.s.c.f.a.aws.CustomRuntimeEventLoop : Located function createAccount
2021-03-01 03:48:50.531 INFO 8 --- [ main] o.s.c.f.adapter.aws.AWSLambdaUtils : Incoming JSON Event: {"name":"Jun King Minon","balance":12000}
2021-03-01 03:48:50.549 INFO 8 --- [ main] o.s.c.f.a.aws.CustomRuntimeEventLoop : Result POST status: 202 ACCEPTED
END RequestId: 14d9a92f-9730-452e-a2b1-341b3dd6a951
REPORT RequestId: 14d9a92f-9730-452e-a2b1-341b3dd6a951 Duration: 24.61 ms Billed Duration: 25 ms Memory Size: 512 MB Max Memory Used: 203 MB
In reality, we need to expose an API endpoint to be invoked by users (or customers) in order to trigger our AWS Lambda function.
- Select your newly created AWS Lambda function
- Under Designer section, click Add trigger and select API Gateway
- On the API dropdown, select the Create an API option.
- Select REST API type
- Select Open security mechanism for now. One would want to use JWT authorizer but this is out of scope for this basic tutorial.
- Click Add button
API Gateway should now be added as part of your triggers under Layers of Designer section. Click this API Gateway and expand details. Take note of the API endpoint which could be something like this:
https://ovspn81pl0.execute-api.ap-southeast-1.amazonaws.com/default/MyCreateAccountFunc
Now one can invoke the API Gateway endpoint above in any API tool such as Postman or cURL. Using cURL, we can call:
- Create Account function by:
curl -H "Content-type: application/json" -X POST -d '{"name":"Jun King Minon", "balance": 12000}' https://ovspn81pl0.execute-api.ap-southeast-1.amazonaws.com/default/MyCreateAccountFunc
- Read Account using function by:
curl https://8jy9vksw5l.execute-api.ap-southeast-1.amazonaws.com/default/MyReadAccountFunc
Note: Repeat the above steps when creating a new AWS Lambda function for the readAccount bean function definition.
Contact me at junbetterway
Happy coding!!!