Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

SnsTemplate provides functionality to validate topic existence (#1137) #1142

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ mail.properties
.project
.classpath
.settings/
.DS_Store
hardikSinghBehl marked this conversation as resolved.
Show resolved Hide resolved

.vscode/

Expand Down
Binary file removed docs/src/main/.DS_Store
Binary file not shown.
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();
}

}
Loading