Skip to content

Commit b108a2e

Browse files
authored
Events v4 serialization v2 (#345)
* adding SES event and update test library for events v4, serialization v2
1 parent 380ee0a commit b108a2e

File tree

8 files changed

+337
-35
lines changed

8 files changed

+337
-35
lines changed

.github/workflows/aws-lambda-java-tests.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,10 @@ jobs:
2626
java-version: 1.8
2727

2828
# Install base module
29-
- name: Install events with Maven
30-
run: mvn -B install --file aws-lambda-java-events/pom.xml
3129
- name: Install serialization with Maven
3230
run: mvn -B install --file aws-lambda-java-serialization/pom.xml
31+
- name: Install events with Maven
32+
run: mvn -B install --file aws-lambda-java-events/pom.xml
3333

3434
# Package target module
3535
- name: Package tests with Maven
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
package com.amazonaws.services.lambda.runtime.events;
2+
3+
import com.fasterxml.jackson.annotation.JsonProperty;
4+
import lombok.AllArgsConstructor;
5+
import lombok.Builder;
6+
import lombok.Data;
7+
import lombok.NoArgsConstructor;
8+
9+
import java.io.Serializable;
10+
import java.time.Instant;
11+
import java.util.List;
12+
13+
/**
14+
* Represent an event received from SES when it receives an incoming message.
15+
*
16+
* See <a href="https://docs.aws.amazon.com/ses/latest/DeveloperGuide/receiving-email-action-lambda.html">documentation</a>.
17+
*/
18+
@Data
19+
@AllArgsConstructor
20+
@Builder(setterPrefix = "with")
21+
@NoArgsConstructor
22+
public class SESEvent implements Serializable {
23+
24+
private static final long serialVersionUID = 4378251841610238092L;
25+
26+
@JsonProperty("Records")
27+
private List<Record> records;
28+
29+
@Data
30+
@AllArgsConstructor
31+
@Builder(setterPrefix = "with")
32+
@NoArgsConstructor
33+
public static class Record implements Serializable {
34+
35+
private static final long serialVersionUID = 4689200289017967041L;
36+
37+
private String eventSource;
38+
private String eventVersion;
39+
private Ses ses;
40+
}
41+
42+
@Data
43+
@AllArgsConstructor
44+
@Builder(setterPrefix = "with")
45+
@NoArgsConstructor
46+
public static class Ses implements Serializable {
47+
48+
private static final long serialVersionUID = -8671051823119970975L;
49+
50+
private Mail mail;
51+
private Receipt receipt;
52+
}
53+
54+
@Data
55+
@AllArgsConstructor
56+
@Builder(setterPrefix = "with")
57+
@NoArgsConstructor
58+
public static class Mail implements Serializable {
59+
60+
private static final long serialVersionUID = 4055476288790904705L;
61+
62+
private Instant timestamp;
63+
private String source;
64+
private String messageId;
65+
private String[] destination;
66+
private boolean headersTruncated;
67+
private List<Header> headers;
68+
private CommonHeaders commonHeaders;
69+
}
70+
71+
@Data
72+
@AllArgsConstructor
73+
@Builder(setterPrefix = "with")
74+
@NoArgsConstructor
75+
public static class Header implements Serializable {
76+
77+
private static final long serialVersionUID = 1059624012149639930L;
78+
79+
private String name;
80+
private String value;
81+
}
82+
83+
@Data
84+
@AllArgsConstructor
85+
@Builder(setterPrefix = "with")
86+
@NoArgsConstructor
87+
public static class CommonHeaders implements Serializable {
88+
89+
private static final long serialVersionUID = 4926097072068505243L;
90+
91+
private String returnPath;
92+
private String[] from;
93+
private String date;
94+
private String[] to;
95+
private String messageId;
96+
private String subject;
97+
}
98+
99+
@Data
100+
@AllArgsConstructor
101+
@Builder(setterPrefix = "with")
102+
@NoArgsConstructor
103+
public static class Receipt implements Serializable {
104+
105+
private static final long serialVersionUID = -2378481926296810065L;
106+
107+
private Instant timestamp;
108+
private long processingTimeMillis;
109+
private String[] recipients;
110+
private Action action;
111+
private Verdict spamVerdict;
112+
private Verdict virusVerdict;
113+
private Verdict spfVerdict;
114+
private Verdict dkimVerdict;
115+
private Verdict dmarcVerdict;
116+
}
117+
118+
@Data
119+
@AllArgsConstructor
120+
@Builder(setterPrefix = "with")
121+
@NoArgsConstructor
122+
public static class Action implements Serializable {
123+
124+
private static final long serialVersionUID = 292227308414074012L;
125+
126+
private String type;
127+
private String functionArn;
128+
private String invocationType;
129+
}
130+
131+
@Data
132+
@AllArgsConstructor
133+
@Builder(setterPrefix = "with")
134+
@NoArgsConstructor
135+
public static class Verdict implements Serializable {
136+
137+
private static final long serialVersionUID = 773331220324957901L;
138+
139+
private String status;
140+
}
141+
}

aws-lambda-java-tests/pom.xml

+3-3
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
<groupId>com.amazonaws</groupId>
66
<artifactId>aws-lambda-java-tests</artifactId>
7-
<version>1.1.1</version>
7+
<version>2.0.0</version>
88
<packaging>jar</packaging>
99

1010
<name>AWS Lambda Java Tests</name>
@@ -40,12 +40,12 @@
4040
<dependency>
4141
<groupId>com.amazonaws</groupId>
4242
<artifactId>aws-lambda-java-serialization</artifactId>
43-
<version>1.0.0</version>
43+
<version>2.0.0</version>
4444
</dependency>
4545
<dependency>
4646
<groupId>com.amazonaws</groupId>
4747
<artifactId>aws-lambda-java-events</artifactId>
48-
<version>3.11.0</version>
48+
<version>4.0.0</version>
4949
</dependency>
5050
<dependency>
5151
<groupId>org.junit.jupiter</groupId>

aws-lambda-java-tests/src/main/java/com/amazonaws/services/lambda/runtime/tests/EventLoader.java

+17-5
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,20 @@
11
/* Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. */
22
package com.amazonaws.services.lambda.runtime.tests;
33

4-
import com.amazonaws.services.lambda.runtime.serialization.PojoSerializer;
5-
import com.amazonaws.services.lambda.runtime.serialization.events.LambdaEventSerializers;
4+
import com.amazonaws.services.lambda.runtime.events.apigateway.APIGatewayCustomAuthorizerEvent;
5+
import com.amazonaws.services.lambda.runtime.events.apigateway.APIGatewayProxyRequestEvent;
6+
import com.amazonaws.services.lambda.runtime.events.apigateway.APIGatewayV2CustomAuthorizerEvent;
7+
import com.amazonaws.services.lambda.runtime.events.apigateway.APIGatewayV2HTTPEvent;
8+
import com.amazonaws.services.lambda.runtime.events.dynamodb.DynamodbEvent;
9+
import com.amazonaws.services.lambda.runtime.events.kinesis.KinesisEvent;
10+
import com.amazonaws.services.lambda.runtime.events.kinesis.KinesisFirehoseEvent;
11+
import com.amazonaws.services.lambda.runtime.events.s3.S3Event;
612

713
import java.io.*;
814

915
import com.amazonaws.services.lambda.runtime.events.*;
16+
import com.amazonaws.services.lambda.serialization.JacksonPojoSerializer;
17+
import com.amazonaws.services.lambda.serialization.PojoSerializer;
1018

1119
/**
1220
* Load events from json files and serialize them in Events
@@ -97,6 +105,10 @@ public static ScheduledEvent loadScheduledEvent(String filename) {
97105
return loadEvent(filename, ScheduledEvent.class);
98106
}
99107

108+
public static SESEvent loadSESEvent(String filename) {
109+
return loadEvent(filename, SESEvent.class);
110+
}
111+
100112
public static SNSEvent loadSNSEvent(String filename) {
101113
return loadEvent(filename, SNSEvent.class);
102114
}
@@ -115,21 +127,21 @@ public static <T> T loadEvent(String filename, Class<T> targetClass) {
115127
throw new IllegalArgumentException("File " + filename + " must have json extension");
116128
}
117129

118-
PojoSerializer<T> serializer = LambdaEventSerializers.serializerFor(targetClass, ClassLoader.getSystemClassLoader());
130+
JacksonPojoSerializer serializer = JacksonPojoSerializer.getInstance();
119131

120132
InputStream stream = serializer.getClass().getResourceAsStream(filename);
121133
if (stream == null) {
122134
stream = serializer.getClass().getClassLoader().getResourceAsStream(filename);
123135
}
124136
if (stream == null) {
125137
try {
126-
stream = new FileInputStream(new File(filename));
138+
stream = new FileInputStream(filename);
127139
} catch (FileNotFoundException e) {
128140
throw new EventLoadingException("Cannot load " + filename, e);
129141
}
130142
}
131143
try {
132-
return serializer.fromJson(stream);
144+
return serializer.fromJson(stream, targetClass);
133145
} finally {
134146
try {
135147
stream.close();

aws-lambda-java-tests/src/test/java/com/amazonaws/services/lambda/runtime/tests/EventLoaderTest.java

+35-22
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
/* Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. */
22
package com.amazonaws.services.lambda.runtime.tests;
33

4-
import com.amazonaws.services.lambda.runtime.events.models.dynamodb.AttributeValue;
5-
import com.amazonaws.services.lambda.runtime.events.models.dynamodb.Record;
6-
import com.amazonaws.services.lambda.runtime.events.models.dynamodb.StreamRecord;
7-
import org.joda.time.DateTime;
4+
import com.amazonaws.services.lambda.runtime.events.apigateway.APIGatewayCustomAuthorizerEvent;
5+
import com.amazonaws.services.lambda.runtime.events.apigateway.APIGatewayProxyRequestEvent;
6+
import com.amazonaws.services.lambda.runtime.events.apigateway.APIGatewayV2CustomAuthorizerEvent;
7+
import com.amazonaws.services.lambda.runtime.events.apigateway.APIGatewayV2HTTPEvent;
8+
import com.amazonaws.services.lambda.runtime.events.dynamodb.DynamodbEvent;
9+
import com.amazonaws.services.lambda.runtime.events.kinesis.KinesisEvent;
10+
import com.amazonaws.services.lambda.runtime.events.kinesis.KinesisFirehoseEvent;
11+
import com.amazonaws.services.lambda.runtime.events.s3.S3Event;
812
import org.junit.jupiter.api.Test;
913

1014
import java.time.Instant;
@@ -52,7 +56,7 @@ public void testLoadAPIGatewayV2CustomAuthorizerEvent() {
5256

5357
assertThat(event).isNotNull();
5458
assertThat(event.getRequestContext().getHttp().getMethod()).isEqualTo("POST");
55-
assertThat(event.getRequestContext().getTimeEpoch()).isEqualTo(Instant.ofEpochMilli(1583348638390L));
59+
assertThat(event.getRequestContext().getTimeEpoch()).isEqualTo(1583348638390L);
5660
}
5761

5862
@Test
@@ -92,7 +96,7 @@ public void testLoadLambdaDestinationEvent() {
9296
LambdaDestinationEvent event = EventLoader.loadLambdaDestinationEvent("lambda_destination_event.json");
9397

9498
assertThat(event).isNotNull();
95-
assertThat(event.getTimestamp()).isEqualTo(DateTime.parse("2019-11-24T21:52:47.333Z"));
99+
assertThat(event.getTimestamp()).isEqualTo(Instant.parse("2019-11-24T21:52:47.333Z"));
96100
assertThat(event.getRequestContext().getFunctionArn()).isEqualTo("arn:aws:lambda:sa-east-1:123456678912:function:event-destinations:$LATEST");
97101
assertThat(event.getRequestPayload().get("Success")).isEqualTo(false);
98102
}
@@ -145,13 +149,13 @@ public void testLoadSNSEvent() {
145149
assertThat(record.getEventVersion()).isEqualTo("1.0");
146150
assertThat(record.getEventSubscriptionArn()).isEqualTo("arn:aws:sns:eu-central-1:123456789012:TopicSendToMe:e3ddc7d5-2f86-40b8-a13d-3362f94fd8dd");
147151

148-
SNSEvent.SNS sns = record.getSNS();
152+
SNSEvent.SNS sns = record.getSns();
149153
assertThat(sns)
150154
.returns("Test sns message", from(SNSEvent.SNS::getSubject))
151155
.returns("{\n \"id\": 42,\n \"name\": \"Bob\"\n}", from(SNSEvent.SNS::getMessage))
152156
.returns("arn:aws:sns:eu-central-1:123456789012:TopicSendToMe", from(SNSEvent.SNS::getTopicArn))
153157
.returns("dc918f50-80c6-56a2-ba33-d8a9bbf013ab", from(SNSEvent.SNS::getMessageId))
154-
.returns(DateTime.parse("2020-10-08T16:06:14.656Z"), from(SNSEvent.SNS::getTimestamp))
158+
.returns(Instant.parse("2020-10-08T16:06:14.656Z"), from(SNSEvent.SNS::getTimestamp))
155159
.returns("https://sns.eu-central-1.amazonaws.com/?Action=Unsubscribe", SNSEvent.SNS::getUnsubscribeUrl);
156160
assertThat(sns.getMessageAttributes()).containsKey("name");
157161
assertThat(sns.getMessageAttributes().get("name").getValue()).isEqualTo("Bob");
@@ -167,19 +171,19 @@ public void testLoadDynamoEvent() {
167171
DynamodbEvent.DynamodbStreamRecord record = event.getRecords().get(0);
168172
assertThat(record)
169173
.returns("arn:aws:dynamodb:eu-central-1:123456789012:table/ExampleTableWithStream/stream/2015-06-27T00:48:05.899", from(DynamodbEvent.DynamodbStreamRecord::getEventSourceARN))
170-
.returns("INSERT", from(Record::getEventName));
174+
.returns("INSERT", from(DynamodbEvent.DynamodbStreamRecord::getEventName));
171175

172-
StreamRecord streamRecord = record.getDynamodb();
176+
DynamodbEvent.DynamodbStreamRecord.StreamRecord streamRecord = record.getDynamodb();
173177
assertThat(streamRecord)
174-
.returns("4421584500000000017450439091", StreamRecord::getSequenceNumber)
175-
.returns(26L, StreamRecord::getSizeBytes)
176-
.returns("NEW_AND_OLD_IMAGES", StreamRecord::getStreamViewType)
177-
.returns(Date.from(ofEpochSecond(1428537600)), StreamRecord::getApproximateCreationDateTime);
178+
.returns("4421584500000000017450439091", DynamodbEvent.DynamodbStreamRecord.StreamRecord::getSequenceNumber)
179+
.returns(26L, DynamodbEvent.DynamodbStreamRecord.StreamRecord::getSizeBytes)
180+
.returns(DynamodbEvent.DynamodbStreamRecord.StreamViewType.NEW_AND_OLD_IMAGES, DynamodbEvent.DynamodbStreamRecord.StreamRecord::getStreamViewType)
181+
.returns(Instant.ofEpochSecond(1428537600), DynamodbEvent.DynamodbStreamRecord.StreamRecord::getApproximateCreationDateTime);
178182

179-
assertThat(streamRecord.getKeys()).contains(entry("Id", new AttributeValue().withN("101")));
183+
assertThat(streamRecord.getKeys()).contains(entry("Id", new DynamodbEvent.DynamodbStreamRecord.AttributeValue().withN("101")));
180184
assertThat(streamRecord.getNewImage()).containsAnyOf(
181-
entry("Message", new AttributeValue("New item!")),
182-
entry("Id", new AttributeValue().withN("101"))
185+
entry("Message", new DynamodbEvent.DynamodbStreamRecord.AttributeValue("New item!")),
186+
entry("Id", new DynamodbEvent.DynamodbStreamRecord.AttributeValue().withN("101"))
183187
);
184188
}
185189

@@ -191,7 +195,7 @@ public void testLoadKinesisEvent() {
191195

192196
KinesisEvent.Record record = event.getRecords().get(0).getKinesis();
193197
assertThat(record.getEncryptionType()).isEqualTo("NONE");
194-
assertThat(record.getApproximateArrivalTimestamp()).isEqualTo(Date.from(ofEpochSecond(1428537600)));
198+
assertThat(record.getApproximateArrivalTimestamp()).isEqualTo(Instant.ofEpochSecond(1428537600));
195199
assertThat(new String(record.getData().array())).isEqualTo("Hello, this is a test 123.");
196200
}
197201

@@ -214,7 +218,7 @@ public void testLoadCodeCommitEvent() {
214218
CodeCommitEvent.Record record = event.getRecords().get(0);
215219
assertThat(record.getEventSourceArn()).isEqualTo("arn:aws:codecommit:eu-central-1:123456789012:my-repo");
216220
assertThat(record.getUserIdentityArn()).isEqualTo("arn:aws:iam::123456789012:root");
217-
assertThat(record.getEventTime()).isEqualTo(DateTime.parse("2016-01-01T23:59:59.000+0000"));
221+
assertThat(record.getEventTime()).isEqualTo(Instant.parse("2016-01-01T23:59:59Z"));
218222

219223
assertThat(record.getCodeCommit().getReferences()).hasSize(1);
220224
CodeCommitEvent.Reference reference = record.getCodeCommit().getReferences().get(0);
@@ -242,7 +246,7 @@ public void testLoadScheduledEvent() {
242246
ScheduledEvent event = EventLoader.loadScheduledEvent("cloudwatch_event.json");
243247
assertThat(event).isNotNull();
244248
assertThat(event.getDetailType()).isEqualTo("Scheduled Event");
245-
assertThat(event.getTime()).isEqualTo(DateTime.parse("2020-09-30T15:58:34Z"));
249+
assertThat(event.getTime()).isEqualTo(Instant.parse("2020-09-30T15:58:34Z"));
246250
}
247251

248252
@Test
@@ -319,15 +323,15 @@ public void testLoadRabbitMQEvent() {
319323
assertThat(messages).hasSize(1);
320324
RabbitMQEvent.RabbitMessage firstMessage = messages.get(0);
321325
assertThat(firstMessage)
322-
.returns(false, RabbitMQEvent.RabbitMessage::getRedelivered)
326+
.returns(false, RabbitMQEvent.RabbitMessage::isRedelivered)
323327
.returns("eyJ0aW1lb3V0IjowLCJkYXRhIjoiQ1pybWYwR3c4T3Y0YnFMUXhENEUifQ==", RabbitMQEvent.RabbitMessage::getData);
324328

325329
RabbitMQEvent.BasicProperties basicProperties = firstMessage.getBasicProperties();
326330
assertThat(basicProperties)
327331
.returns("text/plain", from(RabbitMQEvent.BasicProperties::getContentType))
328332
.returns(1, from(RabbitMQEvent.BasicProperties::getDeliveryMode))
329333
.returns(34, from(RabbitMQEvent.BasicProperties::getPriority))
330-
.returns(60000, from(RabbitMQEvent.BasicProperties::getExpiration))
334+
.returns("60000", from(RabbitMQEvent.BasicProperties::getExpiration))
331335
.returns("AIDACKCEVSQ6C2EXAMPLE", from(RabbitMQEvent.BasicProperties::getUserId))
332336
.returns(80, from(RabbitMQEvent.BasicProperties::getBodySize))
333337
.returns("Jan 1, 1970, 12:33:41 AM", from(RabbitMQEvent.BasicProperties::getTimestamp));
@@ -338,4 +342,13 @@ public void testLoadRabbitMQEvent() {
338342
assertThat(header1.get("bytes")).contains(118, 97, 108, 117, 101, 49);
339343
assertThat((Integer) headers.get("numberInHeader")).isEqualTo(10);
340344
}
345+
346+
@Test
347+
public void testLoadSESEvent() {
348+
SESEvent event = EventLoader.loadSESEvent("ses_event.json");
349+
assertThat(event).isNotNull();
350+
assertThat(event.getRecords()).hasSize(1);
351+
assertThat(event.getRecords().get(0).getSes().getMail().getDestination()[0]).isEqualTo("[email protected]");
352+
assertThat(event.getRecords().get(0).getSes().getMail().getHeaders()).hasSize(29);
353+
}
341354
}

aws-lambda-java-tests/src/test/java/com/amazonaws/services/lambda/runtime/tests/HandlerParamsTest.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
/* Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. */
22
package com.amazonaws.services.lambda.runtime.tests;
33

4-
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
5-
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
4+
import com.amazonaws.services.lambda.runtime.events.apigateway.APIGatewayProxyRequestEvent;
5+
import com.amazonaws.services.lambda.runtime.events.apigateway.APIGatewayProxyResponseEvent;
66
import com.amazonaws.services.lambda.runtime.tests.annotations.*;
77
import org.junit.jupiter.params.ParameterizedTest;
88

aws-lambda-java-tests/src/test/resources/cloudwatch_event.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"detail-type": "Scheduled Event",
55
"source": "aws.events",
66
"account": "123456789012",
7-
"time": "2020-09-30T15:58:34Z",
7+
"time": "2020-09-30T15:58:34.000Z",
88
"region": "eu-central-1",
99
"resources": [
1010
"arn:aws:events:eu-central-1:123456789012:rule/demoschedule"

0 commit comments

Comments
 (0)