com.limemojito.test.sns.SnsSupport Maven / Gradle / Ivy
Show all versions of test-utilities Show documentation
/*
* Copyright 2011-2024 Lime Mojito Pty Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.limemojito.test.sns;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.limemojito.aws.sns.LocalstackSnsConfig;
import com.limemojito.test.sqs.SqsSupport;
import lombok.SneakyThrows;
import org.springframework.stereotype.Service;
import software.amazon.awssdk.services.sns.SnsClient;
import software.amazon.awssdk.services.sns.model.MessageAttributeValue;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* The SnsSupport class provides support for interacting with the Amazon Simple Notification Service (SNS).
* It allows creating and retrieving topics, subscribing queues to topics, and sending messages to topics.
*
* This class requires an instance of SqsSupport, SnsClient, and ObjectMapper to be passed to its constructor.
* These dependencies are used for various operations such as creating topics, subscribing queues to topics, and converting messages to JSON format.
*
* The SnsSupport class provides the following functionality:
*
* - Creating a topic in the SNS based on a given topic name, returning the ARN of the newly created topic.
* - Retrieving the ARN of a topic based on a given topic name.
* - Subscribing a queue to a topic, with an option to specify if the messages should be delivered as raw (unprocessed) messages.
* - Sending a message to a specified topic.
* - Converting and sending a message to a specified topic. The message is converted to JSON format using the provided ObjectMapper.
*
*
* To use the SnsSupport class, create an instance of it and pass the required dependencies to its constructor.
* Then, you can use the various methods provided by the class to interact with the SNS service.
*/
@Service
public class SnsSupport {
/**
* Represents the header key for the deduplication ID in a message sent to the Amazon Simple Notification Service (SNS).
* The deduplication ID is used to prevent duplicate messages from being sent to the same topic.
*/
public static final String HEADER_MESSAGE_DEDUPLICATION_ID = "message-deduplication-id";
/**
* Represents the header key for the message group ID.
* The message group ID is used to group messages that belong to the same message group
* when using Amazon Simple Notification Service (SNS).
*/
public static final String HEADER_MESSAGE_GROUP_ID = "message-group-id";
private final SqsSupport sqs;
private final SnsClient sns;
private final ObjectMapper mapper;
/**
* Represents support for interacting with the Amazon Simple Notification Service (SNS).
* This class provides methods for creating topics, retrieving ARNs, subscribing queues to topics, and sending messages to topics.
*
* @param sqs The SqsSupport object used for interacting with the Amazon Simple Queue Service (SQS).
* @param sns The SnsClient object used for interacting with the Amazon Simple Notification Service (SNS).
* @param mapper The ObjectMapper object used for converting messages to JSON format.
*/
public SnsSupport(SqsSupport sqs,
SnsClient sns,
ObjectMapper mapper) {
this.sqs = sqs;
this.sns = sns;
this.mapper = mapper;
}
/**
* Creates a topic in the Amazon Simple Notification Service (SNS) based on the given topic name.
* The topic name is used to generate an Amazon Resource Name (ARN) for the newly created topic.
*
* @param topicName the name of the topic
* @return the ARN of the newly created topic
*/
public String create(String topicName) {
return getArn(topicName);
}
/**
* Retrieves the Amazon Resource Name (ARN) of a topic in the Amazon Simple Notification Service (SNS) based on the given topic name.
* The topic name is used to identify the topic for which the ARN is retrieved.
*
* @param topicName the name of the topic
* @return the ARN of the specified topic
*/
public String getArn(String topicName) {
return LocalstackSnsConfig.createTopic(sns, topicName).topicArn();
}
/**
* Subscribes a queue to a topic in the Amazon Simple Notification Service (SNS). Raw message delivery is defaulted
* to false.
*
* @param topicName The name of the topic to subscribe to.
* @param queueName The name of the queue to subscribe.
*/
public void subscribe(String topicName, String queueName) {
subscribe(topicName, queueName, false);
}
/**
* Subscribes a queue to a topic in the Amazon Simple Notification Service (SNS), allowing the queue
* to receive messages from the specified topic.
*
* Queue will be created if it does not exist.
*
* @param topicName The name of the topic to subscribe to.
* @param queueName The name of the queue to subscribe.
* @param rawMessageDelivery Specifies whether the messages received by the subscribed queue should
* be delivered as raw (unprocessed) messages.
*/
public void subscribe(String topicName, String queueName, boolean rawMessageDelivery) {
final String arn = create(topicName);
sqs.create(queueName);
final String queueArn = sqs.getQueueArn(queueName);
sns.subscribe(r -> r.topicArn(arn)
.endpoint(queueArn)
.protocol("sqs")
.attributes(Map.of("RawMessageDelivery", Boolean.toString(rawMessageDelivery))));
}
/**
* Sends a message to the specified topic in the Amazon Simple Notification Service (SNS).
*
* @param topicName the name of the topic to send the message to
* @param body the content of the message
*/
public void send(String topicName, String body) {
convertAndSend(topicName, body);
}
/**
* Sends a message to the specified topic in the Amazon Simple Notification Service (SNS).
*
* @param topicName the name of the topic to send the message to
* @param message the content of the message
*/
public void convertAndSend(String topicName, Object message) {
convertAndSend(topicName, message, null);
}
/**
* Converts and sends a message to the specified topic in the Amazon Simple Notification Service (SNS).
* The message is converted to JSON format using the provided ObjectMapper.
*
* @param topicName the name of the topic to send the message to
* @param message the content of the message to send
* @param attributeValues a Map containing additional attributes to include in the SNS message,
* where the key is the attribute name and the value is the attribute value
*/
@SneakyThrows
public void convertAndSend(String topicName, Object message, Map attributeValues) {
String json = mapper.writeValueAsString(message);
sns.publish(b -> {
b.topicArn(getArn(topicName)).message(json);
if (attributeValues != null) {
Map attributes = new LinkedHashMap<>();
for (String key : attributeValues.keySet()) {
String value = attributeValues.get(key).toString();
attributes.put(key,
MessageAttributeValue.builder()
.stringValue(value)
.dataType("String")
.build());
if (HEADER_MESSAGE_DEDUPLICATION_ID.equals(key)) {
b.messageDeduplicationId(value);
attributes.remove(key);
}
if (HEADER_MESSAGE_GROUP_ID.equals(key)) {
b.messageGroupId(value);
attributes.remove(key);
}
}
b.messageAttributes(attributes);
}
});
}
}