Skip to content

Commit

Permalink
Initial lambda code
Browse files Browse the repository at this point in the history
  • Loading branch information
cer committed Nov 21, 2017
1 parent dd4a8af commit b7ce7f5
Show file tree
Hide file tree
Showing 21 changed files with 905 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ build/
*.idea/
*.iml
*.log
.serverless
36 changes: 36 additions & 0 deletions ftgo-restaurant-service-aws-lambda/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@


dependencies {

compile "com.amazonaws:aws-lambda-java-core:1.1.0"
compile "com.amazonaws:aws-lambda-java-events:2.0.1"

compile ("io.eventuate.tram.core:eventuate-tram-producer-jdbc:$eventuateTramVersion") {
exclude module: "org.springframework"
}
compile "io.eventuate.tram.core:eventuate-tram-events:$eventuateTramVersion"
compile project(":ftgo-restaurant-service-api")

compile "org.springframework.boot:spring-boot-starter-data-jpa:$springBootVersion"

compile 'javax.el:javax.el-api:2.2.5'

testCompile "io.eventuate.util:eventuate-util-test:$eventuateUtilVersion"
testCompile "io.eventuate.tram.core:eventuate-tram-test-util:$eventuateTramVersion"

testCompile "org.springframework.boot:spring-boot-starter-test:$springBootVersion"
testCompile 'com.jayway.restassured:rest-assured:2.3.0'
testCompile "com.jayway.jsonpath:json-path:2.3.0"

}

task buildZip(type: Zip) {
from compileJava
from processResources
into('lib') {
from configurations.runtime
}
}

build.dependsOn buildZip

36 changes: 36 additions & 0 deletions ftgo-restaurant-service-aws-lambda/serverless.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
service: ftgo-application-lambda

provider:
name: aws
runtime: java8
timeout: 35
region: ${env:AWS_REGION}
stage: dev
environment:
SPRING_DATASOURCE_DRIVER_CLASS_NAME: com.mysql.jdbc.Driver
SPRING_DATASOURCE_URL: ${env:AWS_RDS_JDBC_URL}
SPRING_DATASOURCE_USERNAME: ${env:AWS_RDS_JDBC_USER_ID}
SPRING_DATASOURCE_PASSWORD: ${env:AWS_RDS_JDBC_USER_PASSWORD}
vpc:
securityGroupIds:
- ${AWS_RDS_SECURITY_GROUP_ID}
subnetIds:
- ${AWS_RDS_SECURITY_VPC_ID}

package:
artifact: build/distributions/ftgo-restaurant-service-aws-lambda.zip


functions:
create-restaurant:
handler: net.chrisrichardson.ftgo.restaurantservice.lambda.CreateRestaurantRequestHandler
events:
- http:
path: restaurants
method: post
find-restaurant:
handler: net.chrisrichardson.ftgo.restaurantservice.lambda.FindRestaurantRequestHandler
events:
- http:
path: restaurants/{restaurantId}
method: get
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package net.chrisrichardson.ftgo.restaurantservice.aws;

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 org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static net.chrisrichardson.ftgo.restaurantservice.aws.ApiGatewayResponse.buildErrorResponse;


public abstract class AbstractHttpHandler implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {

private Logger log = LoggerFactory.getLogger(this.getClass());

@Override
public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent input, Context context) {
log.debug("Got request: {}", input);
try {
beforeHandling(input, context);
return handleHttpRequest(input, context);
} catch (Exception e) {
log.error("Error handling request id: {}", context.getAwsRequestId(), e);
return buildErrorResponse(new AwsLambdaError(
"Internal Server Error",
"500",
context.getAwsRequestId(),
"Error handling request: " + context.getAwsRequestId() + " " + input.toString()));
}
}

protected void beforeHandling(APIGatewayProxyRequestEvent request, Context context) {
// do nothing
}

protected abstract APIGatewayProxyResponseEvent handleHttpRequest(APIGatewayProxyRequestEvent request, Context context);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
package net.chrisrichardson.ftgo.restaurantservice.aws;

import org.apache.commons.lang.builder.ToStringBuilder;

import java.util.Map;
import java.util.Optional;

