Firing an SNS notification upon user registration

As we mentioned earlier, SNS is a very fundamental part of AWS that lets different parts of our software interact between each other via message passing. In SNS, you create topics and subscribe resources to them. Subscribers can be HTTP endpoints, Lambda functions, a mobile application, or you can even send SMS messages via SNS.

In this step, we will create an SNS topic for our user registration event and fire an event to that topic.

Let's start with adding our topic via the CloudFormation template. Add the following block to our Resources section:

"UserRegistrationSnsTopic": { 
 "Type": "AWS::SNS::Topic", 
  "Properties": { 
    "Subscription": [] 
  } 
} 

After deploying your application, you can navigate to https://console.aws.amazon.com/sns/v2/#/topics to see the created topic.

Before going further, let's try SNS in action. As we mentioned earlier, you can subscribe an HTTP endpoint to SNS. Let's use http://requestb.in/ to create a free HTTP POST bin that can show us any request coming to it. After entering the RequestBin website, click on the Create a RequestBin button to create a new request bin. In the next page, the URL for your sandbox will be shown. Copy it and go back to the SNS console. After selecting the topic, click on the Actions and Subscribe to topic buttons subsequently. Pick HTTP as the protocol and paste your RequestBin URL:

Now, go back to RequestBin, and you will see that SNS sent a POST message there. It is to confirm the subscription, and the SubscribeURL field in the incoming JSON will catch your attention. Copy this URL and paste to your browser to confirm the subscription. Now, your topic is subscribed by this fake HTTP endpoint, and you will see any message posted to this topic.

Now, back on the console, you can select your topic again and click on the Publish to Topic button. You can write any message in the text field and click on the Publish message button:


If you go back to RequestBin, you will see that SNS notified it and you can read your message there.

In our architecture, our user registration Lambda will publish the email address of the created user as a message, and this information will be available to the topic's subscribers.

Before we go any further with our code, we must first alter our Lambda's IAM permissions to allow us to publish to that topic.

Add the following block to the Statement array of LambdaCustomPolicy:

{ 
   "Effect": "Allow", 
   "Action": [ 
     "SNS:Publish" 
   ], 
   "Resource": [ 
     { 
       "Ref": "UserRegistrationSnsTopic" 
     } 
   ] 
}

Now, we have to pass the topic's ARN to the Lambda function as an environment variable. Add this environment variable to the environment variables of UserRegistrationLambda:

"UserRegistrationSnsTopic": { 
  "Ref":"UserRegistrationSnsTopic" 
} 

Now, we can add SNS SDK to user registration Lambda. Basically, add this dependency to the build.gradle file of lambda-userregistration:

compile group: 'com.amazonaws', name: 'aws-java-sdk-sns', version: '1.11.+' 

We can now add the required code to the Handler method of this Lambda:

private static final Logger LOGGER = Logger.getLogger(Handler.class); 
private AmazonSNSClient amazonSNSClient; 
 
@Inject 
public Handler setAmazonSNSClient(AmazonSNSClient amazonSNSClient) { 
   this.amazonSNSClient = amazonSNSClient; 
   return this; 
} 
 
private void notifySnsSubscribers(User user) { 
  try { 
     amazonSNSClient.publish(System.getenv("UserRegistrationSnsTopic"),
user.getEmail()); LOGGER.info("SNS notification sent for "+user.getEmail()); } catch (Exception anyException) { LOGGER.info("SNS notification failed for "+user.getEmail(),
anyException); } }

It is a very simple method, and note that we are injecting AmazonSNSClient via dependency injection with its default configuration. We might need a custom configured client, and in this case, we would have to configure it in our dependency injection module. However, right now, it is not in the scope of our book, so we will directly use the default configuration.

Finally, we can add this method to the current handleRequest method as follows:

@Override 
public RegistrationOutput handleRequest(RegistrationInput input, Context context) { 
  User createdUser = userService.registerNewUser(input.username, input.email); 
  notifySnsSubscribers(createdUser); 
  return new RegistrationOutput(createdUser); 
} 

Now, we can deploy our project and create a new user like we showed in the previous chapter. Open the RequestBin page again. You should be seeing that the registered user's email is there, published to the topic.