Creating AWS Lambda using java and spring framework

Introduction

AWS Lambda is another way to use cloud computing on Amazon’s AWS.

It allows you deliver you code and run in production without any server management.

It is auto-scale, high available and you pay only when you are using your function.

Creating the Application

For this basic example, I choose the spring as framework because most of my webservices are created using this framework.

If you are using eclipse, you can install the AWS Toolkit for eclipse. It is very helpful during development and testing stages.

First, you have create the pom.xml file:

<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>
 <groupId>br.com.presba</groupId>
 <artifactId>presba-lambda</artifactId>
 <version>0.0.1</version>
 <name>presba-lambda</name>

 <properties>
 <spring.version>4.0.1.RELEASE</spring.version>
 <java.version>1.8</java.version>
 </properties>

 <dependencies>
 <dependency>
 <groupId>com.amazonaws</groupId>
 <artifactId>aws-lambda-java-core</artifactId>
 <version>1.1.0</version>
 </dependency>
 <dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-core</artifactId>
 <version>${spring.version}</version>
 </dependency>

 <dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-context</artifactId>
 <version>${spring.version}</version>
 </dependency>
 </dependencies>

 <build>
 <plugins>
 <plugin>
 <groupId>org.apache.maven.plugins</groupId>
 <artifactId>maven-shade-plugin</artifactId>
 <configuration>
 <createDependencyReducedPom>false</createDependencyReducedPom>
 </configuration>
 <executions>
 <execution>
 <phase>package</phase>
 <goals>
 <goal>shade</goal>
 </goals>
 </execution>
 </executions>
 </plugin>
 </plugins>
 </build>
</project>

As you can see, the dependencies for the spring framework and aws lambda are defined and the plugin maven-shade-plugin is set in the build section.

Below are the structure and the files used in this project.

presba-lambda
    src/main/java
        br.com.presba
            dao
                BasicSample.java
            Application.java
            LambaFunctionHandler.java
    src/main/resources
        application-context.xml

application-context.xml

<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
 xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
 xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
 xmlns:task="http://www.springframework.org/schema/task"
 xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd 
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd 
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd 
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd 
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd 
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.2.xsd">

<context:component-scan base-package="br.com.presba" />
</beans>

Application.java

package br.com.presba;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Application {
    private static ApplicationContext springContext = null;
    private static ApplicationContext getSpringContext() {
        if (springContext == null) {
            synchronized (ApplicationContext.class) {
                if (springContext == null) {
                    springContext = new ClassPathXmlApplicationContext("/application-context.xml");
                }
            }
        }
        return springContext;
    }
    public static <T> T getBean(Class<T> clazz) {
        return getSpringContext().getBean(clazz);
    }
}

In the Application.java file is created the ApplicationContext using singleton pattern and the ApplicationContext.getBean is encapsulated in the Application.getBean protecting the application context for been accessed from other classes.

LambdaFunctionHandler.java

package br.com.presba;

import java.util.Calendar;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import br.com.presba.dao.BasicSample;

public class LambdaFunctionHandler implements RequestHandler<String, String> {
    private BasicSample basicSample;
    public String handleRequest(String input, Context context) {
        basicSample = Application.getBean(BasicSample.class);
        context.getLogger().log("AWS Request ID: " + context.getAwsRequestId());
        context.getLogger().log("Input: " + input + " at " + Calendar.getInstance().getTimeInMillis());
        return basicSample.doSomething(input);
    }
}

In the LambdaFunctonHandler.java the RequestHandler interface is implemented in order to receive the AWS Lambda call.

BasicSample.java

package br.com.presba.dao;

import org.springframework.stereotype.Component;

@Component
public class BasicSample {
    public String doSomething(String input) {
        return "Something has done with the input " + input;
    }
}

In this BasicSample.java file the method doSomething uses the input string and returns a new string.

Deploying on AWS

The AWS Toolkit helps us on this step. The only thing we have to do is open the any .java file, open the context menu (right-click), chose “AWS Lambda” and then “Upload function to AWS Lambda…” option.

Selection_002

You will see the window below:

_003

Chose the “Create a new Lambda function” option, type the name BasicSampleFunction and click “Next”.

_004

In the window above, you must create a IAM role and a S3 Bucket for your function.

You also need to change the Memory to 512MB, because with less memory, the application takes longer during cold start.

Click Finish and wait until your function is deployed.

Uploading function code to Lambda _005

Running the Function

It’s time to test our work. Right click on any .java file, chose “AWS Lambda” and then “Run function on AWS Lambda…” option.

Selection_002

In the window below, type any text you want to pass to your lambda function and click “Invoke”

Lambda Function Input _006

In the first execution, it will take some time to start your application (~ 3 sec).

If everything works fine, you will see the output in the console.

Selection_007Troubleshooting

If you want to see the log of your call, you can go to the CloudWatch and click on the Log in the left menu.

Look for your function, the log should be /aws/lambda/FunctionName, click on it and a new window will appear.

Chose the first (or the only) Log Stream to see the log.

Conclusion

This is just a start point for the AWS Lambda, you can try some other frameworks instead of spring.

In the next post I’ll show how to create a API Gateway and call the lamba function.

 

Advertisements

5 thoughts on “Creating AWS Lambda using java and spring framework

Add yours

  1. Is there anything that would prevent the spring context from being loaded on every call to this lambda function? If not or if the context needs to be loaded frequently, the response time will not be good right? Is there some way to reduce the impact of spring context loading in a lambda function call? Does it even make sense to use spring in a lambda function? I suppose your spring context could be smaller and lighter since you would be focused on a single api, but it seems to me that use of the spring context makes more sense for a full application server or batch job.

    Like

    1. I totally agree with you. Does not make sense to use spring in lambda function, however you may have some legacy app running spring and you need to deploy it fast and serverless.

      Like

  2. Hi,

    Somehow I am getting below error while running above example on AWS. Any idea?

    errorMessage”: “Line 12 in XML document from class path resource [application-context.xml] is invalid; nested exception is org.xml.sax.SAXParseException; lineNumber: 12; columnNumber: 113; cvc-elt.1: Cannot find the declaration of element ‘beans’.”,
    “errorType”: “org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException”,

    Like

    1. Are you using the same version of spring as me? Also, did you change de xsd confing in the application-context.xml?

      Make sure that the parameter xsi:schemaLocation is the same as below:

      xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
      http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
      http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
      http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd
      http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
      http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.2.xsd"

      Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Create a free website or blog at WordPress.com.

Up ↑

%d bloggers like this: