Hello world lambda in Go
package main import ( "context" "github.com/aws/aws-lambda-go/lambda" ) type MyEvent struct { Name string `json:"name"` } type Pet struct { Name string `json:"name"` } type Response struct { Status string `json:"status"` Pets []Pet `json:"pets"` } func HandleRequest(ctx context.Context, name MyEvent) (Response, error) { var pets []Pet pets = append(pets, Pet{Name: "Lucky"}) pets = append(pets, Pet{Name: "Bethoven"}) response := Response{ Status: "OK", Pets: pets, } return response, nil } func main() { lambda.Start(HandleRequest) }
This is how you define a lambda function with Cloudformation
MyLambdaFunction: Type: AWS::Serverless::Function Properties: Handler: "main" Runtime: go1.x CodeUri: s3://path/to/your/lambda.zip Description: "Your own description" Timeout: 5 # In seconds Role: Fn::GetAtt: - "SomeRole" - "Arn"
How do I reference a resource in another Cloudformation stack during template creation?
https://aws.amazon.com/premiumsupport/knowledge-center/cloudformation-reference-resource/
Connecting a lambda function to an SQS queue
EventSourceMapping: Type: AWS::Lambda::EventSourceMapping Properties: BatchSize: 10 # Default 10. Max 10 Enabled: true EventSourceArn: Fn::ImportValue: Ref: ExternalQueueArn # The queue was defined in another Cloudformation stack FunctionName: Fn::GetAtt: - "MyLambdaFunction" asdfasd - "Arn"
What is the easiest to define a policy to connect to an AWS resource?
Simply define your policy within the role:
MyRole: Properties: ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole AssumeRolePolicyDocument: Statement: - Action: ["sts:AssumeRole"] Effect: Allow Principal: Service: [lambda.amazonaws.com] Version: "2012-10-17" Policies: - PolicyName: "QueuePermissions" PolicyDocument: Version: "2012-10-17" Statement: - Effect: "Allow" Resource: "*" Action: - "sqs:DeleteMessage"
Cloudformation template parameters
When defining parameters, make sure you set a default value. For example:
ExternalQueueArn: Type: String Default: "ExternalQueueArn"
Instead of:
ExternalQueueArn: Type: String
Working with SQS
- Create a brand new project on IntelliJ with Maven(make sure the Maven plugins are enabled)
- Add a dependency for AWS SQS library
<dependencies> <!-- https://mvnrepository.com/artifact/com.amazonaws/aws-java-sdk-sqs --> <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-java-sdk-sqs</artifactId> <version>1.11.538</version> </dependency> </dependencies>
Credentials
Put your AWS credentials in your ~/.aws/credentials
file.
Send message request
import com.amazonaws.services.sqs.AmazonSQS; import com.amazonaws.services.sqs.AmazonSQSClientBuilder; import com.amazonaws.services.sqs.model.SendMessageRequest; public class SqsClient { private static final String QUEUE_NAME = "MyQueue"; public static void main(String[] args) { AmazonSQS sqs = AmazonSQSClientBuilder.defaultClient(); // Get the URL for a queue String queueUrl = sqs.getQueueUrl(QUEUE_NAME).getQueueUrl(); System.out.println("Queue URL: " + queueUrl); SendMessageRequest sendMessageResult = new SendMessageRequest() .withQueueUrl(queueUrl) .withMessageBody("hello world") .withDelaySeconds(5); sqs.sendMessage(sendMessageResult); } }
Parse a request’s payload in a Java lambda
ObjectMapper mapper = new ObjectMapper(); Payload payload = mapper.readValue(inputStream, Payload.class);
Where Payload
is a class that models your data, for example, given the following payload:
{ "Records": [ { "attributes": { "ApproximateFirstReceiveTimestamp": "1556142295605", "ApproximateReceiveCount": "1", "SenderId": "AIAAIAA1AA1P11AACN1O1", "SentTimestamp": "1556142290605" }, "awsRegion": "us-west-2", "body": "{\"message\": \"Hello!\"}", "eventSource": "aws:sqs", "eventSourceARN": "arn:aws:sqs:us-west-2:111111111111:ExternalQueue", "md5OfBody": "c5fd3360e55117d8467fadfef40f8631", "messageAttributes": {}, "messageId": "111bc111-9256-4bb4-bbcb-bbbc111cbeb1", "receiptHandle": "AAAAAAAA..." } ] }
Your classes would look like:
@JsonIgnoreProperties(ignoreUnknown = true) public class Payload { private List<Record> records; @JsonProperty("Records") public List<Record> getRecords() { return records; } public void setRecords(List<Record> records) { this.records = records; } } @JsonIgnoreProperties(ignoreUnknown = true) public class Record { private String messageId; private String body; private String eventSource; private String eventSourceARN; private String awsRegion; // Getters & Setters }
How to create (Input|Output)Stream implementations in Java
Java provides two implementations out of the box, they work with bytes though:
ByteArrayInputStream inputStream = new ByteArrayInputStream("{}".getBytes()); ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
How to read InputStream as a string
Use the BufferedReader class
BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8")); reader.readLine();
Reference: https://stackoverflow.com/questions/5200187
Reading a file in Java(a quick reminder)
InputStreamReader isr = new InputStreamReader(new FileInputStream(fileName), StandardCharsets.UTF_8); BufferedReader bufferedReader = new BufferedReader(isr); StringBuilder builder = new StringBuilder(); String line; while ((line = bufferedReader.readLine()) != null) { builder.append(line); } return builder.toString();