Skip to content

Commit

Permalink
feat: Java api cors lambda crud dynamodb (aws-samples#196)
Browse files Browse the repository at this point in the history
* Java implementation of classic load balancer

* Java Sample for api-cors-lambda-dynamodb

* Refactored to two seaparate module - lambda and cd stack

* Need some dummy files for build to succeed with maven sub-modules.

* need a cdk.json for build to go through

* Need some dummy files for build to succeed with maven sub-modules.
Co-authored-by: Mitchell Valine <[email protected]>
  • Loading branch information
djiten75 authored Feb 19, 2020
1 parent 8e5de53 commit cb0abf2
Show file tree
Hide file tree
Showing 22 changed files with 777 additions and 18 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ $ cdk destroy
| [resource-overrides](https://github.com/aws-samples/aws-cdk-examples/tree/master/java/resource-overrides/) | Use of the resource overrides (aka ["escape hatch"](https://docs.aws.amazon.com/cdk/latest/guide/cfn_layer.html)) mechanism. |
| [stepfunctions-job-poller](https://github.com/aws-samples/aws-cdk-examples/tree/master/java/stepfunctions-job-poller/) | A simple StepFunctions workflow |
| [static-site](https://github.com/aws-samples/aws-cdk-examples/tree/master/java/static-site/) | A static site using CloudFront |

| [api-cors-lambda-crud-dynamodb](https://github.com/aws-samples/aws-cdk-examples/tree/master/java/api-cors-lambda-crud-dynamodb/) | Creating a single API with CORS, and five Lambdas doing CRUD operations over a single DynamoDB |
| [classic-load-balancer](https://github.com/aws-samples/aws-cdk-examples/tree/master/java/classic-load-balancer/) | Using an AutoScalingGroup with a Classic Load Balancer |
## Python examples <a name="Python"></a>

To run a Python example, say my-widget-service:
Expand Down
34 changes: 34 additions & 0 deletions java/api-cors-lambda-crud-dynamodb/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# CDK Java Example

This is an example of a CDK program written in Java.

## Building

To build this app, run `mvn compile`. This will download the required
dependencies to compile the Java code and create jar for associated software.amazon.awscdk.examples.lambda code.

You can use your IDE to write code and unit tests, but you will need to use the
CDK toolkit if you wish to synthesize/deploy stacks.

If you need to modify the lambda code then do mvn package and copy the
jar file to asset directory in the parent module
## CDK Toolkit

The [`cdk.json`](./cdk.json) file in the root of this repository includes
instructions for the CDK toolkit on how to execute this program.

Specifically, it will tell the toolkit to use the `mvn exec:java` command as the
entry point of your application. After changing your Java code, you will be able
to run the CDK toolkit commands as usual (Maven will recompile as needed):

$ cdk ls
<list all stacks in this program>

$ cdk synth
<cloudformation template>

$ cdk deploy
<deploy stack to your account>

$ cdk diff
<diff against deployed stack>
Binary file not shown.
3 changes: 3 additions & 0 deletions java/api-cors-lambda-crud-dynamodb/cdk.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"app": "mvn exec:java -pl cdk -Dexec.mainClass=software.amazon.awscdk.examples.CorsLambdaCrudDynamodbApp"
}
3 changes: 3 additions & 0 deletions java/api-cors-lambda-crud-dynamodb/cdk/cdk.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"app": "mvn test"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
{
}
18 changes: 18 additions & 0 deletions java/api-cors-lambda-crud-dynamodb/cdk/cdk.out.dummy/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"version": "1.16.0",
"artifacts": {
"Tree": {
"type": "cdk:tree",
"properties": {
"file": "tree.json"
}
},
"dummy":{
"type": "aws:cloudformation:stack",
"environment": "aws://unknown-account/unknown-region",
"properties": {
"templateFile": "dummy.template.json"
}
}
}
}
87 changes: 87 additions & 0 deletions java/api-cors-lambda-crud-dynamodb/cdk/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
<?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">
<parent>
<artifactId>cors-lambda-crud-dynamodb</artifactId>
<groupId>com.amazonaws.cdk</groupId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>cdk</artifactId>
<build>
<plugins>
<plugin>

<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>copy-folder</id>
<phase>test</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${project.basedir}/cdk.out</outputDirectory>
<resources>
<resource>
<filtering>false</filtering>
<directory>${project.basedir}/cdk.out.dummy</directory>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>

<dependencies>
<dependency>
<groupId>software.amazon.awscdk</groupId>
<artifactId>core</artifactId>
<version>[1.20.0, 2)</version>
</dependency>
<dependency>
<groupId>software.amazon.awscdk</groupId>
<artifactId>apigateway</artifactId>
<version>[1.20.0, 2)</version>
</dependency>

<dependency>
<groupId>software.amazon.awscdk</groupId>
<artifactId>dynamodb</artifactId>
<version>[1.20.0, 2)</version>
</dependency>
<dependency>
<groupId>software.amazon.awscdk</groupId>
<artifactId>lambda</artifactId>
<version>[1.20.0, 2)</version>
</dependency>

<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-library</artifactId>
<version>1.3</version>
<scope>test</scope>
</dependency>
</dependencies>



</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package software.amazon.awscdk.examples;

import software.amazon.awscdk.core.App;

public class CorsLambdaCrudDynamodbApp {
public static void main(final String[] args) {
App app = new App();

new CorsLambdaCrudDynamodbStack(app, "cdk-cors-lambda-crud-dynamodb-example");

app.synth();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
package software.amazon.awscdk.examples;

import software.amazon.awscdk.core.Construct;
import software.amazon.awscdk.core.Duration;
import software.amazon.awscdk.core.RemovalPolicy;
import software.amazon.awscdk.core.Stack;
import software.amazon.awscdk.services.apigateway.*;
import software.amazon.awscdk.services.dynamodb.Attribute;
import software.amazon.awscdk.services.dynamodb.AttributeType;
import software.amazon.awscdk.services.dynamodb.Table;
import software.amazon.awscdk.services.dynamodb.TableProps;
import software.amazon.awscdk.services.lambda.Code;
import software.amazon.awscdk.services.lambda.Function;
import software.amazon.awscdk.services.lambda.FunctionProps;
import software.amazon.awscdk.services.lambda.Runtime;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* CorsLambdaCrudDynamodbStack CDK example for Java!
*/
class CorsLambdaCrudDynamodbStack extends Stack {
public CorsLambdaCrudDynamodbStack(final Construct parent, final String name) {
super(parent, name);

TableProps tableProps;
Attribute partitionKey = Attribute.builder()
.name("itemId")
.type(AttributeType.STRING)
.build();
tableProps = TableProps.builder()
.tableName("items")
.partitionKey(partitionKey)
// The default removal policy is RETAIN, which means that cdk destroy will not attempt to delete
// the new table, and it will remain in your account until manually deleted. By setting the policy to
// DESTROY, cdk destroy will delete the table (even if it has data in it)
.removalPolicy(RemovalPolicy.DESTROY)
.build();
Table dynamodbTable = new Table(this, "items", tableProps);


Map<String, String> lambdaEnvMap = new HashMap<>();
lambdaEnvMap.put("TABLE_NAME", dynamodbTable.getTableName());
lambdaEnvMap.put("PRIMARY_KEY","itemId");



Function getOneItemFunction = new Function(this, "getOneItemFunction",
getLambdaFunctionProps(lambdaEnvMap, "software.amazon.awscdk.examples.lambda.GetOneItem"));
Function getAllItemsFunction = new Function(this, "getAllItemsFunction",
getLambdaFunctionProps(lambdaEnvMap, "software.amazon.awscdk.examples.lambda.GetAllItems"));
Function createItemFunction = new Function(this, "createItemFunction",
getLambdaFunctionProps(lambdaEnvMap, "software.amazon.awscdk.examples.lambda.CreateItem"));
Function updateItemFunction = new Function(this, "updateItemFunction",
getLambdaFunctionProps(lambdaEnvMap, "software.amazon.awscdk.examples.lambda.UpdateItem"));
Function deleteItemFunction = new Function(this, "deleteItemFunction",
getLambdaFunctionProps(lambdaEnvMap, "software.amazon.awscdk.examples.lambda.DeleteItem"));



dynamodbTable.grantReadWriteData(getOneItemFunction);
dynamodbTable.grantReadWriteData(getAllItemsFunction);
dynamodbTable.grantReadWriteData(createItemFunction);
dynamodbTable.grantReadWriteData(updateItemFunction);
dynamodbTable.grantReadWriteData(deleteItemFunction);

RestApi api = new RestApi(this, "itemsApi",
RestApiProps.builder().restApiName("Items Service").build());

IResource items = api.getRoot().addResource("items");

Integration getAllIntegration = new LambdaIntegration(getAllItemsFunction);
items.addMethod("GET", getAllIntegration);

Integration createOneIntegration = new LambdaIntegration(createItemFunction);
items.addMethod("POST", createOneIntegration);
addCorsOptions(items);



IResource singleItem = items.addResource("{id}");
Integration getOneIntegration = new LambdaIntegration(getOneItemFunction);
singleItem.addMethod("GET",getOneIntegration);

Integration updateOneIntegration = new LambdaIntegration(updateItemFunction);
singleItem.addMethod("PATCH",updateOneIntegration);

Integration deleteOneIntegration = new LambdaIntegration(deleteItemFunction);
singleItem.addMethod("DELETE",deleteOneIntegration);
addCorsOptions(singleItem);
}



private void addCorsOptions(IResource item) {
List<MethodResponse> methoedResponses = new ArrayList<>();

Map<String, Boolean> responseParameters = new HashMap<>();
responseParameters.put("method.response.header.Access-Control-Allow-Headers", Boolean.TRUE);
responseParameters.put("method.response.header.Access-Control-Allow-Methods", Boolean.TRUE);
responseParameters.put("method.response.header.Access-Control-Allow-Credentials", Boolean.TRUE);
responseParameters.put("method.response.header.Access-Control-Allow-Origin", Boolean.TRUE);
methoedResponses.add(MethodResponse.builder()
.responseParameters(responseParameters)
.statusCode("200")
.build());
MethodOptions methodOptions = MethodOptions.builder()
.methodResponses(methoedResponses)
.build()
;

Map<String, String> requestTemplate = new HashMap<>();
requestTemplate.put("application/json","{\"statusCode\": 200}");
List<IntegrationResponse> integrationResponses = new ArrayList<>();

Map<String, String> integrationResponseParameters = new HashMap<>();
integrationResponseParameters.put("method.response.header.Access-Control-Allow-Headers","'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,X-Amz-User-Agent'");
integrationResponseParameters.put("method.response.header.Access-Control-Allow-Origin","'*'");
integrationResponseParameters.put("method.response.header.Access-Control-Allow-Credentials","'false'");
integrationResponseParameters.put("method.response.header.Access-Control-Allow-Methods","'OPTIONS,GET,PUT,POST,DELETE'");
integrationResponses.add(IntegrationResponse.builder()
.responseParameters(integrationResponseParameters)
.statusCode("200")
.build());
Integration methodIntegration = MockIntegration.Builder.create()
.integrationResponses(integrationResponses)
.passthroughBehavior(PassthroughBehavior.NEVER)
.requestTemplates(requestTemplate)
.build();

item.addMethod("OPTIONS", methodIntegration, methodOptions);
}

private FunctionProps getLambdaFunctionProps(Map<String, String> lambdaEnvMap, String handler) {
return FunctionProps.builder()
.code(Code.fromAsset("./asset/lambda-1.0.0-jar-with-dependencies.jar"))
.handler(handler)
.runtime(Runtime.JAVA_8)
.environment(lambdaEnvMap)
.timeout(Duration.seconds(30))
.memorySize(512)
.build();
}
}
3 changes: 3 additions & 0 deletions java/api-cors-lambda-crud-dynamodb/lambda/cdk.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"app": "mvn test"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"version": "1.16.0",
"artifacts": {
"Tree": {
"type": "cdk:tree",
"properties": {
"file": "tree.json"
}
},
"dummy":{
"type": "aws:cloudformation:stack",
"environment": "aws://unknown-account/unknown-region",
"properties": {
"templateFile": "dummy.template.json"
}
}
}
}
Loading

0 comments on commit cb0abf2

Please sign in to comment.