Dropwizard AWS LocalStack Tutorial

Dropwizard AWS LocalStack Tutorial

Introduction

        Dropwizard is one of the most popular frameworks used today for building microservices. I was looking for a simple Dropwizard AWS LocalStack Tutorial online, but there are a very few tutorials. Some are very tough to follow. Hence I decided to come up with a simple post on this topic.
        In this tutorial, we will focus on creating a Dropwizard App and integrating it with AWS SQS(Simple Queue Service) and SNS(Simple Notification Service). Then we will make a SQS Queue to subscribe to a SNS Topic, publish a message on the topic and retrieve it on the SQS Queue.

LocalStack

        LocalStack is a fully functional local cloud stack. With LocalSatck, you can run your AWS Applications or Lambdas on your local machine without connecting to a remote cloud provider. To know more about LocalStack please visit their website.

I am assuming that you have a Basic Knowledge of Dropwizard and have a Basic Dropwizard Application running in your machine. If not, please check my blog post on Basic Dropwizard Application by going to the link: Dropwizard Tutorial.

Requirements to Run the Application:
  1. Java
  2. Maven
  3. LocalStack
  4. AWS CLI
  5. IDE of your choice
LocalStack and AWS CLI should be setup and running in your machine. To setup, run and test if LocalStack and AWS CLI are working fine, please refer to my post on: LocalStack and AWS CLI Setup.

Once you have a Basic Dropwizard Application and LocalStack up and running in your machine, here are the additional steps required to add the AWS integration.

Step 1: Maven Dependencies to be added in pom.xml

Add AWS Java SDK to the project by using the following dependency in the pom.xml:
        <dependency>
            <groupId>com.amazonaws</groupId>
            <artifactId>aws-java-sdk</artifactId>
            <version>${amazonaws.version}</version>
        </dependency>
  
