Skip to content

Commit ec2dfab

Browse files
author
Evangilo Morais
committed
add support to set a prefix for the S3 key #7
1 parent 50ee609 commit ec2dfab

File tree

4 files changed

+114
-2
lines changed

4 files changed

+114
-2
lines changed

src/main/java/com/amazon/sqs/javamessaging/AmazonSQSExtendedClient.java

+11-2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import java.util.List;
2323
import java.util.Map;
2424
import java.util.Optional;
25+
import java.util.UUID;
2526

2627
import org.apache.commons.logging.Log;
2728
import org.apache.commons.logging.LogFactory;
@@ -965,7 +966,7 @@ private SendMessageBatchRequestEntry storeMessageInS3(SendMessageBatchRequestEnt
965966
updateMessageAttributePayloadSize(batchEntry.messageAttributes(), messageContentSize));
966967

967968
// Store the message content in S3.
968-
String largeMessagePointer = payloadStore.storeOriginalPayload(messageContentStr);
969+
String largeMessagePointer = storeOriginalPayload(messageContentStr);
969970
batchEntryBuilder.messageBody(largeMessagePointer);
970971

971972
return batchEntryBuilder.build();
@@ -984,12 +985,20 @@ private SendMessageRequest storeMessageInS3(SendMessageRequest sendMessageReques
984985
updateMessageAttributePayloadSize(sendMessageRequest.messageAttributes(), messageContentSize));
985986

986987
// Store the message content in S3.
987-
String largeMessagePointer = payloadStore.storeOriginalPayload(messageContentStr);
988+
String largeMessagePointer = storeOriginalPayload(messageContentStr);
988989
sendMessageRequestBuilder.messageBody(largeMessagePointer);
989990

990991
return sendMessageRequestBuilder.build();
991992
}
992993

994+
private String storeOriginalPayload(String messageContentStr) {
995+
String s3KeyPrefix = clientConfiguration.getS3KeyPrefix();
996+
if (StringUtils.isBlank(s3KeyPrefix)) {
997+
return payloadStore.storeOriginalPayload(messageContentStr);
998+
}
999+
return payloadStore.storeOriginalPayload(messageContentStr, s3KeyPrefix + UUID.randomUUID());
1000+
}
1001+
9931002
private Map<String, MessageAttributeValue> updateMessageAttributePayloadSize(
9941003
Map<String, MessageAttributeValue> messageAttributes, Long messageContentSize) {
9951004
Map<String, MessageAttributeValue> updatedMessageAttributes = new HashMap<>(messageAttributes);

src/main/java/com/amazon/sqs/javamessaging/ExtendedClientConfiguration.java

+34
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import software.amazon.awssdk.annotations.NotThreadSafe;
1919
import software.amazon.awssdk.services.s3.S3Client;
2020
import software.amazon.awssdk.services.s3.model.ObjectCannedACL;
21+
import software.amazon.awssdk.utils.StringUtils;
2122
import software.amazon.payloadoffloading.PayloadStorageConfiguration;
2223
import software.amazon.payloadoffloading.ServerSideEncryptionStrategy;
2324

@@ -32,6 +33,7 @@ public class ExtendedClientConfiguration extends PayloadStorageConfiguration {
3233
private boolean cleanupS3Payload = true;
3334
private boolean useLegacyReservedAttributeName = true;
3435
private boolean ignorePayloadNotFound = false;
36+
private String s3KeyPrefix;
3537

3638
public ExtendedClientConfiguration() {
3739
super();
@@ -43,6 +45,7 @@ public ExtendedClientConfiguration(ExtendedClientConfiguration other) {
4345
this.cleanupS3Payload = other.doesCleanupS3Payload();
4446
this.useLegacyReservedAttributeName = other.usesLegacyReservedAttributeName();
4547
this.ignorePayloadNotFound = other.ignoresPayloadNotFound();
48+
this.s3KeyPrefix = other.s3KeyPrefix;
4649
}
4750

4851
/**
@@ -128,6 +131,37 @@ public ExtendedClientConfiguration withIgnorePayloadNotFound(boolean ignorePaylo
128131
return this;
129132
}
130133

134+
/**
135+
* Sets a string that will be used as prefix of the S3 Key.
136+
*
137+
* @param s3KeyPrefix
138+
* A S3 key prefix value
139+
*/
140+
public void setS3KeyPrefix(String s3KeyPrefix) {
141+
this.s3KeyPrefix = StringUtils.trim(s3KeyPrefix);
142+
}
143+
144+
/**
145+
* Sets a string that will be used as prefix of the S3 Key.
146+
*
147+
* @param s3KeyPrefix
148+
* A S3 key prefix value
149+
*
150+
* @return the updated ExtendedClientConfiguration object.
151+
*/
152+
public ExtendedClientConfiguration withS3KeyPrefix(String s3KeyPrefix) {
153+
setS3KeyPrefix(s3KeyPrefix);
154+
return this;
155+
}
156+
157+
/**
158+
* Gets the S3 key prefix
159+
* @return the prefix value which is being used for compose the S3 key.
160+
*/
161+
public String getS3KeyPrefix() {
162+
return this.s3KeyPrefix;
163+
}
164+
131165
/**
132166
* Checks whether or not clean up large objects in S3 is enabled.
133167
*

src/test/java/com/amazon/sqs/javamessaging/AmazonSQSExtendedClientTest.java

+50
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,11 @@
1515

1616
package com.amazon.sqs.javamessaging;
1717

18+
import org.junit.jupiter.api.AfterEach;
1819
import org.junit.jupiter.api.BeforeEach;
1920
import org.junit.jupiter.api.Test;
2021
import org.mockito.ArgumentCaptor;
22+
import org.mockito.MockedStatic;
2123
import software.amazon.awssdk.awscore.AwsRequestOverrideConfiguration;
2224
import software.amazon.awssdk.core.ApiName;
2325
import software.amazon.awssdk.core.ResponseInputStream;
@@ -62,9 +64,11 @@
6264
import static org.junit.jupiter.api.Assertions.assertNull;
6365
import static org.junit.jupiter.api.Assertions.assertTrue;
6466
import static org.mockito.ArgumentMatchers.any;
67+
import static org.mockito.ArgumentMatchers.argThat;
6568
import static org.mockito.ArgumentMatchers.eq;
6669
import static org.mockito.Mockito.isA;
6770
import static org.mockito.Mockito.mock;
71+
import static org.mockito.Mockito.mockStatic;
6872
import static org.mockito.Mockito.never;
6973
import static org.mockito.Mockito.spy;
7074
import static org.mockito.Mockito.times;
@@ -82,11 +86,16 @@ public class AmazonSQSExtendedClientTest {
8286
private SqsClient extendedSqsWithDefaultKMS;
8387
private SqsClient extendedSqsWithGenericReservedAttributeName;
8488
private SqsClient extendedSqsWithDeprecatedMethods;
89+
private SqsClient extendedSqsWithS3KeyPrefix;
8590
private SqsClient mockSqsBackend;
8691
private S3Client mockS3;
92+
93+
private MockedStatic<UUID> uuidMockStatic;
8794
private static final String S3_BUCKET_NAME = "test-bucket-name";
8895
private static final String SQS_QUEUE_URL = "test-queue-url";
8996
private static final String S3_SERVER_SIDE_ENCRYPTION_KMS_KEY_ID = "test-customer-managed-kms-key-id";
97+
private static final String S3_KEY_PREFIX = "test-s3-key-prefix";
98+
private static final String S3_KEY_UUID = "test-s3-key-uuid";
9099

91100
private static final int LESS_THAN_SQS_SIZE_LIMIT = 3;
92101
private static final int SQS_SIZE_LIMIT = 262144;
@@ -101,6 +110,7 @@ public class AmazonSQSExtendedClientTest {
101110

102111
@BeforeEach
103112
public void setupClients() {
113+
uuidMockStatic = mockStatic(UUID.class);
104114
mockS3 = mock(S3Client.class);
105115
mockSqsBackend = mock(SqsClient.class);
106116
when(mockS3.putObject(isA(PutObjectRequest.class), isA(RequestBody.class))).thenReturn(null);
@@ -121,11 +131,25 @@ public void setupClients() {
121131

122132
ExtendedClientConfiguration extendedClientConfigurationDeprecated = new ExtendedClientConfiguration().withPayloadSupportEnabled(mockS3, S3_BUCKET_NAME);
123133

134+
ExtendedClientConfiguration extendedClientConfigurationWithS3KeyPrefix = new ExtendedClientConfiguration()
135+
.withPayloadSupportEnabled(mockS3, S3_BUCKET_NAME)
136+
.withS3KeyPrefix(S3_KEY_PREFIX);
137+
138+
UUID uuidMock = mock(UUID.class);
139+
when(uuidMock.toString()).thenReturn(S3_KEY_UUID);
140+
uuidMockStatic.when(UUID::randomUUID).thenReturn(uuidMock);
141+
124142
extendedSqsWithDefaultConfig = spy(new AmazonSQSExtendedClient(mockSqsBackend, extendedClientConfiguration));
125143
extendedSqsWithCustomKMS = spy(new AmazonSQSExtendedClient(mockSqsBackend, extendedClientConfigurationWithCustomKMS));
126144
extendedSqsWithDefaultKMS = spy(new AmazonSQSExtendedClient(mockSqsBackend, extendedClientConfigurationWithDefaultKMS));
127145
extendedSqsWithGenericReservedAttributeName = spy(new AmazonSQSExtendedClient(mockSqsBackend, extendedClientConfigurationWithGenericReservedAttributeName));
128146
extendedSqsWithDeprecatedMethods = spy(new AmazonSQSExtendedClient(mockSqsBackend, extendedClientConfigurationDeprecated));
147+
extendedSqsWithS3KeyPrefix = spy(new AmazonSQSExtendedClient(mockSqsBackend, extendedClientConfigurationWithS3KeyPrefix));
148+
}
149+
150+
@AfterEach
151+
public void tearDown() {
152+
uuidMockStatic.close();
129153
}
130154

131155
@Test
@@ -617,6 +641,32 @@ public void testWhenSendMessageWIthCannedAccessControlListDefined() {
617641
assertEquals(expected, captor.getValue().acl());
618642
}
619643

644+
@Test
645+
public void testWhenSendLargeMessageWithS3PrefixKeyDefined() {
646+
String messageBody = generateStringWithLength(MORE_THAN_SQS_SIZE_LIMIT);
647+
648+
SendMessageRequest messageRequest = SendMessageRequest.builder().queueUrl(SQS_QUEUE_URL).messageBody(messageBody).build();
649+
650+
extendedSqsWithS3KeyPrefix.sendMessage(messageRequest);
651+
652+
verify(mockS3, times(1)).putObject(
653+
argThat((PutObjectRequest obj) -> obj.key().equals(S3_KEY_PREFIX + S3_KEY_UUID)),
654+
isA(RequestBody.class));
655+
}
656+
657+
@Test
658+
public void testWhenSendLargeMessageWithUndefinedS3PrefixKey() {
659+
String messageBody = generateStringWithLength(MORE_THAN_SQS_SIZE_LIMIT);
660+
661+
SendMessageRequest messageRequest = SendMessageRequest.builder().queueUrl(SQS_QUEUE_URL).messageBody(messageBody).build();
662+
663+
extendedSqsWithDefaultConfig.sendMessage(messageRequest);
664+
665+
verify(mockS3, times(1)).putObject(
666+
argThat((PutObjectRequest obj) -> obj.key().equals(S3_KEY_UUID)),
667+
isA(RequestBody.class));
668+
}
669+
620670
private void testReceiveMessage_when_MessageIsLarge(String reservedAttributeName) {
621671
String pointer = new PayloadS3Pointer(S3_BUCKET_NAME, "S3Key").toJson();
622672
Message message = Message.builder()

src/test/java/com/amazon/sqs/javamessaging/ExtendedClientConfigurationTest.java

+19
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ public class ExtendedClientConfigurationTest {
3737
private static final String s3BucketName = "test-bucket-name";
3838
private static final String s3ServerSideEncryptionKMSKeyId = "test-customer-managed-kms-key-id";
3939
private static final ServerSideEncryptionStrategy serverSideEncryptionStrategy = ServerSideEncryptionFactory.customerKey(s3ServerSideEncryptionKMSKeyId);
40+
private static final String s3KeyPrefix = "test-s3-key-prefix";
4041

4142
@Test
4243
public void testCopyConstructor() {
@@ -164,4 +165,22 @@ public void testMessageSizeThreshold() {
164165
assertEquals(messageLength, extendedClientConfiguration.getPayloadSizeThreshold());
165166

166167
}
168+
169+
@Test
170+
public void testS3keyPrefix() {
171+
ExtendedClientConfiguration extendedClientConfiguration = new ExtendedClientConfiguration();
172+
173+
extendedClientConfiguration.withS3KeyPrefix(s3KeyPrefix);
174+
175+
assertEquals(s3KeyPrefix, extendedClientConfiguration.getS3KeyPrefix());
176+
}
177+
178+
@Test
179+
public void testTrimS3keyPrefix() {
180+
ExtendedClientConfiguration extendedClientConfiguration = new ExtendedClientConfiguration();
181+
182+
extendedClientConfiguration.withS3KeyPrefix(String.format(" %s ", s3KeyPrefix));
183+
184+
assertEquals(s3KeyPrefix, extendedClientConfiguration.getS3KeyPrefix());
185+
}
167186
}

0 commit comments

Comments
 (0)