Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lambda proxy integration #43

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions MonoToMicroAssets/MonoToMicroLambda.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Resources:
- !Sub "arn:aws:lambda:${AWS::Region}:580247275435:layer:LambdaInsightsExtension:38"
Code:
S3Bucket: '{{resolve:ssm:LambdaAssetBucketName:1}}'
S3Key: MonoToMicroLambda-0.0.1.jar
S3Key: MonoToMicroLambda-0.0.2.jar
Role: !Sub 'arn:aws:iam::${AWS::AccountId}:role/service-role/MonoToMicroLambdaRole'
Handler: com.monoToMicro.Lambda.UnicornBasketImpl::addUnicornToBasket
TracingConfig:
Expand All @@ -33,7 +33,7 @@ Resources:
- !Sub "arn:aws:lambda:${AWS::Region}:580247275435:layer:LambdaInsightsExtension:38"
Code:
S3Bucket: '{{resolve:ssm:LambdaAssetBucketName:1}}'
S3Key: MonoToMicroLambda-0.0.1.jar
S3Key: MonoToMicroLambda-0.0.2.jar
Role: !Sub 'arn:aws:iam::${AWS::AccountId}:role/service-role/MonoToMicroLambdaRole'
Handler: com.monoToMicro.Lambda.UnicornBasketImpl::removeUnicornFromBasket
TracingConfig:
Expand All @@ -53,7 +53,7 @@ Resources:
- !Sub "arn:aws:lambda:${AWS::Region}:580247275435:layer:LambdaInsightsExtension:38"
Code:
S3Bucket: '{{resolve:ssm:LambdaAssetBucketName:1}}'
S3Key: MonoToMicroLambda-0.0.1.jar
S3Key: MonoToMicroLambda-0.0.2.jar
Role: !Sub 'arn:aws:iam::${AWS::AccountId}:role/service-role/MonoToMicroLambdaRole'
Handler: com.monoToMicro.Lambda.UnicornBasketImpl::getUnicornsBasket
TracingConfig:
Expand Down
6 changes: 4 additions & 2 deletions MonoToMicroLambda/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ plugins {
}

group 'com.monoToMicro'
version '0.0.1'
version '0.0.2'
java.sourceCompatibility = JavaVersion.VERSION_11
java.targetCompatibility = JavaVersion.VERSION_11

Expand All @@ -14,10 +14,12 @@ repositories {
}

dependencies {
implementation 'com.amazonaws:aws-lambda-java-core:1.2.1'
implementation 'com.amazonaws:aws-lambda-java-core:1.2.3'
implementation 'com.amazonaws:aws-lambda-java-events:3.11.3'
implementation platform('software.amazon.awssdk:bom:2.17.136')
implementation platform('com.amazonaws:aws-xray-recorder-sdk-bom:2.14.0')
implementation 'software.amazon.awssdk:aws-crt-client:2.17.143-PREVIEW'
implementation 'software.amazon.lambda:powertools-serialization:1.17.0'
implementation 'software.amazon.awssdk:dynamodb-enhanced', {
exclude group: 'software.amazon.awssdk', module: 'netty-nio-client'
exclude group: 'software.amazon.awssdk', module: 'apache-client'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,15 @@
package com.monoToMicro.Lambda;

import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.LambdaLogger;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.APIGatewayV2HTTPEvent;
import com.amazonaws.services.lambda.runtime.events.APIGatewayV2HTTPResponse;
import com.amazonaws.xray.AWSXRay;
import com.amazonaws.xray.entities.Subsegment;
import com.amazonaws.xray.interceptors.TracingInterceptor;
import com.fasterxml.jackson.core.JsonProcessingException;
import static software.amazon.lambda.powertools.utilities.EventDeserializer.extractDataFrom;

import software.amazon.awssdk.auth.credentials.EnvironmentVariableCredentialsProvider;
import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration;
Expand All @@ -35,22 +40,29 @@
import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient;
import software.amazon.awssdk.services.dynamodb.model.DynamoDbException;
import software.amazon.awssdk.utils.StringUtils;
import software.amazon.lambda.powertools.utilities.JsonConfig;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;

public class UnicornBasketImpl implements RequestHandler<UnicornBasket, String> {

public class UnicornBasketImpl implements RequestHandler<APIGatewayV2HTTPEvent, APIGatewayV2HTTPResponse> {
private static final String UNICORN_TABLE_NAME = "unishop";
private static final DynamoDbAsyncClient ddb = DynamoDbAsyncClient.builder()
.credentialsProvider(EnvironmentVariableCredentialsProvider.create())
.httpClientBuilder(AwsCrtAsyncHttpClient.builder().maxConcurrency(50))
.region(Region.of(System.getenv("AWS_REGION")))
.overrideConfiguration(ClientOverrideConfiguration.builder()
.addExecutionInterceptor(new TracingInterceptor()).build())
.addExecutionInterceptor(new TracingInterceptor()).build())
.build();
private static final DynamoDbEnhancedAsyncClient client = DynamoDbEnhancedAsyncClient.builder()
.dynamoDbClient(ddb)
.build();
private static Map<String, String> staticHeaders = Map.of("Content-Type", "application/json",
"Access-Control-Allow-Headers", "Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token",
"Access-Control-Allow-Origin", "*",
"Access-Control-Allow-Methods", "DELETE,OPTIONS,POST,GET");

static {
try {
Expand All @@ -64,15 +76,20 @@ public class UnicornBasketImpl implements RequestHandler<UnicornBasket, String>
}

@Override
public String handleRequest(UnicornBasket unicornBasket, Context context) {
return "Unicorn Lives Matter";
public APIGatewayV2HTTPResponse handleRequest(APIGatewayV2HTTPEvent event, Context context) {
return APIGatewayV2HTTPResponse.builder().withStatusCode(200)
.withHeaders(staticHeaders).withBody("Unicorn Lives Matter").build();
}

public String addUnicornToBasket(UnicornBasket unicornBasket, Context context)
throws ExecutionException, InterruptedException {
public APIGatewayV2HTTPResponse addUnicornToBasket(APIGatewayV2HTTPEvent event, Context context)
throws ExecutionException, InterruptedException {
final DynamoDbAsyncTable<UnicornBasket> unicornBasketTable = client.table(
UNICORN_TABLE_NAME, TableSchema.fromBean(UnicornBasket.class));

UnicornBasket unicornBasket = extractDataFrom(event).as(UnicornBasket.class);
LambdaLogger logger = context.getLogger();
logger.log("Incoming addUnicornToBasket request " + parseDTOToString(unicornBasket));

//Get current basket
UnicornBasket currentBasket = unicornBasketTable.getItem(r ->
r.key(Key.builder().partitionValue(unicornBasket.getUuid()).build())).get();
Expand All @@ -84,9 +101,11 @@ public String addUnicornToBasket(UnicornBasket unicornBasket, Context context)
Subsegment subsegment = AWSXRay.beginSubsegment("Creating new basket");
subsegment.putMetadata("unicorns", "newBasket", unicornBasket.getUuid());
AWSXRay.endSubsegment();
return "Added Unicorn to basket";
return APIGatewayV2HTTPResponse.builder().withStatusCode(200)
.withHeaders(staticHeaders).withBody("Added Unicorn to basket").build();
}
return "No basket exist and none was created";
return APIGatewayV2HTTPResponse.builder().withStatusCode(200)
.withHeaders(staticHeaders).withBody("No basket exist and none was created").build();
}

//basket already exist, will check if item exist and add if not found
Expand All @@ -101,7 +120,8 @@ public String addUnicornToBasket(UnicornBasket unicornBasket, Context context)
for (Unicorn currentUnicorn : currentUnicorns) {
if (currentUnicorn.getUuid().equals(unicornToAddUuid)) {
//The unicorn already exists, no need to add him.
return "Unicorn already exists!";
return APIGatewayV2HTTPResponse.builder().withStatusCode(200)
.withHeaders(staticHeaders).withBody("Unicorn already exists!").build();
}
}

Expand All @@ -112,23 +132,30 @@ public String addUnicornToBasket(UnicornBasket unicornBasket, Context context)
Subsegment subsegment = AWSXRay.beginSubsegment("Adding new unicorn");
subsegment.putMetadata("unicorns", "newUnicorn ", unicornToAdd.getUuid());
AWSXRay.endSubsegment();
return "Added Unicorn to basket";
return APIGatewayV2HTTPResponse.builder().withStatusCode(200)
.withHeaders(staticHeaders).withBody("Added Unicorn to basket").build();
}
return "Are you sure you added a Unicorn?";
return APIGatewayV2HTTPResponse.builder().withStatusCode(200)
.withHeaders(staticHeaders).withBody("Are you sure you added a Unicorn?").build();
}

public String removeUnicornFromBasket(UnicornBasket unicornBasket, Context context)
public APIGatewayV2HTTPResponse removeUnicornFromBasket(APIGatewayV2HTTPEvent event, Context context)
throws ExecutionException, InterruptedException {
final DynamoDbAsyncTable<UnicornBasket> unicornBasketTable = client.table(
UNICORN_TABLE_NAME, TableSchema.fromBean(UnicornBasket.class));

UnicornBasket unicornBasket = extractDataFrom(event).as(UnicornBasket.class);
LambdaLogger logger = context.getLogger();
logger.log("Incoming removeUnicornFromBasket request " + parseDTOToString(unicornBasket));

//Get current basket
UnicornBasket currentBasket = unicornBasketTable.getItem(r ->
r.key(Key.builder().partitionValue(unicornBasket.getUuid()).build())).get();

//if no basket exist then return an error
if (currentBasket == null) {
return "No basket exist, nothing to delete";
return APIGatewayV2HTTPResponse.builder().withStatusCode(200)
.withHeaders(staticHeaders).withBody("No basket exist, nothing to delete").build();
}

//basket exist, will check if item exist and will remove
Expand All @@ -146,12 +173,14 @@ public String removeUnicornFromBasket(UnicornBasket unicornBasket, Context conte
if (currentUnicorns.isEmpty()) {
//no more unicorns in basket, will delete the basket
unicornBasketTable.deleteItem(currentBasket);
return "Unicorn was removed and basket was deleted!";
return APIGatewayV2HTTPResponse.builder().withStatusCode(200)
.withHeaders(staticHeaders).withBody("Unicorn was removed and basket was deleted!").build();
} else {
//keeping basket alive as more unicorns are in it
currentBasket.setUnicorns(currentUnicorns);
unicornBasketTable.putItem(currentBasket);
return "Unicorn was removed! Other unicorns are still in basket";
return APIGatewayV2HTTPResponse.builder().withStatusCode(200)
.withHeaders(staticHeaders).withBody("Unicorn was removed! Other unicorns are still in basket").build();
}
}
}
Expand All @@ -160,21 +189,39 @@ public String removeUnicornFromBasket(UnicornBasket unicornBasket, Context conte
//no unicorn to remove, will try to remove the basket nonetheless
unicornBasketTable.deleteItem(currentBasket);
}
return "Didn't find a unicorn to remove";
return APIGatewayV2HTTPResponse.builder().withStatusCode(200)
.withHeaders(staticHeaders).withBody("Didn't find a unicorn to remove").build();
}
return "Are you sure you asked to remove a Unicorn?";
return APIGatewayV2HTTPResponse.builder().withStatusCode(200)
.withHeaders(staticHeaders).withBody("Are you sure you asked to remove a Unicorn?").build();
}

public UnicornBasket getUnicornsBasket(UnicornBasket unicornBasket, Context context)
public APIGatewayV2HTTPResponse getUnicornsBasket(APIGatewayV2HTTPEvent event, Context context)
throws ExecutionException, InterruptedException {
final DynamoDbAsyncTable<UnicornBasket> unicornBasketTable = client.table(
UNICORN_TABLE_NAME, TableSchema.fromBean(UnicornBasket.class));
LambdaLogger logger = context.getLogger();

UnicornBasket unicornBasket = null;

if (null != event && null != event.getPathParameters()) {
logger.log("Incoming getUnicornsBasket request Path params" + event.getPathParameters().toString());
String uuidPathParamValue = event.getPathParameters().get("uuid");

if (!StringUtils.isEmpty(unicornBasket.getUuid())) {
return unicornBasketTable.getItem(r ->
r.key(Key.builder().partitionValue(unicornBasket.getUuid()).build())).get();
if (StringUtils.isNotBlank(uuidPathParamValue)) {
unicornBasket = unicornBasketTable
.getItem(r -> r.key(Key.builder().partitionValue(uuidPathParamValue).build())).get();
}
}
return APIGatewayV2HTTPResponse.builder().withStatusCode(200).withHeaders(staticHeaders)
.withBody(parseDTOToString(unicornBasket)).build();
}

return null;
private static String parseDTOToString(UnicornBasket unicornBasket) {
try {
return JsonConfig.get().getObjectMapper().writeValueAsString(unicornBasket);
} catch (JsonProcessingException e) {
return "";
}
}
}