Here is the full pom.xml:
  <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.aj.dropwizardaws</groupId>
	<artifactId>DropwizardAWS</artifactId>
	<version>1.0.0</version>


	<properties>
		<dropwizard.version>2.0.25</dropwizard.version>
        <amazonaws.version>1.12.62</amazonaws.version>
		<jackson.version>2.12.5</jackson.version>
        <jdk.version>1.8</jdk.version>
		<packaging>jar</packaging>
	</properties>

	<dependencies>

		<dependency>
            <groupId>io.dropwizard</groupId>
            <artifactId>dropwizard-core</artifactId>
            <version>${dropwizard.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>com.fasterxml.jackson.core</groupId>
                    <artifactId>jackson-databind</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>com.amazonaws</groupId>
            <artifactId>aws-java-sdk</artifactId>
            <version>${amazonaws.version}</version>
        </dependency>

        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-collections4</artifactId>
            <version>4.1</version>
            <exclusions>
                <exclusion>
                    <groupId>com.fasterxml.jackson.core</groupId>
                    <artifactId>jackson-databind</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>${jackson.version}</version>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>${jackson.version}</version>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>${jackson.version}</version>
        </dependency>

	</dependencies>

	<build>
		<plugins>
			<plugin>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.0</version>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-jar-plugin</artifactId>
				<version>2.4</version>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-shade-plugin</artifactId>
				<version>2.3</version>
				<configuration>
					<createDependencyReducedPom>true</createDependencyReducedPom>
					<filters>
						<filter>
							<artifact>*:*</artifact>
							<excludes>
								<exclude>META-INF/*.SF</exclude>
								<exclude>META-INF/*.DSA</exclude>
								<exclude>META-INF/*.RSA</exclude>
							</excludes>
						</filter>
					</filters>
				</configuration>
				<executions>
					<execution>
						<phase>package</phase>
						<goals>
							<goal>shade</goal>
						</goals>
						<configuration>
							<transformers>
								<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
								<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
									<mainClass>com.aj.dropwizardaws.DropwizardAWSApplication</mainClass>
								</transformer>
							</transformers>
						</configuration>
					</execution>
				</executions>
			    </plugin>
		         </plugins>
	              </build>
                   </project> 

Step 2: AWS Managed Object

Most services involve objects which need to be started and stopped: thread pools, database connections, etc. Dropwizard provides the Managed interface for this. Managed interface is a powerful and very useful concept that you should be aware of in Dropwizard. You can either have the class in question implement the start() and stop() methods, or write a wrapper class which does so. Adding a Managed instance to your service’s Environment ties that object’s lifecycle to that of the service’s HTTP server. Before the server starts, the start() method is called. After the server has stopped (and after its graceful shutdown period) the stop() method is called. We will configure AWS  as a Managed object. The code required to do that is present in AWSManaged.java. Here is the code:
  package com.aj.dropwizardaws;

  import com.amazonaws.AmazonWebServiceClient;
  import io.dropwizard.lifecycle.Managed;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;

  public class AWSManaged implements Managed {

      private static final Logger logger = LoggerFactory.getLogger(AWSManaged.class);

      private AmazonWebServiceClient awsClient;

      private AWSManaged() {
          // Prevent instantiation
      }

      public AWSManaged(AmazonWebServiceClient awsClient) {
          if (awsClient == null) {
              throw new IllegalArgumentException("AWS client cannot be null");
          }
          this.awsClient = awsClient;
      }

      @Override
      public void start() throws Exception {
      }

      @Override
      public void stop() throws Exception {
          logger.info("Shutting down AWS client, " + awsClient.getClass());
          awsClient.shutdown();
      }
  }

Step 3: Object Classes

There are two object classes for SNS Request object and SQS Request Object.
Here is AmazonSNSRequest.java:
package com.aj.dropwizardaws.domain;

public class AmazonSNSRequest {

    private String topicArn;
    private String message;
    private String subject;
    private String queueUrl;

    public String getTopicArn() {
        return topicArn;
    }

    public void setTopicArn(String topicArn) {
        this.topicArn = topicArn;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public String getSubject() {
        return subject;
    }

    public void setSubject(String subject) {
        this.subject = subject;
    }

    public String getQueueUrl() {
        return queueUrl;
    }

    public void setQueueUrl(String queueUrl) {
        this.queueUrl = queueUrl;
    }

    @Override
    public String toString() {
        return "AmazonSNSRequest{" +
                "topicArn='" + topicArn + '\'' +
                ", message='" + message + '\'' +
                ", subject='" + subject + '\'' +
                ", queueUrl='" + queueUrl + '\'' +
                '}';
    }
}
Here is AmazonSQSRequest.java:
package com.aj.dropwizardaws.domain;

import com.amazonaws.services.sqs.model.MessageAttributeValue;

import java.util.Map;

public class AmazonSQSRequest {

    private String queueUrl;
    private String messageBody;
    private int delaySeconds;
    private Map<String, MessageAttributeValue> messageAttributes;

    public String getQueueUrl() {
        return queueUrl;
    }

    public void setQueueUrl(String queueUrl) {
        this.queueUrl = queueUrl;
    }

    public String getMessageBody() {
        return messageBody;
    }

    public void setMessageBody(String messageBody) {
        this.messageBody = messageBody;
    }

    public int getDelaySeconds() {
        return delaySeconds;
    }

    public void setDelaySeconds(int delaySeconds) {
        this.delaySeconds = delaySeconds;
    }

    public Map<String, MessageAttributeValue> getMessageAttributes() {
        return messageAttributes;
    }

    public void setMessageAttributes(Map<String, MessageAttributeValue> messageAttributes) {
        this.messageAttributes = messageAttributes;
    }

    @Override
    public String toString() {
        return "AmazonSQSRequest{" +
                "queueUrl='" + queueUrl + '\'' +
                ", messageBody='" + messageBody + '\'' +
                ", delaySeconds=" + delaySeconds +
                ", messageAttributes=" + messageAttributes +
                '}';
    }
}

Step 4: API Resources

There are 2 API resources, one for SQS and one for SNS.
Here are the APIs in the SQS API class:
  1. Create Queue
  2. List Queues
  3. Send Message
  4. Receive Message
Here is AmazonSQSResource.java:
  package com.aj.dropwizardaws.resource;

  import com.aj.dropwizardaws.domain.AmazonSQSRequest;
  import com.amazonaws.services.sqs.AmazonSQS;
  import com.amazonaws.services.sqs.model.*;
  import com.codahale.metrics.annotation.Timed;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;

  import javax.ws.rs.*;
  import javax.ws.rs.core.MediaType;
  import javax.ws.rs.core.Response;
  import java.util.*;

  @Path("/amazonSQS")
  @Produces(MediaType.APPLICATION_JSON)
  public class AmazonSQSResource {

      private static AmazonSQS amazonSQS;

      public AmazonSQSResource(AmazonSQS builtSQS) {
          amazonSQS = builtSQS;
      }

      private static final Logger logger = LoggerFactory.getLogger(AmazonSQSResource.class);

      @Path("/createQueue/{sqsQueueName}")
      @Timed
      @GET
      @Produces(MediaType.APPLICATION_JSON)
      public Response createQueue(@PathParam("sqsQueueName") String sqsQueueName) {
          logger.info("SQS Queue Name is: {}", sqsQueueName);
          CreateQueueRequest request = new CreateQueueRequest().withQueueName(sqsQueueName);
          CreateQueueResult result = amazonSQS.createQueue(request);
          Map<String, String> response = new HashMap<>();
          response.put("queueUrl", result.getQueueUrl());
          return Response.ok(response).build();
      }

      @Path("/listQueues")
      @Timed
      @GET
      @Produces(MediaType.APPLICATION_JSON)
      public Response listQueues() {
          List<String> queueUrls = amazonSQS.listQueues().getQueueUrls();
          Map<String, List<String>> response = new HashMap<>();
          response.put("sqsQueueURLs", queueUrls);
          return Response.ok(response).build();
      }

      @Path("/sendMessage")
      @POST
      @Timed
      @Produces(MediaType.APPLICATION_JSON)
      @Consumes(MediaType.APPLICATION_JSON)
      public Response send(AmazonSQSRequest amazonSQSRequest) {
          logger.info("Request received is: {}", amazonSQSRequest.toString());
          SendMessageRequest sendMessageStandardQueue = new SendMessageRequest()
                  .withQueueUrl(amazonSQSRequest.getQueueUrl())
                  .withMessageBody(amazonSQSRequest.getMessageBody())
                  .withDelaySeconds(amazonSQSRequest.getDelaySeconds())
                  .withMessageAttributes(amazonSQSRequest.getMessageAttributes());
          amazonSQS.sendMessage(sendMessageStandardQueue);
          Map<String, String> response = new HashMap<>();
          response.put("message", "Message sent");
          return Response.ok(response).build();
      }

      @Path("/receiveMessage")
      @POST
      @Timed
      @Produces(MediaType.APPLICATION_JSON)
      @Consumes(MediaType.APPLICATION_JSON)
      public Response receiveMessage(AmazonSQSRequest amazonSQSRequest) {
          logger.info("Request received is: {}", amazonSQSRequest.toString());
          Map<String, List<Message>> response = new HashMap<>();
          List<Message> messages = amazonSQS.receiveMessage(new ReceiveMessageRequest(amazonSQSRequest.
                  getQueueUrl()).withAttributeNames("All").withMessageAttributeNames("All")).getMessages();
          logger.info("Number of messages are: {}", messages.size());
          response.put("message", messages);
          return Response.ok(response).build();
      }
  }
  
Here are the APIs in the SNS API class:
  1. Create Topic
  2. Get Topics
  3. Subscribe Queue
  4. Get Subscriptions
  5. Publish Message
Here is AmazonSNSResource.java:
  package com.aj.dropwizardaws.resource;

  import com.aj.dropwizardaws.domain.AmazonSNSRequest;
  import com.amazonaws.services.sns.AmazonSNS;
  import com.amazonaws.services.sns.model.*;
  import com.amazonaws.services.sns.util.Topics;
  import com.amazonaws.services.sqs.AmazonSQS;
  import com.codahale.metrics.annotation.Timed;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;

  import javax.ws.rs.*;
  import javax.ws.rs.core.MediaType;
  import javax.ws.rs.core.Response;
  import java.util.HashMap;
  import java.util.List;
  import java.util.Map;

  @Path("/amazonSNS")
  @Produces(MediaType.APPLICATION_JSON)
  public class AmazonSNSResource {

      private static AmazonSNS amazonSNS;
      private static AmazonSQS amazonSQS;

      public AmazonSNSResource(AmazonSNS builtSNS, AmazonSQS builtSQS) {
          amazonSNS = builtSNS;
          amazonSQS = builtSQS;
      }

      private static final Logger logger = LoggerFactory.getLogger(AmazonSNSResource.class);

      @Path("/createTopic/{snsTopicName}")
      @Timed
      @GET
      @Produces(MediaType.APPLICATION_JSON)
      public Response createTopic(@PathParam("snsTopicName") String snsTopicName) {
          logger.info("SNS Topic Name is: {}", snsTopicName);
          CreateTopicRequest request = new CreateTopicRequest()
                      .withName(snsTopicName);
          CreateTopicResult result = amazonSNS.createTopic(request);
          Map<String, String> response = new HashMap<>();
          response.put("topicArn", result.getTopicArn());
          return Response.ok(response).build();
      }

      @Path("/getTopics")
      @Timed
      @GET
      @Produces(MediaType.APPLICATION_JSON)
      public Response getTopics() {
          List<Topic> topics = amazonSNS.listTopics().getTopics();
          Map<String, List<Topic>> response = new HashMap<>();
          response.put("snsTopics", topics);
          return Response.ok(response).build();
      }

      @Path("/subscribeQueue")
      @Timed
      @POST
      @Produces(MediaType.APPLICATION_JSON)
      @Consumes(MediaType.APPLICATION_JSON)
      public Response subscribeQueue(AmazonSNSRequest amazonSNSRequest) {
          logger.info("Request received is: {}", amazonSNSRequest.toString());
          Topics.subscribeQueue(amazonSNS, amazonSQS, amazonSNSRequest.getTopicArn(), amazonSNSRequest.getQueueUrl());
          Map<String, String> response = new HashMap<>();
          response.put("message", "SQS Queue is subscribed to SNS Topic successfully");
          return Response.ok(response).build();
      }

      @Path("/getSubscriptions")
      @Timed
      @GET
      @Produces(MediaType.APPLICATION_JSON)
      public Response getSubscriptions() {
          List<Subscription> subscriptions = amazonSNS.listSubscriptions().getSubscriptions();
          Map<String, List<Subscription>> response = new HashMap<>();
          response.put("snsSubscriptions", subscriptions);
          return Response.ok(response).build();
      }

      @Path("/publish")
      @POST
      @Timed
      @Produces(MediaType.APPLICATION_JSON)
      @Consumes(MediaType.APPLICATION_JSON)
      public Response publish(AmazonSNSRequest amazonSNSRequest) {
          logger.info("Request received is: {}", amazonSNSRequest.toString() );
          PublishRequest publishRequest = new PublishRequest(amazonSNSRequest.getTopicArn(), amazonSNSRequest.getMessage())
                  .withSubject(amazonSNSRequest.getSubject());
          PublishResult publishResult = amazonSNS.publish(publishRequest);
          Map<String, String> response = new HashMap<>();
          response.put("Message published successfully. Message ID is: ", publishResult.getMessageId());
          return Response.ok(response).build();
      }
  } 

Step 5: Create the Application Class 

Everything comes together in the application class. We register the resources, health check and AWS Managed Object in the application class. The SNS and SQS entry points are initialized in the Application class using the LocalStack AccessKey and SecretKey. We use the Docker Host IP address and LocalStack runs on the port 4566. Using these details the service end point is derived. The SQSClient and SNSClient are built with all these details. The code is present in the Application class. Here is DropwizardAWSApplication.java:
    package com.aj.dropwizardaws;

    import com.aj.dropwizardaws.resource.AmazonSNSResource;
    import com.aj.dropwizardaws.resource.AmazonSQSResource;
    import com.aj.dropwizardaws.resource.DropwizardAWSHealthCheckResource;
    import com.aj.dropwizardaws.resource.PingResource;
    import com.amazonaws.AmazonWebServiceClient;
    import com.amazonaws.auth.AWSStaticCredentialsProvider;
    import com.amazonaws.auth.BasicAWSCredentials;
    import com.amazonaws.client.builder.AwsClientBuilder;
    import com.amazonaws.services.sns.AmazonSNS;
    import com.amazonaws.services.sns.AmazonSNSClientBuilder;
    import com.amazonaws.services.sqs.AmazonSQS;
    import com.amazonaws.services.sqs.AmazonSQSClientBuilder;
    import io.dropwizard.Application;
    import io.dropwizard.setup.Bootstrap;
    import io.dropwizard.setup.Environment;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;


    public class DropwizardAWSApplication extends Application<DropwizardAWSConfiguration> {

        private static final Logger logger = LoggerFactory.getLogger(DropwizardAWSApplication.class);

        public static void main(String[] args) throws Exception {
            new DropwizardAWSApplication().run("server", args[0]);
        }

        @Override
        public void initialize(Bootstrap<DropwizardAWSConfiguration> b) {
        }

        @Override
        public void run(DropwizardAWSConfiguration config, Environment env) {
            BasicAWSCredentials awsCreds = new BasicAWSCredentials("ajtechdeveloper", "softwaredevelopercentral");
            logger.info("Initialize Amazon SNS entry point");
            AmazonSNS sns = AmazonSNSClientBuilder.standard().
                    withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration("http://192.168.99.100:4566", "us-east-1")).
                    withCredentials(new AWSStaticCredentialsProvider(awsCreds)).
                    build();
            env.lifecycle().manage(new AWSManaged((AmazonWebServiceClient) sns));
            logger.info("Initialize Amazon SQS entry point");
            AmazonSQS sqs = AmazonSQSClientBuilder.standard().
                    withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration("http://192.168.99.100:4566", "us-east-1")).
                    withCredentials(new AWSStaticCredentialsProvider(awsCreds)).
                    build();
            env.lifecycle().manage(new AWSManaged((AmazonWebServiceClient) sqs));
            logger.info("Registering RESTful API resources");
            env.jersey().register(new PingResource());
            env.jersey().register(new AmazonSQSResource(sqs));
            env.jersey().register(new AmazonSNSResource(sns, sqs));
            env.healthChecks().register("DropwizardAWSHealthCheck",
                    new DropwizardAWSHealthCheckResource(config));
        }
    }

Project Setup:

For Java Setup, please refer to:  Java Setup
For Maven Setup, please refer to: Maven Setup
For Git and Project Setup, please refer to: Git and Project Setup

Run Application:

1. To run application in your IDE use:
    Program arguments: src/main/resources/dropwizardaws.yml
2. To run JAR from command prompt:
     Build jar by using command:   
   mvn clean install
     Run JAR by using command in Project folder location:
   java -jar target\DropwizardAWS-1.0.0.jar src\main\resources\dropwizardaws.yml

API calls and results:

1. Create Queue
 
2. List Queues
    Response:
    {
    "sqsQueueURLs": [
        "http://localhost:4566/000000000000/messageQueue"
    ]
    }
  

3. Send Message
    Body: 
    {
     "queueUrl": "http://192.168.99.100:4566/000000000000/messageQueue",
     "messageBody": "Simple message.",
     "delaySeconds": 5,
     "messageAttributes":{
     "Attribute1": {
        "stringValue": "An attribute",
        "dataType": "String"
    },
     "Attribute2": {
        "stringValue": "Another attribute",
        "dataType": "String"
     }
    }
   }
4. Create Topic

5. Get Topics  
    Response:
  {
    "snsTopics": [
        {
            "topicArn": "arn:aws:sns:us-east-1:000000000000:messageTopic"
        }
    ]
  }
  
6. Subscribe Queue
    Body: 
    {
      "topicArn": "arn:aws:sns:us-east-1:000000000000:messageTopic",
      "queueUrl": "http://192.168.99.100:4566/000000000000/messageQueue"
    }
7. Get Subscriptions
     Response: 
    {
    "snsSubscriptions": [
        {
            "subscriptionArn": "arn:aws:sns:us-east-1:000000000000:messageTopic:eff8e2f7-5cf7-4914-8a76-3c5eafe8d4ed",
            "owner": "",
            "protocol": "sqs",
            "endpoint": "arn:aws:sqs:us-east-1:000000000000:messageQueue",
            "topicArn": "arn:aws:sns:us-east-1:000000000000:messageTopic"
        }
    ]
}
8. Publish Message
    Body: 
    {
     "topicArn": "arn:aws:sns:us-east-1:000000000000:messageTopic",
     "message": "Message on SNS: Message Topic",
     "subject": "Message Subject"
    }
9. Receive Message
    Body: 
    {
 	"queueUrl": "http://192.168.99.100:4566/000000000000/messageQueue"
    }
  
    Response 1: Message from SQS
    {
    "message": [
        {
            "messageId": "ba63d6f1-1160-b01d-a1a9-5950422de93b",
            "receiptHandle": "ujhsudvtlfyokckqqhtprbzvyvbascjcutfqxdtgtoxpirvsdapvpayhzitfcrzqycuygvhlnhuzjsmbclroeezcxspzypthujkgicfwcmrqcszslrbycmxqxvhooejmwytaesozuzxslqggmfpbwampqkcfoywmumhkuiddafgtnttdhqrgtzdrm",
            "body": "Simple message.",
            "attributes": {
                "ApproximateReceiveCount": "1",
                "SentTimestamp": "1631011444823",
                "SenderId": "AIDAIT2UOQQY3AUEKVGXU",
                "ApproximateFirstReceiveTimestamp": "1631011465975"
            },
            "messageAttributes": {
                "Attribute2": {
                    "stringValue": "Another attribute",
                    "binaryValue": null,
                    "stringListValues": [],
                    "binaryListValues": [],
                    "dataType": "String"
                },
                "Attribute1": {
                    "stringValue": "An attribute",
                    "binaryValue": null,
                    "stringListValues": [],
                    "binaryListValues": [],
                    "dataType": "String"
                }
            },
            "md5OfMessageAttributes": "3993451abc49ee6de6c7df6f9163e8de",
            "md5OfBody": "e4db76f198a5b568108dfbf6b22a01eb"
            }
        ]
    }
    Response 2: Message from SNS
  {
    "message": [
        {
            "messageId": "0746bb54-71c8-fa23-b6f4-7687afec30b1",
            "receiptHandle": "sbvjggzvehdccfrdzcamicotyntdrfjlbdvliepuffqcfmnshidxpmdlqldtgsvynxiretajviblhgczibspjmivmsgxexanhjaaedecoucuhxxljdozriaoqedmomxllpvxbdbtaxdmaqxafeynmcvgsjwtaweikyvaxwcyiitgiruubctgjzqxj",
            "body": "{\"Type\": \"Notification\", \"MessageId\": \"a8b20ccb-aca3-475a-aa68-1a26f5c7b79c\", \"TopicArn\": \"arn:aws:sns:us-east-1:000000000000:messageTopic\", \"Message\": \"Message on SNS: Message Topic\", \"Timestamp\": \"2021-09-06T23:23:21.933Z\", \"SignatureVersion\": \"1\", \"Signature\": \"EXAMPLEpH+..\", \"SigningCertURL\": \"https://sns.us-east-1.amazonaws.com/SimpleNotificationService-0000000000000000000000.pem\", \"Subject\": \"Message Subject\"}",
            "attributes": {
                "ApproximateReceiveCount": "7",
                "SentTimestamp": "1630970602041",
                "MessageGroupId": "",
                "SenderId": "AIDAIT2UOQQY3AUEKVGXU",
                "ApproximateFirstReceiveTimestamp": "1630971531659"
            },
            "messageAttributes": {},
            "md5OfMessageAttributes": null,
            "md5OfBody": "87df4be88a67a73aa4dcd9802da25a65"
        }
    ]
  }
  
Other than these APIs, this application has the following APIs:

1. GET API for Application Health Check:
http://localhost:4000/admin/healthcheck
2. GET API to Ping and test if the application is up and running: 
    http://localhost:4000/ping
3. POST API to Ping and test if the application is up and running: 
    http://localhost:4000/ping
    JSON Request Body:
    {
     "input": "ping"
    }
4. GET Admin API to see application metrics: Dropwizard provides this Admin API. As I have set adminContextPath as: /admin in dropwizardmongodb.yml the link I need to use in any browser is: http://localhost:4000/admin/
You can click on individual links on this page to see different application metrics.

Conclusion and GitHub link:

    This tutorial gives a comprehensive overview of Dropwizard, LocalStack and integration with AWS SQS and SNS. The code for the application used in this post is available on GitHub
    Learn the most popular and trending technologies like Blockchain, Cryptocurrency, Machine Learning, Chatbots, Internet of Things (IoT), Big Data Processing, Elastic Stack, React, Highcharts, Progressive Web Application (PWA), Angular, gRPC, GraphQL, Golang, Akka HTTP, Play Framework, Dropwizard, Docker, Netflix Eureka, Netflix Zuul, Spring Cloud, Spring Boot, Flask and RESTful Web Service integration with MongoDB, Kafka, Redis, Aerospike, MySQL DB in simple steps by reading my most popular blog posts at Software Developer Central.   
    If you like my post, please feel free to share it using the share button just below this paragraph or next to the heading of the post. You can also tweet with #SoftwareDeveloperCentral on Twitter. To get a notification on my latest posts or to keep the conversation going, you can follow me on Twitter or Instagram. Please leave a note below if you have any questions or comments.

Comments

Popular Posts

Dropwizard MySQL Integration Tutorial

Asynchronous Processing (@Async) in Spring Boot

Send Email in Java