Skip to content

Commit

Permalink
Add SnsTemplate#topicExists to check with given ARN exists (#1142)
Browse files Browse the repository at this point in the history
Fixes #1137
  • Loading branch information
hardikSinghBehl committed Sep 18, 2024
1 parent 0ab9af7 commit cf4349a
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 1 deletion.
6 changes: 5 additions & 1 deletion docs/src/main/asciidoc/sns.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ public class TopicArnResolverConfiguration {
----

However, when using the topic ARN in your application, the `SnsTemplate` provides a `topicExists` method to validate the existence of the SNS topic at application startup itself.

==== SNS Operations

Because of Spring Messaging compatibility, `SnsTemplate` exposes many methods that you may not need if you don't need Spring Messaging abstractions.
Expand Down Expand Up @@ -235,6 +237,7 @@ Following IAM permissions are required by Spring Cloud AWS:
| To publish notification you will also need | `sns:ListTopics`
| To use Annotation-driven HTTP notification endpoint | `sns:ConfirmSubscription`
| For resolving topic name to ARN | `sns:CreateTopic`
| For validating topic existence by ARN | `sns:GetTopicAttributes`
|===

Sample IAM policy granting access to SNS:
Expand All @@ -248,7 +251,8 @@ Sample IAM policy granting access to SNS:
"Effect": "Allow",
"Action": [
"sns:Publish",
"sns:ConfirmSubscription"
"sns:ConfirmSubscription",
"sns:GetTopicAttributes"
],
"Resource": "yourArn"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
* High level SNS operations.
*
* @author Maciej Walkowiak
* @author Hardik Singh Behl
* @since 3.0
*/
public interface SnsOperations {
Expand All @@ -30,4 +31,12 @@ public interface SnsOperations {
* @param notification - the notification
*/
void sendNotification(String topic, SnsNotification<?> notification);

/**
* Checks if topic with given ARN exists.
*
* @param topicArn - ARN of the topic
* @return true if topic exists, false otherwise
*/
boolean topicExists(String topicArn);
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import org.springframework.util.Assert;
import software.amazon.awssdk.arns.Arn;
import software.amazon.awssdk.services.sns.SnsClient;
import software.amazon.awssdk.services.sns.model.NotFoundException;

/**
* Helper class that simplifies synchronous sending of notifications to SNS. The only mandatory fields are
Expand All @@ -42,6 +43,7 @@
* @author Alain Sahli
* @author Matej Nedic
* @author Mariusz Sondecki
* @author Hardik Singh Behl
* @since 1.0
*/
public class SnsTemplate extends AbstractMessageSendingTemplate<TopicMessageChannel>
Expand Down Expand Up @@ -151,6 +153,17 @@ public void addChannelInterceptor(ChannelInterceptor channelInterceptor) {
public void sendNotification(String topic, SnsNotification<?> notification) {
this.convertAndSend(topic, notification.getPayload(), notification.getHeaders());
}

@Override
public boolean topicExists(String topicArn) {
Assert.notNull(topicArn, "topicArn must not be null");
try {
snsClient.getTopicAttributes(request -> request.topicArn(topicArn));
} catch (NotFoundException exception) {
return false;
}
return true;
}

private TopicMessageChannel resolveMessageChannelByTopicName(String topicName) {
Arn topicArn = this.topicArnResolver.resolveTopicArn(topicName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
import io.awspring.cloud.sns.core.SnsTemplate;
import io.awspring.cloud.sns.core.TopicNotFoundException;
import io.awspring.cloud.sns.core.TopicsListingTopicArnResolver;
import net.bytebuddy.utility.RandomString;

import java.util.HashMap;
import java.util.Map;
import org.junit.jupiter.api.AfterEach;
Expand Down Expand Up @@ -51,6 +53,7 @@
* Integration tests for {@link SnsTemplate}.
*
* @author Matej Nedic
* @author Hardik Singh Behl
*/
@Testcontainers
class SnsTemplateIntegrationTest {
Expand Down Expand Up @@ -203,5 +206,25 @@ private static void createTopics() {
}
}
}

@Test
void shouldReturnFalseForNonExistingTopic() {
String nonExistentTopicArn = String.format("arn:aws:sns:us-east-1:000000000000:%s", RandomString.make());

boolean response = snsTemplate.topicExists(nonExistentTopicArn);

assertThat(response).isFalse();
}

@Test
void shouldReturnTrueForExistingTopic() {
String topicName = RandomString.make();
snsClient.createTopic(request -> request.name(topicName));
String topicArn = String.format("arn:aws:sns:us-east-1:000000000000:%s", topicName);

boolean response = snsTemplate.topicExists(topicArn);

assertThat(response).isTrue();
}

}

0 comments on commit cf4349a

Please sign in to comment.