├── .gitignore
├── README.md
├── pom.xml
├── src
└── main
│ ├── java
│ └── com
│ │ ├── cagataygurturk
│ │ └── example
│ │ │ ├── config
│ │ │ └── SpringConfig.java
│ │ │ ├── lambda
│ │ │ ├── AbstractHandler.java
│ │ │ └── MainHandler.java
│ │ │ └── services
│ │ │ ├── AnotherService.java
│ │ │ └── Service.java
│ │ └── example
│ │ ├── config
│ │ └── SpringConfig.java
│ │ ├── lambda
│ │ ├── AbstractHandler.java
│ │ └── MainHandler.java
│ │ └── services
│ │ ├── AnotherService.java
│ │ └── Service.java
│ └── resources
│ └── log4j.properties
└── tests
└── com
└── cagataygurturk
└── example
└── services
└── ServiceTest.java
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | *.iml
3 |
4 | ## File-based project format:
5 | *.iws
6 |
7 | ## Plugin-specific files:
8 |
9 | # IntelliJ
10 | /out/
11 |
12 | # mpeltonen/sbt-idea plugin
13 | .idea_modules/
14 |
15 | # JIRA plugin
16 | atlassian-ide-plugin.xml
17 |
18 | aws
19 | target
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # AWS Lambda Boilerplate for JAVA and Spring IoC
2 |
3 | Do you miss JAVA, its great features and all Spring framework sugar in AWS Lambda? Use this boilerplate code to author JAVA functions in Lambda and enjoy all features of Spring IoC. It also supports local debugging of JAVA functions.
4 |
5 | ## Usage
6 |
7 | The code is already documented. **MainHandler** is the main entrance point of your lambda function. **services** package includes Spring Beans. For default, MainHandler fetches **Service** Bean from IoC container but once you have Service instance you can use Autowiring features.
8 |
9 | ### Local running
10 |
11 | In root folder fire
12 |
13 | ```
14 | mvn compile exec:java
15 | ```
16 |
17 | You can configure your IDE to run com.example.lambda.local.LocalRunner as Main Class and com.cagataygurturk.lambda.MainHandler as program argument to debug locally your function.
18 |
19 | ### Deployment
20 |
21 | In root folder fire
22 |
23 | ```
24 | mvn package -Denv=production
25 | ```
26 |
27 | This creates a JAR package in target folder.
28 |
29 | As you can see in `pom.xml`, "-Denv=production" activates production profile and it excludes `aws-lambda-local-runner` dependency from deployment package in order to get rid of a unnecessary dependency which is not needed in production environment. Forgetting this does not affect the project but it increases JAR package size.
30 |
31 | You can upload the created JAR folder to AWS Lambda console. Handler function should be configured to `com.cagataygurturk.example.lambda.MainHandler`.
32 |
33 | ## More about the topic
34 |
35 | - Check out [Lambada Framework](https://github.com/lambadaframework/lambadaframework) for seamless AWS Lambda and JAVA integration.
36 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
12 | * - Local runner uses getExampleEvent() method to find the example event that you use during your events.
13 | *
14 | * @param
17 | * - It configures automatically Spring IoC. To enable this support Concrete handler classes extends this class with T type
18 | * which should implement @Configuration interface.
19 | * @see MainHandler
20 | *
21 | *
22 | * Every lambda handler class should extend this abstract base class and normally you do not touch this class
23 | */
24 | @SuppressWarnings("unused")
25 | public abstract class AbstractHandler
36 | * Event json that lambda function got is automatically serialized to this POJO. For more details see Lambda documentation:
37 | *
38 | * @link http://docs.aws.amazon.com/lambda/latest/dg/java-handler-io-type-pojo.html
39 | */
40 | public static class Request {
41 | String firstName;
42 | String lastName;
43 |
44 | public String getFirstName() {
45 | return firstName;
46 | }
47 |
48 | public void setFirstName(String firstName) {
49 | this.firstName = firstName;
50 | }
51 |
52 | public String getLastName() {
53 | return lastName;
54 | }
55 |
56 | public void setLastName(String lastName) {
57 | this.lastName = lastName;
58 | }
59 |
60 | public Request(String firstName, String lastName) {
61 | this.firstName = firstName;
62 | this.lastName = lastName;
63 | }
64 |
65 | public Request() {
66 | }
67 | }
68 |
69 | /**
70 | * Response is also a POJO that will handler return and
71 | * Lambda runtime automatically serializes it to JSON. Again see the documentation.
72 | *
73 | * @link http://docs.aws.amazon.com/lambda/latest/dg/java-handler-io-type-pojo.html
74 | */
75 | public static class Response {
76 | String greetings;
77 |
78 | public String getGreetings() {
79 | return greetings;
80 | }
81 |
82 | public void setGreetings(String greetings) {
83 | this.greetings = greetings;
84 | }
85 |
86 | public Response(String greetings) {
87 | this.greetings = greetings;
88 | }
89 |
90 | public Response() {
91 | }
92 |
93 | }
94 |
95 |
96 | /**
97 | * Main handler method is invoked when Lambda function is invoked. You should configure the name of this method in the AWS Console.
98 | * In this example, the value would be com.cagataygurturk.lambda.MainHandler. As we implement RequestHandler interface Lambda runtime
99 | * detects this method automatically and invokes it.
100 | *
101 | *
102 | *
103 | * As a best practice, this method should be kept very short and all the business logic should sit
104 | * in "Service" instance that we will fetch from Spring IoC container and will enjoy from all
105 | * Spring IoC features.
106 | *
107 | * Lambda specific code ends here and beginning from this point old good JAVA starts.
108 | *
109 | * @param request Request object
110 | * @param context Context object
111 | * @return Response
112 | * @throws RuntimeException
113 | * @see RequestHandler
114 | */
115 | public Response handleRequest(Request request, Context context)
116 | throws RuntimeException {
117 |
118 | /**
119 | * BusinessService is where all our business logic sits.
120 | */
121 | Service businessService = getApplicationContext().getBean(Service.class);
122 | return new Response(businessService.getText(request.getFirstName() + " " + request.getLastName()));
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/src/main/java/com/cagataygurturk/example/services/AnotherService.java:
--------------------------------------------------------------------------------
1 | package com.cagataygurturk.example.services;
2 |
3 | import org.springframework.stereotype.Component;
4 |
5 | @Component
6 | public class AnotherService {
7 |
8 | public String getText(String text) {
9 | return "Hi " + text;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/com/cagataygurturk/example/services/Service.java:
--------------------------------------------------------------------------------
1 | package com.cagataygurturk.example.services;
2 |
3 | import org.springframework.beans.factory.annotation.Autowired;
4 | import org.springframework.stereotype.Component;
5 |
6 | @Component
7 | public class Service {
8 |
9 | /**
10 | * Autowiring another Spring Bean
11 | */
12 | @Autowired
13 | AnotherService anotherService;
14 |
15 | public String getText(String text) {
16 | return anotherService.getText(text);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/java/com/example/config/SpringConfig.java:
--------------------------------------------------------------------------------
1 | package com.example.config;
2 |
3 | import org.springframework.context.annotation.ComponentScan;
4 | import org.springframework.context.annotation.Configuration;
5 |
6 |
7 | @Configuration
8 | @ComponentScan("com.example")
9 | public class SpringConfig {
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/com/example/lambda/AbstractHandler.java:
--------------------------------------------------------------------------------
1 | package com.example.lambda;
2 |
3 | import org.springframework.context.ApplicationContext;
4 | import org.springframework.context.annotation.AnnotationConfigApplicationContext;
5 | import org.springframework.context.annotation.Configuration;
6 |
7 | import java.lang.reflect.ParameterizedType;
8 |
9 | /**
10 | * Every lambda handler class should extend this abstract base class
11 | *
12 | * T type parameter is used to determine the Spring @Configuration class, thus T should be a class that declares @Configuration annotation. Otherwise, an exception is thrown.
13 | *
14 | * @param
92 | * As a best practice, this method should be kept very short and all the business logic should sit
93 | * in "Service" instance that we will fetch from Spring IoC container and will enjoy from all
94 | * Spring IoC features.
95 | *
96 | * Lambda specific code ends here and beginning from this point old good JAVA starts.
97 | *
98 | * @param request
99 | * @param context
100 | * @return Response
101 | * @throws RuntimeException
102 | */
103 | public Response handleRequest(Request request, Context context)
104 | throws RuntimeException {
105 |
106 | Service businessService = getApplicationContext().getBean(Service.class);
107 | return new Response(businessService.getText(request.getFirstName() + " " + request.getLastName()));
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/src/main/java/com/example/services/AnotherService.java:
--------------------------------------------------------------------------------
1 | package com.example.services;
2 |
3 | import org.springframework.stereotype.Component;
4 |
5 | @Component
6 | public class AnotherService {
7 |
8 | public String getText(String text) {
9 | return "Hi " + text;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/com/example/services/Service.java:
--------------------------------------------------------------------------------
1 | package com.example.services;
2 |
3 | import org.springframework.beans.factory.annotation.Autowired;
4 | import org.springframework.stereotype.Component;
5 |
6 | @Component
7 | public class Service {
8 |
9 | @Autowired
10 | AnotherService service2;
11 |
12 | public String getText(String text) {
13 | return service2.getText(text);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/resources/log4j.properties:
--------------------------------------------------------------------------------
1 | log = .
2 | log4j.rootLogger = DEBUG, LAMBDA
3 |
4 | #Define the LAMBDA appender
5 | log4j.appender.LAMBDA=com.amazonaws.services.lambda.runtime.log4j.LambdaAppender
6 | log4j.appender.LAMBDA.layout=org.apache.log4j.PatternLayout
7 | log4j.appender.LAMBDA.layout.conversionPattern=%d{yyyy-MM-dd HH:mm:ss} <%X{AWSRequestId}> %-5p %c{1}:%L - %m%n
--------------------------------------------------------------------------------
/tests/com/cagataygurturk/example/services/ServiceTest.java:
--------------------------------------------------------------------------------
1 | package com.cagataygurturk.example.services;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 |
8 | public class ServiceTest {
9 | @Test
10 | public void CreateTest() {
11 | Service service = new Service();
12 | assertTrue(true);
13 | }
14 | }
--------------------------------------------------------------------------------