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.