JAVA-10628: Create new aws-modules and move other aws related modules
inside it
This commit is contained in:
1
aws-modules/aws-lambda/.gitignore
vendored
Normal file
1
aws-modules/aws-lambda/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
.aws-sam/
|
||||
11
aws-modules/aws-lambda/README.md
Normal file
11
aws-modules/aws-lambda/README.md
Normal file
@@ -0,0 +1,11 @@
|
||||
## AWS Lambda
|
||||
|
||||
This module contains articles about AWS Lambda
|
||||
|
||||
### Relevant Articles:
|
||||
- [A Basic AWS Lambda Example With Java](https://www.baeldung.com/java-aws-lambda)
|
||||
- [Using AWS Lambda with API Gateway](https://www.baeldung.com/aws-lambda-api-gateway)
|
||||
- [Introduction to AWS Serverless Application Model](https://www.baeldung.com/aws-serverless)
|
||||
- [How to Implement Hibernate in an AWS Lambda Function in Java](https://www.baeldung.com/java-aws-lambda-hibernate)
|
||||
- [Writing an Enterprise-Grade AWS Lambda in Java](https://www.baeldung.com/java-enterprise-aws-lambda)
|
||||
- [AWS Lambda Using DynamoDB With Java](https://www.baeldung.com/aws-lambda-dynamodb-java)
|
||||
105
aws-modules/aws-lambda/lambda/pom.xml
Normal file
105
aws-modules/aws-lambda/lambda/pom.xml
Normal file
@@ -0,0 +1,105 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<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>
|
||||
<artifactId>lambda</artifactId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
<name>lambda</name>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>aws-lambda</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.amazonaws</groupId>
|
||||
<artifactId>aws-java-sdk-dynamodb</artifactId>
|
||||
<version>${aws-java-sdk.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.amazonaws</groupId>
|
||||
<artifactId>aws-java-sdk-core</artifactId>
|
||||
<version>${aws-java-sdk.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.amazonaws</groupId>
|
||||
<artifactId>aws-lambda-java-core</artifactId>
|
||||
<version>${aws-lambda-java-core.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
<groupId>commons-logging</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.amazonaws</groupId>
|
||||
<artifactId>aws-lambda-java-events</artifactId>
|
||||
<version>${aws-lambda-java-events.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
<groupId>commons-logging</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>${gson.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>${commons-io.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.googlecode.json-simple</groupId>
|
||||
<artifactId>json-simple</artifactId>
|
||||
<version>${json-simple.version}</version>
|
||||
<exclusions>
|
||||
<!-- junit4 dependency is excluded as it should to be resolved from junit-vintage-engine
|
||||
included in parent-modules. -->
|
||||
<exclusion>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>${maven-shade-plugin.version}</version>
|
||||
<configuration>
|
||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<json-simple.version>1.1.1</json-simple.version>
|
||||
<aws-lambda-java-events.version>1.3.0</aws-lambda-java-events.version>
|
||||
<aws-lambda-java-core.version>1.2.0</aws-lambda-java-core.version>
|
||||
<gson.version>2.8.2</gson.version>
|
||||
<aws-java-sdk.version>1.11.241</aws-java-sdk.version>
|
||||
<maven-shade-plugin.version>3.0.0</maven-shade-plugin.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,60 @@
|
||||
AWSTemplateFormatVersion: '2010-09-09'
|
||||
Transform: 'AWS::Serverless-2016-10-31'
|
||||
Description: Baeldung Serverless Application Model Example with Implicit API Definition
|
||||
Globals:
|
||||
Api:
|
||||
EndpointConfiguration: REGIONAL
|
||||
Name: "TestAPI"
|
||||
Resources:
|
||||
PersonTable:
|
||||
Type: AWS::Serverless::SimpleTable
|
||||
Properties:
|
||||
PrimaryKey:
|
||||
Name: id
|
||||
Type: Number
|
||||
TableName: Person
|
||||
StorePersonFunction:
|
||||
Type: AWS::Serverless::Function
|
||||
Properties:
|
||||
Handler: com.baeldung.lambda.apigateway.APIDemoHandler::handleRequest
|
||||
Runtime: java8
|
||||
Timeout: 15
|
||||
MemorySize: 512
|
||||
CodeUri: ../target/aws-lambda-0.1.0-SNAPSHOT.jar
|
||||
Policies:
|
||||
- DynamoDBCrudPolicy:
|
||||
TableName: !Ref PersonTable
|
||||
Environment:
|
||||
Variables:
|
||||
TABLE_NAME: !Ref PersonTable
|
||||
Events:
|
||||
StoreApi:
|
||||
Type: Api
|
||||
Properties:
|
||||
Path: /persons
|
||||
Method: PUT
|
||||
GetPersonByHTTPParamFunction:
|
||||
Type: AWS::Serverless::Function
|
||||
Properties:
|
||||
Handler: com.baeldung.lambda.apigateway.APIDemoHandler::handleGetByParam
|
||||
Runtime: java8
|
||||
Timeout: 15
|
||||
MemorySize: 512
|
||||
CodeUri: ../target/aws-lambda-0.1.0-SNAPSHOT.jar
|
||||
Policies:
|
||||
- DynamoDBReadPolicy:
|
||||
TableName: !Ref PersonTable
|
||||
Environment:
|
||||
Variables:
|
||||
TABLE_NAME: !Ref PersonTable
|
||||
Events:
|
||||
GetByPathApi:
|
||||
Type: Api
|
||||
Properties:
|
||||
Path: /persons/{id}
|
||||
Method: GET
|
||||
GetByQueryApi:
|
||||
Type: Api
|
||||
Properties:
|
||||
Path: /persons
|
||||
Method: GET
|
||||
@@ -0,0 +1,112 @@
|
||||
AWSTemplateFormatVersion: '2010-09-09'
|
||||
Transform: 'AWS::Serverless-2016-10-31'
|
||||
Description: Baeldung Serverless Application Model Example with Inline Swagger API Definition
|
||||
Resources:
|
||||
PersonTable:
|
||||
Type: AWS::Serverless::SimpleTable
|
||||
Properties:
|
||||
PrimaryKey:
|
||||
Name: id
|
||||
Type: Number
|
||||
TableName: Person
|
||||
StorePersonFunction:
|
||||
Type: AWS::Serverless::Function
|
||||
Properties:
|
||||
Handler: com.baeldung.lambda.apigateway.APIDemoHandler::handleRequest
|
||||
Runtime: java8
|
||||
Timeout: 15
|
||||
MemorySize: 512
|
||||
CodeUri: ../target/aws-lambda-0.1.0-SNAPSHOT.jar
|
||||
Policies:
|
||||
- DynamoDBCrudPolicy:
|
||||
TableName: !Ref PersonTable
|
||||
Environment:
|
||||
Variables:
|
||||
TABLE_NAME: !Ref PersonTable
|
||||
Events:
|
||||
StoreApi:
|
||||
Type: Api
|
||||
Properties:
|
||||
Path: /persons
|
||||
Method: PUT
|
||||
RestApiId:
|
||||
Ref: MyApi
|
||||
GetPersonByHTTPParamFunction:
|
||||
Type: AWS::Serverless::Function
|
||||
Properties:
|
||||
Handler: com.baeldung.lambda.apigateway.APIDemoHandler::handleGetByParam
|
||||
Runtime: java8
|
||||
Timeout: 15
|
||||
MemorySize: 512
|
||||
CodeUri: ../target/aws-lambda-0.1.0-SNAPSHOT.jar
|
||||
Policies:
|
||||
- DynamoDBReadPolicy:
|
||||
TableName: !Ref PersonTable
|
||||
Environment:
|
||||
Variables:
|
||||
TABLE_NAME: !Ref PersonTable
|
||||
Events:
|
||||
GetByPathApi:
|
||||
Type: Api
|
||||
Properties:
|
||||
Path: /persons/{id}
|
||||
Method: GET
|
||||
RestApiId:
|
||||
Ref: MyApi
|
||||
GetByQueryApi:
|
||||
Type: Api
|
||||
Properties:
|
||||
Path: /persons
|
||||
Method: GET
|
||||
RestApiId:
|
||||
Ref: MyApi
|
||||
MyApi:
|
||||
Type: AWS::Serverless::Api
|
||||
Properties:
|
||||
StageName: test
|
||||
EndpointConfiguration: REGIONAL
|
||||
DefinitionBody:
|
||||
swagger: "2.0"
|
||||
info:
|
||||
title: "TestAPI"
|
||||
paths:
|
||||
/persons:
|
||||
get:
|
||||
parameters:
|
||||
- name: "id"
|
||||
in: "query"
|
||||
required: true
|
||||
type: "string"
|
||||
x-amazon-apigateway-request-validator: "Validate query string parameters and\
|
||||
\ headers"
|
||||
x-amazon-apigateway-integration:
|
||||
uri:
|
||||
Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${GetPersonByHTTPParamFunction.Arn}/invocations
|
||||
responses: {}
|
||||
httpMethod: "POST"
|
||||
type: "aws_proxy"
|
||||
put:
|
||||
x-amazon-apigateway-integration:
|
||||
uri:
|
||||
Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${StorePersonFunction.Arn}/invocations
|
||||
responses: {}
|
||||
httpMethod: "POST"
|
||||
type: "aws_proxy"
|
||||
/persons/{id}:
|
||||
get:
|
||||
parameters:
|
||||
- name: "id"
|
||||
in: "path"
|
||||
required: true
|
||||
type: "string"
|
||||
responses: {}
|
||||
x-amazon-apigateway-integration:
|
||||
uri:
|
||||
Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${GetPersonByHTTPParamFunction.Arn}/invocations
|
||||
responses: {}
|
||||
httpMethod: "POST"
|
||||
type: "aws_proxy"
|
||||
x-amazon-apigateway-request-validators:
|
||||
Validate query string parameters and headers:
|
||||
validateRequestParameters: true
|
||||
validateRequestBody: false
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.baeldung.lambda;
|
||||
|
||||
import com.amazonaws.services.lambda.runtime.Context;
|
||||
|
||||
public class LambdaMethodHandler {
|
||||
public String handleRequest(String input, Context context) {
|
||||
context.getLogger().log("Input: " + input);
|
||||
return "Hello World - " + input;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.baeldung.lambda;
|
||||
|
||||
import com.amazonaws.services.lambda.runtime.Context;
|
||||
import com.amazonaws.services.lambda.runtime.RequestHandler;
|
||||
|
||||
public class LambdaRequestHandler implements RequestHandler<String, String> {
|
||||
public String handleRequest(String input, Context context) {
|
||||
context.getLogger().log("Input: " + input);
|
||||
return "Hello World - " + input;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.baeldung.lambda;
|
||||
|
||||
import com.amazonaws.services.lambda.runtime.Context;
|
||||
import com.amazonaws.services.lambda.runtime.RequestStreamHandler;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
public class LambdaRequestStreamHandler implements RequestStreamHandler {
|
||||
|
||||
public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) throws IOException {
|
||||
String input = IOUtils.toString(inputStream, "UTF-8");
|
||||
outputStream.write(("Hello World - " + input).getBytes());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
package com.baeldung.lambda.apigateway;
|
||||
|
||||
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
|
||||
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
|
||||
import com.amazonaws.services.dynamodbv2.document.*;
|
||||
import com.amazonaws.services.dynamodbv2.document.spec.PutItemSpec;
|
||||
import com.amazonaws.services.lambda.runtime.Context;
|
||||
import com.amazonaws.services.lambda.runtime.RequestStreamHandler;
|
||||
import com.baeldung.lambda.apigateway.model.Person;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.parser.JSONParser;
|
||||
import org.json.simple.parser.ParseException;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
public class APIDemoHandler implements RequestStreamHandler {
|
||||
|
||||
private JSONParser parser = new JSONParser();
|
||||
private static final String DYNAMODB_TABLE_NAME = System.getenv("TABLE_NAME");
|
||||
|
||||
@Override
|
||||
public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) throws IOException {
|
||||
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
|
||||
JSONObject responseJson = new JSONObject();
|
||||
|
||||
AmazonDynamoDB client = AmazonDynamoDBClientBuilder.defaultClient();
|
||||
DynamoDB dynamoDb = new DynamoDB(client);
|
||||
|
||||
try {
|
||||
JSONObject event = (JSONObject) parser.parse(reader);
|
||||
|
||||
if (event.get("body") != null) {
|
||||
|
||||
Person person = new Person((String) event.get("body"));
|
||||
|
||||
dynamoDb.getTable(DYNAMODB_TABLE_NAME)
|
||||
.putItem(new PutItemSpec().withItem(new Item().withNumber("id", person.getId())
|
||||
.withString("name", person.getName())));
|
||||
}
|
||||
|
||||
JSONObject responseBody = new JSONObject();
|
||||
responseBody.put("message", "New item created");
|
||||
|
||||
JSONObject headerJson = new JSONObject();
|
||||
headerJson.put("x-custom-header", "my custom header value");
|
||||
|
||||
responseJson.put("statusCode", 200);
|
||||
responseJson.put("headers", headerJson);
|
||||
responseJson.put("body", responseBody.toString());
|
||||
|
||||
} catch (ParseException pex) {
|
||||
responseJson.put("statusCode", 400);
|
||||
responseJson.put("exception", pex);
|
||||
}
|
||||
|
||||
OutputStreamWriter writer = new OutputStreamWriter(outputStream, "UTF-8");
|
||||
writer.write(responseJson.toString());
|
||||
writer.close();
|
||||
}
|
||||
|
||||
public void handleGetByParam(InputStream inputStream, OutputStream outputStream, Context context) throws IOException {
|
||||
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
|
||||
JSONObject responseJson = new JSONObject();
|
||||
|
||||
AmazonDynamoDB client = AmazonDynamoDBClientBuilder.defaultClient();
|
||||
DynamoDB dynamoDb = new DynamoDB(client);
|
||||
|
||||
Item result = null;
|
||||
try {
|
||||
JSONObject event = (JSONObject) parser.parse(reader);
|
||||
JSONObject responseBody = new JSONObject();
|
||||
|
||||
if (event.get("pathParameters") != null) {
|
||||
|
||||
JSONObject pps = (JSONObject) event.get("pathParameters");
|
||||
if (pps.get("id") != null) {
|
||||
|
||||
int id = Integer.parseInt((String) pps.get("id"));
|
||||
result = dynamoDb.getTable(DYNAMODB_TABLE_NAME)
|
||||
.getItem("id", id);
|
||||
}
|
||||
|
||||
} else if (event.get("queryStringParameters") != null) {
|
||||
|
||||
JSONObject qps = (JSONObject) event.get("queryStringParameters");
|
||||
if (qps.get("id") != null) {
|
||||
|
||||
int id = Integer.parseInt((String) qps.get("id"));
|
||||
result = dynamoDb.getTable(DYNAMODB_TABLE_NAME)
|
||||
.getItem("id", id);
|
||||
}
|
||||
}
|
||||
if (result != null) {
|
||||
|
||||
Person person = new Person(result.toJSON());
|
||||
responseBody.put("Person", person);
|
||||
responseJson.put("statusCode", 200);
|
||||
} else {
|
||||
|
||||
responseBody.put("message", "No item found");
|
||||
responseJson.put("statusCode", 404);
|
||||
}
|
||||
|
||||
JSONObject headerJson = new JSONObject();
|
||||
headerJson.put("x-custom-header", "my custom header value");
|
||||
|
||||
responseJson.put("headers", headerJson);
|
||||
responseJson.put("body", responseBody.toString());
|
||||
|
||||
} catch (ParseException pex) {
|
||||
responseJson.put("statusCode", 400);
|
||||
responseJson.put("exception", pex);
|
||||
}
|
||||
|
||||
OutputStreamWriter writer = new OutputStreamWriter(outputStream, "UTF-8");
|
||||
writer.write(responseJson.toString());
|
||||
writer.close();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.baeldung.lambda.apigateway.model;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
|
||||
public class Person {
|
||||
|
||||
private int id;
|
||||
private String name;
|
||||
|
||||
public Person(String json) {
|
||||
Gson gson = new Gson();
|
||||
Person request = gson.fromJson(json, Person.class);
|
||||
this.id = request.getId();
|
||||
this.name = request.getName();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
final Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||
return gson.toJson(this);
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.baeldung.lambda.dynamodb;
|
||||
|
||||
import com.amazonaws.regions.Region;
|
||||
import com.amazonaws.regions.Regions;
|
||||
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient;
|
||||
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
|
||||
import com.amazonaws.services.dynamodbv2.document.Item;
|
||||
import com.amazonaws.services.dynamodbv2.document.PutItemOutcome;
|
||||
import com.amazonaws.services.dynamodbv2.document.spec.PutItemSpec;
|
||||
import com.amazonaws.services.dynamodbv2.model.ConditionalCheckFailedException;
|
||||
import com.amazonaws.services.lambda.runtime.Context;
|
||||
import com.amazonaws.services.lambda.runtime.RequestHandler;
|
||||
import com.baeldung.lambda.dynamodb.bean.PersonRequest;
|
||||
import com.baeldung.lambda.dynamodb.bean.PersonResponse;
|
||||
|
||||
public class SavePersonHandler implements RequestHandler<PersonRequest, PersonResponse> {
|
||||
|
||||
private DynamoDB dynamoDb;
|
||||
|
||||
private String DYNAMODB_TABLE_NAME = "Person";
|
||||
private Regions REGION = Regions.US_WEST_2;
|
||||
|
||||
public PersonResponse handleRequest(PersonRequest personRequest, Context context) {
|
||||
this.initDynamoDbClient();
|
||||
|
||||
persistData(personRequest);
|
||||
|
||||
PersonResponse personResponse = new PersonResponse();
|
||||
personResponse.setMessage("Saved Successfully!!!");
|
||||
return personResponse;
|
||||
}
|
||||
|
||||
private PutItemOutcome persistData(PersonRequest personRequest) throws ConditionalCheckFailedException {
|
||||
return this.dynamoDb.getTable(DYNAMODB_TABLE_NAME)
|
||||
.putItem(
|
||||
new PutItemSpec().withItem(new Item()
|
||||
.withNumber("id", personRequest.getId())
|
||||
.withString("firstName", personRequest.getFirstName())
|
||||
.withString("lastName", personRequest.getLastName())
|
||||
.withNumber("age", personRequest.getAge())
|
||||
.withString("address", personRequest.getAddress())));
|
||||
}
|
||||
|
||||
private void initDynamoDbClient() {
|
||||
AmazonDynamoDBClient client = new AmazonDynamoDBClient();
|
||||
client.setRegion(Region.getRegion(REGION));
|
||||
this.dynamoDb = new DynamoDB(client);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package com.baeldung.lambda.dynamodb.bean;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
|
||||
public class PersonRequest {
|
||||
private int id;
|
||||
private String firstName;
|
||||
private String lastName;
|
||||
private int age;
|
||||
private String address;
|
||||
|
||||
public static void main(String[] args) {
|
||||
PersonRequest personRequest = new PersonRequest();
|
||||
personRequest.setId(1);
|
||||
personRequest.setFirstName("John");
|
||||
personRequest.setLastName("Doe");
|
||||
personRequest.setAge(30);
|
||||
personRequest.setAddress("United States");
|
||||
System.out.println(personRequest);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
final Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||
return gson.toJson(this);
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getFirstName() {
|
||||
return firstName;
|
||||
}
|
||||
|
||||
public void setFirstName(String firstName) {
|
||||
this.firstName = firstName;
|
||||
}
|
||||
|
||||
public String getLastName() {
|
||||
return lastName;
|
||||
}
|
||||
|
||||
public void setLastName(String lastName) {
|
||||
this.lastName = lastName;
|
||||
}
|
||||
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public void setAge(int age) {
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
public String getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
public void setAddress(String address) {
|
||||
this.address = address;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.baeldung.lambda.dynamodb.bean;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
|
||||
public class PersonResponse {
|
||||
private String message;
|
||||
|
||||
public String toString() {
|
||||
final Gson gson = new Gson();
|
||||
return gson.toJson(this);
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
}
|
||||
13
aws-modules/aws-lambda/lambda/src/main/resources/logback.xml
Normal file
13
aws-modules/aws-lambda/lambda/src/main/resources/logback.xml
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
|
||||
</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root level="INFO">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
</configuration>
|
||||
22
aws-modules/aws-lambda/pom.xml
Normal file
22
aws-modules/aws-lambda/pom.xml
Normal file
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<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>
|
||||
<artifactId>aws-lambda</artifactId>
|
||||
<name>aws-lambda</name>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>aws-modules</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
<module>lambda</module>
|
||||
<module>shipping-tracker/ShippingFunction</module>
|
||||
<module>todo-reminder/ToDoFunction</module>
|
||||
</modules>
|
||||
|
||||
</project>
|
||||
1
aws-modules/aws-lambda/shipping-tracker/.gitignore
vendored
Normal file
1
aws-modules/aws-lambda/shipping-tracker/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
.aws-sam/
|
||||
@@ -0,0 +1,74 @@
|
||||
<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/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>ShippingFunction</artifactId>
|
||||
<version>1.0</version>
|
||||
<name>ShippingFunction</name>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.amazonaws</groupId>
|
||||
<artifactId>aws-lambda-java-core</artifactId>
|
||||
<version>${aws-lambda-java-core.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.amazonaws</groupId>
|
||||
<artifactId>aws-lambda-java-events</artifactId>
|
||||
<version>${aws-lambda-java-events.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>${jackson-databind.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-core</artifactId>
|
||||
<version>${hibernate.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-hikaricp</artifactId>
|
||||
<version>${hibernate.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
<version>${postgresql.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.1.1</version>
|
||||
<configuration>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
<hibernate.version>5.4.21.Final</hibernate.version>
|
||||
<aws-lambda-java-core.version>1.2.0</aws-lambda-java-core.version>
|
||||
<aws-lambda-java-events.version>3.1.0</aws-lambda-java-events.version>
|
||||
<jackson-databind.version>2.11.2</jackson-databind.version>
|
||||
<postgresql.version>42.2.16</postgresql.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,121 @@
|
||||
package com.baeldung.lambda.shipping;
|
||||
|
||||
import com.amazonaws.services.lambda.runtime.Context;
|
||||
import com.amazonaws.services.lambda.runtime.RequestHandler;
|
||||
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
|
||||
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.zaxxer.hikari.HikariDataSource;
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.boot.MetadataSources;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistry;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.hibernate.cfg.AvailableSettings.*;
|
||||
import static org.hibernate.cfg.AvailableSettings.PASS;
|
||||
|
||||
/**
|
||||
* Handler for requests to Lambda function.
|
||||
*/
|
||||
public class App implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
|
||||
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
|
||||
private SessionFactory sessionFactory = createSessionFactory();
|
||||
|
||||
public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent input, Context context) {
|
||||
try {
|
||||
ShippingService service = new ShippingService(sessionFactory, new ShippingDao());
|
||||
return routeRequest(input, service);
|
||||
} finally {
|
||||
flushConnectionPool();
|
||||
}
|
||||
}
|
||||
|
||||
private APIGatewayProxyResponseEvent routeRequest(APIGatewayProxyRequestEvent input, ShippingService service) {
|
||||
Map<String, String> headers = new HashMap<>();
|
||||
headers.put("Content-Type", "application/json");
|
||||
headers.put("X-Custom-Header", "application/json");
|
||||
|
||||
Object result = "OK";
|
||||
|
||||
switch (input.getResource()) {
|
||||
case "/consignment":
|
||||
result = service.createConsignment(
|
||||
fromJson(input.getBody(), Consignment.class));
|
||||
break;
|
||||
case "/consignment/{id}":
|
||||
result = service.view(input.getPathParameters().get("id"));
|
||||
break;
|
||||
case "/consignment/{id}/item":
|
||||
service.addItem(input.getPathParameters().get("id"),
|
||||
fromJson(input.getBody(), Item.class));
|
||||
break;
|
||||
case "/consignment/{id}/checkin":
|
||||
service.checkIn(input.getPathParameters().get("id"),
|
||||
fromJson(input.getBody(), Checkin.class));
|
||||
break;
|
||||
}
|
||||
|
||||
return new APIGatewayProxyResponseEvent()
|
||||
.withHeaders(headers)
|
||||
.withStatusCode(200)
|
||||
.withBody(toJson(result));
|
||||
}
|
||||
|
||||
private static <T> String toJson(T object) {
|
||||
try {
|
||||
return OBJECT_MAPPER.writeValueAsString(object);
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static <T> T fromJson(String json, Class<T> type) {
|
||||
try {
|
||||
return OBJECT_MAPPER.readValue(json, type);
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static SessionFactory createSessionFactory() {
|
||||
Map<String, String> settings = new HashMap<>();
|
||||
settings.put(URL, System.getenv("DB_URL"));
|
||||
settings.put(DIALECT, "org.hibernate.dialect.PostgreSQLDialect");
|
||||
settings.put(DEFAULT_SCHEMA, "shipping");
|
||||
settings.put(DRIVER, "org.postgresql.Driver");
|
||||
settings.put(USER, System.getenv("DB_USER"));
|
||||
settings.put(PASS, System.getenv("DB_PASSWORD"));
|
||||
settings.put("hibernate.hikari.connectionTimeout", "20000");
|
||||
settings.put("hibernate.hikari.minimumIdle", "1");
|
||||
settings.put("hibernate.hikari.maximumPoolSize", "2");
|
||||
settings.put("hibernate.hikari.idleTimeout", "30000");
|
||||
|
||||
// commented out as we only need them on first use
|
||||
// settings.put(HBM2DDL_AUTO, "create-only");
|
||||
// settings.put(HBM2DDL_DATABASE_ACTION, "create");
|
||||
|
||||
StandardServiceRegistry registry = new StandardServiceRegistryBuilder()
|
||||
.applySettings(settings)
|
||||
.build();
|
||||
|
||||
return new MetadataSources(registry)
|
||||
.addAnnotatedClass(Consignment.class)
|
||||
.addAnnotatedClass(Item.class)
|
||||
.addAnnotatedClass(Checkin.class)
|
||||
.buildMetadata()
|
||||
.buildSessionFactory();
|
||||
}
|
||||
|
||||
private void flushConnectionPool() {
|
||||
ConnectionProvider connectionProvider = sessionFactory.getSessionFactoryOptions()
|
||||
.getServiceRegistry()
|
||||
.getService(ConnectionProvider.class);
|
||||
HikariDataSource hikariDataSource = connectionProvider.unwrap(HikariDataSource.class);
|
||||
hikariDataSource.getHikariPoolMXBean().softEvictConnections();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.baeldung.lambda.shipping;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Embeddable;
|
||||
|
||||
@Embeddable
|
||||
public class Checkin {
|
||||
private String timeStamp;
|
||||
private String location;
|
||||
|
||||
@Column(name = "timestamp")
|
||||
public String getTimeStamp() {
|
||||
return timeStamp;
|
||||
}
|
||||
|
||||
public void setTimeStamp(String timeStamp) {
|
||||
this.timeStamp = timeStamp;
|
||||
}
|
||||
|
||||
@Column(name = "location")
|
||||
public String getLocation() {
|
||||
return location;
|
||||
}
|
||||
|
||||
public void setLocation(String location) {
|
||||
this.location = location;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package com.baeldung.lambda.shipping;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static javax.persistence.FetchType.EAGER;
|
||||
|
||||
@Entity(name = "consignment")
|
||||
@Table(name = "consignment")
|
||||
public class Consignment {
|
||||
private String id;
|
||||
private String source;
|
||||
private String destination;
|
||||
private boolean isDelivered;
|
||||
private List<Item> items = new ArrayList<>();
|
||||
private List<Checkin> checkins = new ArrayList<>();
|
||||
|
||||
@Id
|
||||
@Column(name = "consignment_id")
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Column(name = "source")
|
||||
public String getSource() {
|
||||
return source;
|
||||
}
|
||||
|
||||
public void setSource(String source) {
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
@Column(name = "destination")
|
||||
public String getDestination() {
|
||||
return destination;
|
||||
}
|
||||
|
||||
public void setDestination(String destination) {
|
||||
this.destination = destination;
|
||||
}
|
||||
|
||||
@Column(name = "delivered", columnDefinition = "boolean")
|
||||
public boolean isDelivered() {
|
||||
return isDelivered;
|
||||
}
|
||||
|
||||
public void setDelivered(boolean delivered) {
|
||||
isDelivered = delivered;
|
||||
}
|
||||
|
||||
@ElementCollection(fetch = EAGER)
|
||||
@CollectionTable(name = "consignment_item", joinColumns = @JoinColumn(name = "consignment_id"))
|
||||
@OrderColumn(name = "item_index")
|
||||
public List<Item> getItems() {
|
||||
return items;
|
||||
}
|
||||
|
||||
public void setItems(List<Item> items) {
|
||||
this.items = items;
|
||||
}
|
||||
|
||||
@ElementCollection(fetch = EAGER)
|
||||
@CollectionTable(name = "consignment_checkin", joinColumns = @JoinColumn(name = "consignment_id"))
|
||||
@OrderColumn(name = "checkin_index")
|
||||
public List<Checkin> getCheckins() {
|
||||
return checkins;
|
||||
}
|
||||
|
||||
public void setCheckins(List<Checkin> checkins) {
|
||||
this.checkins = checkins;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.baeldung.lambda.shipping;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Embeddable;
|
||||
|
||||
@Embeddable
|
||||
public class Item {
|
||||
private String location;
|
||||
private String description;
|
||||
private String timeStamp;
|
||||
|
||||
@Column(name = "location")
|
||||
public String getLocation() {
|
||||
return location;
|
||||
}
|
||||
|
||||
public void setLocation(String location) {
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
@Column(name = "description")
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
@Column(name = "timestamp")
|
||||
public String getTimeStamp() {
|
||||
return timeStamp;
|
||||
}
|
||||
|
||||
public void setTimeStamp(String timeStamp) {
|
||||
this.timeStamp = timeStamp;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.baeldung.lambda.shipping;
|
||||
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.Transaction;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class ShippingDao {
|
||||
/**
|
||||
* Save a consignment to the database
|
||||
* @param consignment the consignment to save
|
||||
*/
|
||||
public void save(Session session, Consignment consignment) {
|
||||
Transaction transaction = session.beginTransaction();
|
||||
session.save(consignment);
|
||||
transaction.commit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a consignment in the database by id
|
||||
*/
|
||||
public Optional<Consignment> find(Session session, String id) {
|
||||
return Optional.ofNullable(session.get(Consignment.class, id));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package com.baeldung.lambda.shipping;
|
||||
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.SessionFactory;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.UUID;
|
||||
|
||||
public class ShippingService {
|
||||
private SessionFactory sessionFactory;
|
||||
private ShippingDao shippingDao;
|
||||
|
||||
public ShippingService(SessionFactory sessionFactory, ShippingDao shippingDao) {
|
||||
this.sessionFactory = sessionFactory;
|
||||
this.shippingDao = shippingDao;
|
||||
}
|
||||
|
||||
public String createConsignment(Consignment consignment) {
|
||||
try (Session session = sessionFactory.openSession()) {
|
||||
consignment.setDelivered(false);
|
||||
consignment.setId(UUID.randomUUID().toString());
|
||||
shippingDao.save(session, consignment);
|
||||
return consignment.getId();
|
||||
}
|
||||
}
|
||||
|
||||
public void addItem(String consignmentId, Item item) {
|
||||
try (Session session = sessionFactory.openSession()) {
|
||||
shippingDao.find(session, consignmentId)
|
||||
.ifPresent(consignment -> addItem(session, consignment, item));
|
||||
}
|
||||
}
|
||||
|
||||
private void addItem(Session session, Consignment consignment, Item item) {
|
||||
consignment.getItems()
|
||||
.add(item);
|
||||
shippingDao.save(session, consignment);
|
||||
}
|
||||
|
||||
public void checkIn(String consignmentId, Checkin checkin) {
|
||||
try (Session session = sessionFactory.openSession()) {
|
||||
shippingDao.find(session, consignmentId)
|
||||
.ifPresent(consignment -> checkIn(session, consignment, checkin));
|
||||
}
|
||||
}
|
||||
|
||||
private void checkIn(Session session, Consignment consignment, Checkin checkin) {
|
||||
consignment.getCheckins().add(checkin);
|
||||
consignment.getCheckins().sort(Comparator.comparing(Checkin::getTimeStamp));
|
||||
if (checkin.getLocation().equals(consignment.getDestination())) {
|
||||
consignment.setDelivered(true);
|
||||
}
|
||||
shippingDao.save(session, consignment);
|
||||
}
|
||||
|
||||
public Consignment view(String consignmentId) {
|
||||
try (Session session = sessionFactory.openSession()) {
|
||||
return shippingDao.find(session, consignmentId)
|
||||
.orElseGet(Consignment::new);
|
||||
}
|
||||
}
|
||||
}
|
||||
47
aws-modules/aws-lambda/shipping-tracker/template.yaml
Normal file
47
aws-modules/aws-lambda/shipping-tracker/template.yaml
Normal file
@@ -0,0 +1,47 @@
|
||||
AWSTemplateFormatVersion: '2010-09-09'
|
||||
Transform: AWS::Serverless-2016-10-31
|
||||
Description: >
|
||||
shipping-tracker
|
||||
|
||||
Sample SAM Template for shipping-tracker
|
||||
|
||||
# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
|
||||
Globals:
|
||||
Function:
|
||||
Timeout: 20
|
||||
|
||||
Resources:
|
||||
ShippingFunction:
|
||||
Type: AWS::Serverless::Function
|
||||
Properties:
|
||||
CodeUri: ShippingFunction
|
||||
Handler: com.baeldung.lambda.shipping.App::handleRequest
|
||||
Runtime: java8
|
||||
MemorySize: 512
|
||||
Environment:
|
||||
Variables:
|
||||
DB_URL: jdbc:postgresql://postgres/postgres
|
||||
DB_USER: postgres
|
||||
DB_PASSWORD: password
|
||||
Events:
|
||||
CreateConsignment:
|
||||
Type: Api
|
||||
Properties:
|
||||
Path: /consignment
|
||||
Method: post
|
||||
AddItem:
|
||||
Type: Api
|
||||
Properties:
|
||||
Path: /consignment/{id}/item
|
||||
Method: post
|
||||
CheckIn:
|
||||
Type: Api
|
||||
Properties:
|
||||
Path: /consignment/{id}/checkin
|
||||
Method: post
|
||||
ViewConsignment:
|
||||
Type: Api
|
||||
Properties:
|
||||
Path: /consignment/{id}
|
||||
Method: get
|
||||
|
||||
119
aws-modules/aws-lambda/todo-reminder/ToDoFunction/pom.xml
Normal file
119
aws-modules/aws-lambda/todo-reminder/ToDoFunction/pom.xml
Normal file
@@ -0,0 +1,119 @@
|
||||
<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/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>helloworld</groupId>
|
||||
<artifactId>ToDoFunction</artifactId>
|
||||
<version>1.0</version>
|
||||
<name>ToDoFunction</name>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.amazonaws</groupId>
|
||||
<artifactId>aws-lambda-java-core</artifactId>
|
||||
<version>${aws-lambda-java-core.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.amazonaws</groupId>
|
||||
<artifactId>aws-lambda-java-events</artifactId>
|
||||
<version>${aws-lambda-java-events.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>uk.org.webcompere</groupId>
|
||||
<artifactId>lightweight-config</artifactId>
|
||||
<version>${lightweight-config.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.amazonaws</groupId>
|
||||
<artifactId>aws-lambda-java-log4j2</artifactId>
|
||||
<version>${aws-lambda-java-log4j2.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j-slf4j-impl</artifactId>
|
||||
<version>${log4j-slf4j-impl.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.github.openfeign</groupId>
|
||||
<artifactId>feign-core</artifactId>
|
||||
<version>${feign-core.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.github.openfeign</groupId>
|
||||
<artifactId>feign-slf4j</artifactId>
|
||||
<version>${feign-core.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.github.openfeign</groupId>
|
||||
<artifactId>feign-gson</artifactId>
|
||||
<version>${feign-core.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.inject</groupId>
|
||||
<artifactId>guice</artifactId>
|
||||
<version>${guice.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.vintage</groupId>
|
||||
<artifactId>junit-vintage-engine</artifactId>
|
||||
<version>${junit-jupiter.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>uk.org.webcompere</groupId>
|
||||
<artifactId>system-stubs-junit4</artifactId>
|
||||
<version>${system-stubs-junit4.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<version>${mockito-core.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
<artifactId>assertj-core</artifactId>
|
||||
<version>${assertj-core.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.2.4</version>
|
||||
<configuration>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
<aws-lambda-java-core.version>1.2.1</aws-lambda-java-core.version>
|
||||
<aws-lambda-java-events.version>3.6.0</aws-lambda-java-events.version>
|
||||
<lightweight-config.version>1.1.0</lightweight-config.version>
|
||||
<aws-lambda-java-log4j2.version>1.2.0</aws-lambda-java-log4j2.version>
|
||||
<log4j-slf4j-impl.version>2.13.2</log4j-slf4j-impl.version>
|
||||
<feign-core.version>11.2</feign-core.version>
|
||||
<guice.version>5.0.1</guice.version>
|
||||
<system-stubs-junit4.version>1.2.0</system-stubs-junit4.version>
|
||||
<mockito-core.version>4.1.0</mockito-core.version>
|
||||
<assertj-core.version>3.19.0</assertj-core.version>
|
||||
<junit-jupiter.version>5.8.1</junit-jupiter.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.baeldung.lambda.todo;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.URL;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.amazonaws.services.lambda.runtime.Context;
|
||||
import com.amazonaws.services.lambda.runtime.RequestHandler;
|
||||
import com.amazonaws.services.lambda.runtime.RequestStreamHandler;
|
||||
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
|
||||
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
|
||||
import com.baeldung.lambda.todo.config.ExecutionContext;
|
||||
import com.baeldung.lambda.todo.service.PostService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Handler for requests to Lambda function.
|
||||
*/
|
||||
public class App implements RequestStreamHandler {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(App.class);
|
||||
|
||||
private String environmentName = System.getenv("ENV_NAME");
|
||||
private ExecutionContext executionContext = new ExecutionContext();
|
||||
|
||||
@Override
|
||||
public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) throws IOException {
|
||||
context.getLogger().log("App starting\n");
|
||||
context.getLogger().log("Environment: "
|
||||
+ environmentName + "\n");
|
||||
|
||||
try {
|
||||
PostService postService = executionContext.getPostService();
|
||||
executionContext.getToDoReaderService()
|
||||
.getOldestToDo()
|
||||
.ifPresent(postService::makePost);
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("Failed: {}", e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.baeldung.lambda.todo.api;
|
||||
|
||||
import feign.RequestLine;
|
||||
|
||||
public interface PostApi {
|
||||
@RequestLine("POST /posts")
|
||||
void makePost(PostItem item);
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.baeldung.lambda.todo.api;
|
||||
|
||||
public class PostItem {
|
||||
private String title;
|
||||
private String body;
|
||||
private int userId;
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getBody() {
|
||||
return body;
|
||||
}
|
||||
|
||||
public void setBody(String body) {
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
public int getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public void setUserId(int userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PostItem{"
|
||||
+ "title='" + title + '\''
|
||||
+ ", body='" + body + '\''
|
||||
+ ", userId=" + userId +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.baeldung.lambda.todo.api;
|
||||
|
||||
import feign.RequestLine;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ToDoApi {
|
||||
@RequestLine("GET /todos")
|
||||
List<ToDoItem> getAllTodos();
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.baeldung.lambda.todo.api;
|
||||
|
||||
public class ToDoItem {
|
||||
private int userId;
|
||||
private int id;
|
||||
private String title;
|
||||
private boolean completed;
|
||||
|
||||
public int getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public void setUserId(int userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public boolean isCompleted() {
|
||||
return completed;
|
||||
}
|
||||
|
||||
public void setCompleted(boolean completed) {
|
||||
this.completed = completed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ToDoItem{"
|
||||
+ "userId=" + userId
|
||||
+ ", id=" + id
|
||||
+ ", title='" + title + '\''
|
||||
+ ", completed=" + completed +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.baeldung.lambda.todo.config;
|
||||
|
||||
public class Config {
|
||||
private String toDoEndpoint;
|
||||
private String postEndpoint;
|
||||
private String environmentName;
|
||||
|
||||
private Credentials toDoCredentials;
|
||||
private Credentials postCredentials;
|
||||
|
||||
public String getToDoEndpoint() {
|
||||
return toDoEndpoint;
|
||||
}
|
||||
|
||||
public void setToDoEndpoint(String toDoEndpoint) {
|
||||
this.toDoEndpoint = toDoEndpoint;
|
||||
}
|
||||
|
||||
public String getPostEndpoint() {
|
||||
return postEndpoint;
|
||||
}
|
||||
|
||||
public void setPostEndpoint(String postEndpoint) {
|
||||
this.postEndpoint = postEndpoint;
|
||||
}
|
||||
|
||||
public String getEnvironmentName() {
|
||||
return environmentName;
|
||||
}
|
||||
|
||||
public void setEnvironmentName(String environmentName) {
|
||||
this.environmentName = environmentName;
|
||||
}
|
||||
|
||||
public Credentials getToDoCredentials() {
|
||||
return toDoCredentials;
|
||||
}
|
||||
|
||||
public void setToDoCredentials(Credentials toDoCredentials) {
|
||||
this.toDoCredentials = toDoCredentials;
|
||||
}
|
||||
|
||||
public Credentials getPostCredentials() {
|
||||
return postCredentials;
|
||||
}
|
||||
|
||||
public void setPostCredentials(Credentials postCredentials) {
|
||||
this.postCredentials = postCredentials;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.baeldung.lambda.todo.config;
|
||||
|
||||
public class Credentials {
|
||||
private String username;
|
||||
private String password;
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.baeldung.lambda.todo.config;
|
||||
|
||||
import com.baeldung.lambda.todo.service.PostService;
|
||||
import com.baeldung.lambda.todo.service.ToDoReaderService;
|
||||
import com.google.inject.Guice;
|
||||
import com.google.inject.Injector;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class ExecutionContext {
|
||||
private static final Logger LOGGER =
|
||||
LoggerFactory.getLogger(ExecutionContext.class);
|
||||
|
||||
private ToDoReaderService toDoReaderService;
|
||||
private PostService postService;
|
||||
|
||||
public ExecutionContext() {
|
||||
LOGGER.info("Loading configuration");
|
||||
|
||||
try {
|
||||
Injector injector = Guice.createInjector(new Services());
|
||||
this.toDoReaderService = injector.getInstance(ToDoReaderService.class);
|
||||
this.postService = injector.getInstance(PostService.class);
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("Could not start", e);
|
||||
}
|
||||
}
|
||||
|
||||
public ToDoReaderService getToDoReaderService() {
|
||||
return toDoReaderService;
|
||||
}
|
||||
|
||||
public PostService getPostService() {
|
||||
return postService;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.baeldung.lambda.todo.config;
|
||||
|
||||
import com.baeldung.lambda.todo.api.PostApi;
|
||||
import com.baeldung.lambda.todo.api.ToDoApi;
|
||||
import com.google.inject.AbstractModule;
|
||||
import feign.Feign;
|
||||
import feign.auth.BasicAuthRequestInterceptor;
|
||||
import feign.gson.GsonDecoder;
|
||||
import feign.gson.GsonEncoder;
|
||||
import feign.slf4j.Slf4jLogger;
|
||||
import uk.org.webcompere.lightweightconfig.ConfigLoader;
|
||||
|
||||
import static feign.Logger.Level.FULL;
|
||||
|
||||
public class Services extends AbstractModule {
|
||||
@Override
|
||||
protected void configure() {
|
||||
Config config = ConfigLoader.loadYmlConfigFromResource("configuration.yml", Config.class);
|
||||
|
||||
ToDoApi toDoApi = Feign.builder()
|
||||
.decoder(new GsonDecoder())
|
||||
.logger(new Slf4jLogger())
|
||||
.logLevel(FULL)
|
||||
.requestInterceptor(new BasicAuthRequestInterceptor(config.getToDoCredentials().getUsername(), config.getToDoCredentials().getPassword()))
|
||||
.target(ToDoApi.class, config.getToDoEndpoint());
|
||||
|
||||
PostApi postApi = Feign.builder()
|
||||
.encoder(new GsonEncoder())
|
||||
.logger(new Slf4jLogger())
|
||||
.logLevel(FULL)
|
||||
.requestInterceptor(new BasicAuthRequestInterceptor(config.getPostCredentials().getUsername(), config.getPostCredentials().getPassword()))
|
||||
.target(PostApi.class, config.getPostEndpoint());
|
||||
|
||||
bind(Config.class).toInstance(config);
|
||||
bind(ToDoApi.class).toInstance(toDoApi);
|
||||
bind(PostApi.class).toInstance(postApi);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.baeldung.lambda.todo.service;
|
||||
|
||||
import com.baeldung.lambda.todo.api.PostApi;
|
||||
import com.baeldung.lambda.todo.api.PostItem;
|
||||
import com.baeldung.lambda.todo.api.ToDoItem;
|
||||
import com.google.inject.Inject;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
|
||||
public class PostService {
|
||||
private static final Logger LOGGER = LogManager.getLogger(PostService.class);
|
||||
private PostApi postApi;
|
||||
|
||||
@Inject
|
||||
public PostService(PostApi postApi) {
|
||||
this.postApi = postApi;
|
||||
}
|
||||
|
||||
public void makePost(ToDoItem toDoItem) {
|
||||
LOGGER.info("Posting about: {}", toDoItem);
|
||||
PostItem item = new PostItem();
|
||||
item.setTitle("To Do is Out Of Date: " + toDoItem.getId());
|
||||
item.setUserId(toDoItem.getUserId());
|
||||
item.setBody("Not done: " + toDoItem.getTitle());
|
||||
|
||||
LOGGER.info("Post: {}", item);
|
||||
postApi.makePost(item);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.baeldung.lambda.todo.service;
|
||||
|
||||
import com.baeldung.lambda.todo.api.ToDoApi;
|
||||
import com.baeldung.lambda.todo.api.ToDoItem;
|
||||
import com.baeldung.lambda.todo.config.Config;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.Optional;
|
||||
|
||||
public class ToDoReaderService {
|
||||
// Log4j logger
|
||||
private static final Logger LOGGER = LogManager.getLogger(ToDoReaderService.class);
|
||||
|
||||
private ToDoApi toDoApi;
|
||||
|
||||
@Inject
|
||||
public ToDoReaderService(Config configuration, ToDoApi toDoApi) {
|
||||
LOGGER.info("ToDo Endpoint on: {}", configuration.getToDoEndpoint());
|
||||
|
||||
this.toDoApi = toDoApi;
|
||||
}
|
||||
|
||||
public Optional<ToDoItem> getOldestToDo() {
|
||||
return toDoApi.getAllTodos().stream()
|
||||
.filter(item -> !item.isCompleted())
|
||||
.findFirst();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
toDoEndpoint: https://jsonplaceholder.typicode.com
|
||||
postEndpoint: https://jsonplaceholder.typicode.com
|
||||
environmentName: ${ENV_NAME}
|
||||
toDoCredentials:
|
||||
username: baeldung
|
||||
password: ${TODO_PASSWORD:-password}
|
||||
postCredentials:
|
||||
username: baeldung
|
||||
password: ${POST_PASSWORD:-password}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Configuration packages="com.amazonaws.services.lambda.runtime.log4j2">
|
||||
<Appenders>
|
||||
<Lambda name="Lambda">
|
||||
<PatternLayout>
|
||||
<pattern>%d{yyyy-MM-dd HH:mm:ss} %X{AWSRequestId} %-5p %c{1} - %m%n</pattern>
|
||||
</PatternLayout>
|
||||
</Lambda>
|
||||
</Appenders>
|
||||
<Loggers>
|
||||
<Root level="info">
|
||||
<AppenderRef ref="Lambda" />
|
||||
</Root>
|
||||
</Loggers>
|
||||
</Configuration>
|
||||
@@ -0,0 +1,58 @@
|
||||
package com.baeldung.lambda.todo;
|
||||
|
||||
import com.amazonaws.services.lambda.runtime.Context;
|
||||
import com.baeldung.lambda.todo.config.Config;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Answers;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import uk.org.webcompere.lightweightconfig.ConfigLoader;
|
||||
import uk.org.webcompere.systemstubs.rules.EnvironmentVariablesRule;
|
||||
import uk.org.webcompere.systemstubs.stream.input.LinesAltStream;
|
||||
import uk.org.webcompere.systemstubs.stream.output.NoopStream;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class AppTest {
|
||||
|
||||
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
|
||||
private Context mockContext;
|
||||
|
||||
@Rule
|
||||
public EnvironmentVariablesRule environmentVariablesRule = new EnvironmentVariablesRule();
|
||||
|
||||
private InputStream fakeInputStream = new LinesAltStream();
|
||||
private OutputStream fakeOutputStream = new NoopStream();
|
||||
|
||||
@Test
|
||||
public void whenTheEnvironmentVariableIsSet_thenItIsLogged() throws Exception {
|
||||
environmentVariablesRule.set("ENV_NAME", "unitTest");
|
||||
new App().handleRequest(fakeInputStream, fakeOutputStream, mockContext);
|
||||
|
||||
verify(mockContext.getLogger())
|
||||
.log("Environment: unitTest\n");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenEnvironmentVariableIsNotSet_thenUseDefault() {
|
||||
String setting = Optional.ofNullable(System.getenv("SETTING"))
|
||||
.orElse("default");
|
||||
|
||||
assertThat(setting).isEqualTo("default");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenConfiguration_canLoadIntoPojo() {
|
||||
environmentVariablesRule.set("ENV_NAME", "unitTest");
|
||||
Config config = ConfigLoader.loadYmlConfigFromResource("configuration.yml", Config.class);
|
||||
assertThat(config.getEnvironmentName()).isEqualTo("unitTest");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.baeldung.lambda.todo.service;
|
||||
|
||||
import com.baeldung.lambda.todo.config.Config;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import uk.org.webcompere.systemstubs.rules.SystemOutRule;
|
||||
|
||||
import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;
|
||||
|
||||
public class ToDoReaderServiceTest {
|
||||
|
||||
@Rule
|
||||
public SystemOutRule systemOutRule = new SystemOutRule();
|
||||
|
||||
@Test
|
||||
public void whenTheServiceStarts_thenItOutputsEndpoint() {
|
||||
Config config = new Config();
|
||||
config.setToDoEndpoint("https://todo-endpoint.com");
|
||||
ToDoReaderService service = new ToDoReaderService(config, null);
|
||||
|
||||
assertThat(systemOutRule.getLinesNormalized())
|
||||
.contains("ToDo Endpoint on: https://todo-endpoint.com");
|
||||
}
|
||||
}
|
||||
22
aws-modules/aws-lambda/todo-reminder/template.yaml
Normal file
22
aws-modules/aws-lambda/todo-reminder/template.yaml
Normal file
@@ -0,0 +1,22 @@
|
||||
AWSTemplateFormatVersion: '2010-09-09'
|
||||
Transform: AWS::Serverless-2016-10-31
|
||||
Description: todo-reminder application
|
||||
|
||||
Parameters:
|
||||
EnvironmentName:
|
||||
Type: String
|
||||
Default: dev
|
||||
|
||||
Resources:
|
||||
ToDoFunction:
|
||||
Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
|
||||
Properties:
|
||||
Timeout: 20
|
||||
CodeUri: ToDoFunction
|
||||
Handler: com.baeldung.lambda.todo.App::handleRequest
|
||||
Runtime: java8
|
||||
MemorySize: 512
|
||||
Environment: # More info about Env Vars: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#environment-object
|
||||
Variables:
|
||||
PARAM1: VALUE
|
||||
ENV_NAME: !Ref EnvironmentName
|
||||
Reference in New Issue
Block a user