public class ApiGatewayRequest {

private String resource;
private String path;
private String httpMethod;
private Map<String, String> headers;
private Map<String, String> queryStringParameters;
private Map<String, String> pathParameters;
private Map<String, String> stageVariables;
private RequestContext requestContext;
private String body;
private boolean isBase64Encoded;

public String getResource() {
return resource;
}

public void setResource(String resource) {
this.resource = resource;
}

public String getPath() {
return path;
}

public void setPath(String path) {
this.path = path;
}

public String getHttpMethod() {
return httpMethod;
}

public void setHttpMethod(String httpMethod) {
this.httpMethod = httpMethod;
}

public Map<String, String> getHeaders() {
return headers;
}

public void setHeaders(Map<String, String> headers) {
this.headers = headers;
}

public Map<String, String> getQueryStringParameters() {
return queryStringParameters;
}

public void setQueryStringParameters(Map<String, String> queryStringParameters) {
this.queryStringParameters = queryStringParameters;
}

public Map<String, String> getPathParameters() {
return pathParameters;
}

public void setPathParameters(Map<String, String> pathParameters) {
this.pathParameters = pathParameters;
}

public Map<String, String> getStageVariables() {
return stageVariables;
}

public void setStageVariables(Map<String, String> stageVariables) {
this.stageVariables = stageVariables;
}

public RequestContext getRequestContext() {
return requestContext;
}

public void setRequestContext(RequestContext requestContext) {
this.requestContext = requestContext;
}

public String getBody() {
return body;
}

public void setBody(String body) {
this.body = body;
}

public boolean isBase64Encoded() {
return isBase64Encoded;
}

public void setBase64Encoded(boolean base64Encoded) {
isBase64Encoded = base64Encoded;
}

@Override
public String toString() {
return ToStringBuilder.reflectionToString(this);
}

public String getPathParam(String paramName) {
return Optional.ofNullable(this.getPathParameters())
.map(paramsMap -> paramsMap.get(paramName))
.orElse(null);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package net.chrisrichardson.ftgo.restaurantservice.aws;

import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
import io.eventuate.javaclient.commonimpl.JSonMapper;

import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

public class ApiGatewayResponse {
private final int statusCode;
private final String body;
private final Map<String, String> headers;
private final boolean isBase64Encoded;

public ApiGatewayResponse(int statusCode, String body, Map<String, String> headers, boolean isBase64Encoded) {
this.statusCode = statusCode;
this.body = body;
this.headers = headers;
this.isBase64Encoded = isBase64Encoded;
}

public int getStatusCode() {
return statusCode;
}

public String getBody() {
return body;
}

public Map<String, String> getHeaders() {
return headers;
}

// API Gateway expects the property to be called "isBase64Encoded" => isIs
public boolean isIsBase64Encoded() {
return isBase64Encoded;
}

public static Builder builder() {
return new Builder();
}

public static class Builder {
private int statusCode = 200;
private Map<String, String> headers = Collections.emptyMap();
private String rawBody;
private Object objectBody;
private byte[] binaryBody;
private boolean base64Encoded;

public Builder setStatusCode(int statusCode) {
this.statusCode = statusCode;
return this;
}

public Builder setHeaders(Map<String, String> headers) {
this.headers = headers;
return this;
}

public Builder setRawBody(String rawBody) {
this.rawBody = rawBody;
return this;
}

public Builder setObjectBody(Object objectBody) {
this.objectBody = objectBody;
return this;
}

public Builder setBinaryBody(byte[] binaryBody) {
this.binaryBody = binaryBody;
setBase64Encoded(true);
return this;
}

public Builder setBase64Encoded(boolean base64Encoded) {
this.base64Encoded = base64Encoded;
return this;
}

public APIGatewayProxyResponseEvent build() {
String body = null;
if (rawBody != null) {
body = rawBody;
} else if (objectBody != null) {
body = JSonMapper.toJson(objectBody);
} else if (binaryBody != null) {
body = new String(Base64.getEncoder().encode(binaryBody), StandardCharsets.UTF_8);
}
APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent();
response.setStatusCode(statusCode);
response.setBody(body);
response.setHeaders(headers);
return response;
}
}

public static APIGatewayProxyResponseEvent buildErrorResponse(AwsLambdaError error) {
return ApiGatewayResponse.builder()
.setStatusCode(Integer.valueOf(error.getCode()))
.setObjectBody(error)
.setHeaders(applicationJsonHeaders())
.build();
}

public static Map<String, String> applicationJsonHeaders() {
Map<String, String> headers = new HashMap<>();
headers.put("Content-Type", "application/json");
return headers;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package net.chrisrichardson.ftgo.restaurantservice.aws;

public class AwsLambdaError {
private String type;
private String code;
private String requestId;
private String message;

public AwsLambdaError() {
}

public AwsLambdaError(String type, String code, String requestId, String message) {
this.type = type;
this.code = code;
this.requestId = requestId;
this.message = message;
}

public String getType() {
return type;
}

public String getCode() {
return code;
}

public String getRequestId() {
return requestId;
}

public String getMessage() {
return message;
}
}
Loading

0 comments on commit b7ce7f5

Please sign in to comment.