diff --git a/README.md b/README.md
index f1d0e1d..7170311 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,19 @@
-# Spring boot
+# Spring boot with AWS Lambda
+
+Sample application to demonstrate running a Spring Boot application as an AWS Lambda built with Cloud formation.
+
+# AWS Lambda
+
+Build the code and deploy with AWS SAM.
+
+mvn clean package
+
+aws cloudformation package --template-file sam.yaml --output-template-file target/output-sam.yaml --s3-bucket lambda-cfn
+
+aws cloudformation deploy --template-file target/output-sam.yaml --stack-name spring-boot-lambda --capabilities CAPABILITY_IAM
+
+aws cloudformation describe-stacks --stack-name spring-boot-lambda
-Sample Spring Boot application with a single REST API.
# Run
@@ -10,14 +23,14 @@ To build and run from a packaged jar locally:
or
- mvn clean package
+ mvn clean package -Dboot
java -jar target/spring-boot-lambda-1.0.0-SNAPSHOT.jar
# Docker
To build the image. First build the application, then build the docker image
- mvn package
+ mvn package -Dboot
docker build -t spring-boot-lambda .
## Run
diff --git a/pom.xml b/pom.xml
index 762cf58..3c2409a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -23,15 +23,65 @@
org.springframework.boot
spring-boot-starter-web
+
+
+ com.amazonaws.serverless
+ aws-serverless-java-container-spring
+ [0.1,)
+
-
-
-
- org.springframework.boot
- spring-boot-maven-plugin
-
-
-
+
+
+ boot
+
+
+ boot
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
+ default
+
+ true
+
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+ 2.3
+
+ false
+
+
+
+ package
+
+ shade
+
+
+
+
+ org.apache.tomcat.embed:*
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sam.yaml b/sam.yaml
new file mode 100644
index 0000000..76e2e4c
--- /dev/null
+++ b/sam.yaml
@@ -0,0 +1,27 @@
+AWSTemplateFormatVersion: '2010-09-09'
+Transform: AWS::Serverless-2016-10-31
+Description: Lambda with spring boot.
+
+Resources:
+ LambdaSpringBootFunction:
+ Type: AWS::Serverless::Function
+ Properties:
+ Handler: com.keyholesoftware.lambda.LambdaHandler::handleRequest
+ Runtime: java8
+ CodeUri: target/spring-boot-lambda-1.0.0-SNAPSHOT.jar
+ MemorySize: 1512
+ Policies: AWSLambdaBasicExecutionRole
+ Timeout: 60
+ Events:
+ GetResource:
+ Type: Api
+ Properties:
+ Path: /{proxy+}
+ Method: any
+
+Outputs:
+ LambdaSpringBootApi:
+ Description: URL for application
+ Value: !Sub 'https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Stage/languages'
+ Export:
+ Name: LambdaSpringBootApi
diff --git a/src/main/java/com/keyholesoftware/lambda/LambdaHandler.java b/src/main/java/com/keyholesoftware/lambda/LambdaHandler.java
new file mode 100644
index 0000000..b91b8d3
--- /dev/null
+++ b/src/main/java/com/keyholesoftware/lambda/LambdaHandler.java
@@ -0,0 +1,36 @@
+package com.keyholesoftware.lambda;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import com.amazonaws.serverless.exceptions.ContainerInitializationException;
+import com.amazonaws.serverless.proxy.model.AwsProxyRequest;
+import com.amazonaws.serverless.proxy.model.AwsProxyResponse;
+import com.amazonaws.serverless.proxy.spring.SpringBootLambdaContainerHandler;
+import com.amazonaws.services.lambda.runtime.Context;
+import com.amazonaws.services.lambda.runtime.RequestStreamHandler;
+
+public class LambdaHandler implements RequestStreamHandler {
+
+ private static SpringBootLambdaContainerHandler handler;
+
+ static {
+ try {
+ handler = SpringBootLambdaContainerHandler.getAwsProxyHandler(Application.class);
+ handler.activateSpringProfiles("lambda");
+ } catch (ContainerInitializationException e) {
+ // Re-throw the exception to force another cold start
+ e.printStackTrace();
+ throw new RuntimeException("Could not initialize Spring Boot application", e);
+ }
+ }
+
+ @Override
+ public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) throws IOException {
+ handler.proxyStream(inputStream, outputStream, context);
+
+ // just in case it wasn't closed by the mapper
+ outputStream.close();
+ }
+}
diff --git a/src/main/java/com/keyholesoftware/lambda/config/Config.java b/src/main/java/com/keyholesoftware/lambda/config/Config.java
new file mode 100644
index 0000000..5fa592d
--- /dev/null
+++ b/src/main/java/com/keyholesoftware/lambda/config/Config.java
@@ -0,0 +1,56 @@
+package com.keyholesoftware.lambda.config;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+import org.springframework.web.servlet.HandlerAdapter;
+import org.springframework.web.servlet.HandlerExceptionResolver;
+import org.springframework.web.servlet.HandlerMapping;
+import org.springframework.web.servlet.ModelAndView;
+import org.springframework.web.servlet.config.annotation.EnableWebMvc;
+import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
+import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
+
+@Configuration
+@EnableWebMvc
+@Profile("lambda")
+public class Config {
+
+ /**
+ * Create required HandlerMapping, to avoid several default HandlerMapping instances being created
+ */
+ @Bean
+ public HandlerMapping handlerMapping() {
+ return new RequestMappingHandlerMapping();
+ }
+
+ /**
+ * Create required HandlerAdapter, to avoid several default HandlerAdapter instances being created
+ */
+ @Bean
+ public HandlerAdapter handlerAdapter() {
+ return new RequestMappingHandlerAdapter();
+ }
+
+ /**
+ * optimization - avoids creating default exception resolvers; not required as the serverless container handles
+ * all exceptions
+ *
+ * By default, an ExceptionHandlerExceptionResolver is created which creates many dependent object, including
+ * an expensive ObjectMapper instance.
+ */
+ @Bean
+ public HandlerExceptionResolver handlerExceptionResolver() {
+ return new HandlerExceptionResolver() {
+
+ @Override
+ public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
+ return null;
+ }
+ };
+ }
+
+}