How Java Developers Publish Their Lambda Functions With AWS CDK

We will talk about aws cdk on this article. It is really important service for cloud developers because it is hard to manage all services in the aws but with the aws cdk development teams can easily configure their services.

What is AWS CDK

AWS cloud development kit is a framework that is used for defining cloud infrastructure in code. It is based on Infrastructure as Code (IAC) standards that enable developers to maintain their cloud infrastructure in a repeatable and predictable manner.

Create The App

In this part we will talk about how to create our first app and AWS CDK Toolkit command-line tool.

cdk init hello_cdk --language java
mvn compile -q

You can easily init your first project with cdk init command. On this stage we have 2 classes. One of them is “HelloCdkApp” that is our main entry point. The other one is “HelloCdkStack” that contains our service stack. We will define our services stack on this class.

Let’s create our lambda function. First create resources folder and hello.js file.

const AWS = require('aws-sdk');
const S3 = new AWS.S3();

const bucketName = process.env.BUCKET;

exports.main = async function(event, context) {
try {
var method = event.httpMethod;
// Get name, if present
var widgetName = event.path.startsWith('/') ? event.path.substring(1) : event.path;

if (method === "GET") {
// GET / to get the names of all widgets
if (event.path === "/") {
const data = await S3.listObjectsV2({ Bucket: bucketName }).promise();
var body = {
widgets: data.Contents.map(function(e) { return e.Key })
};
return {
statusCode: 200,
headers: {},
body: JSON.stringify(body)
};
}

if (widgetName) {
// GET /name to get info on widget name
const data = await S3.getObject({ Bucket: bucketName, Key: widgetName}).promise();
var body = data.Body.toString('utf-8');

return {
statusCode: 200,
headers: {},
body: JSON.stringify(body)
};
}
}

if (method === "POST") {
// POST /name
// Return error if we do not have a name
if (!widgetName) {
return {
statusCode: 400,
headers: {},
body: "Widget name missing"
};
}

// Create some dummy data to populate object
const now = new Date();
var data = widgetName + " created: " + now;

var base64data = new Buffer(data, 'binary');

await S3.putObject({
Bucket: bucketName,
Key: widgetName,
Body: base64data,
ContentType: 'application/json'
}).promise();

return {
statusCode: 200,
headers: {},
body: JSON.stringify(event.widgets)
};
}

if (method === "DELETE") {
// DELETE /name
// Return an error if we do not have a name
if (!widgetName) {
return {
statusCode: 400,
headers: {},
body: "Widget name missing"
};
}

await S3.deleteObject({
Bucket: bucketName, Key: widgetName
}).promise();

return {
statusCode: 200,
headers: {},
body: "Successfully deleted widget " + widgetName
};
}

// We got something besides a GET, POST, or DELETE
return {
statusCode: 400,
headers: {},
body: "We only accept GET, POST, and DELETE, not " + method
};
} catch(error) {
var body = error.stack || JSON.stringify(error, null, 2);
return {
statusCode: 400,
headers: {},
body: body
}
}
}

We will add some maven dependencies for apigateway, lambda and s3.

<dependency>
<groupId>software.amazon.awscdk</groupId>
<artifactId>apigateway</artifactId>
<version>1.76.0</version>
</dependency>


<dependency>
<groupId>software.amazon.awscdk</groupId>
<artifactId>lambda</artifactId>
<version>1.76.0</version>
</dependency>


<dependency>
<groupId>software.amazon.awscdk</groupId>
<artifactId>s3</artifactId>
<version>1.76.0</version>
</dependency>

Let’s update our “HelloCdkApp” class.

@SuppressWarnings("serial")
public HelloCdkApp(Construct scope, String id) {
super(scope, id);

Bucket bucket = new Bucket(this, "HelloCdkStack");

Function handler = Function.Builder.create(this, "HelloCdkHandler")
.runtime(Runtime.NODEJS_10_X)
.code(Code.fromAsset("resources"))
.handler("hellocdk.main")
.environment(new HashMap<String, String>() {{
put("BUCKET", bucket.getBucketName());
}}).build();

bucket.grantReadWrite(handler);

RestApi api = RestApi.Builder.create(this, "HelloCdk-API")
.restApiName("HelloCdk Service").description("This service services HelloCdk.")
.build();

LambdaIntegration getWidgetsIntegration = LambdaIntegration.Builder.create(handler)
.requestTemplates(new HashMap<String, String>() {{
put("application/json", "{ \"statusCode\": \"200\" }");
}}).build();

api.getRoot().addMethod("GET", getWidgetsIntegration);


Resource widget = api.getRoot().addResource("{id}");

// Add new widget to bucket with: POST /{id}
LambdaIntegration postWidgetIntegration = new LambdaIntegration(handler);

// Get a specific widget from bucket with: GET /{id}
LambdaIntegration getWidgetIntegration = new LambdaIntegration(handler);

// Remove a specific widget from the bucket with: DELETE /{id}
LambdaIntegration deleteWidgetIntegration = new LambdaIntegration(handler);

widget.addMethod("POST", postWidgetIntegration); // POST /{id}
widget.addMethod("GET", getWidgetIntegration); // GET /{id}
widget.addMethod("DELETE", deleteWidgetIntegration); // DELETE /{id}

}

after adding the method run the following commands;

cdk bootstrap
cdk deploy

Let’s check our AWS services. The first one is ApiGateway

The second one is Lamda

The last one is S3

On the final we will destroy our stack. Because it is unnecasatiy for us.

cdk destroy

For full code please visit my github.