AmazonSQS Third Party Integration with Twillio SMS

Read Time 4 mins | Written by: Chris(Chang) Xu

Twilip

Problem:

In this blog, we will try to introduce how to use Twilio API to send the verification code to the customer’s mobile device. Since our application was built on top of spring and AWS, we will also explain how to integrate Twilio with Spring-MVC and deploy to AWS.

Challenges:

There are a couple of difficulties during the implementing process including:

  1. Micro-Service Containerization.
  2. Integrate and Optimize Twilio APIs in Spring-MVC.
  3. Unit Test with Mockito for Third Party Integration.

Micro-Service Containerization:

The Micro-Service Containerization process would involve modularization and dependency injection in a sense to improve the scalability. There are two reasons for us to process Twilio APIs on different modular;

1. The waiting time would be longer if we use the idea of monolithic for the services. For example, if we send 10 messages simultaneously, we need to wait until the server complete the sequential request then we are able to send the next request. If we process these requests in parallel, we can improve response time and user experience.

2. When 10,000 clients try to send the messages at the same time, we need containers to handle those requests. Thus, the event-driven design would be ideal in this case. We can toss events to JMS, and scale up workers to pick up events.  We can also scale as many as worker needed.

Dependency Installation:

First of all, we would add maven dependency for the MVC and worker modules which ensure the core module information be available for every module. By this maven dependency, we conduct a jar file contains core information.

<dependency>
      <groupId>${project.groupId}</groupId>
      <version>${project.version}</version>
      <artifactId>core</artifactId>
</dependency>

Secondly, we need to install this jar file to the MVC and Worker modules. We would use this command line (skip test is optional):

mvn clean compile install -DskipTests=true

Go through this process on the root folder or each separate folder. Finally, we need to import the Database configuration to MVC and Worker by using @Import annotation.

Event-Drive SQS:

We use the AmazonSQS to send the message to containers. In this case, the controller will send a message to SQS by using the sendMessage method. The sendMessage method including two arguments which are messageBody and delaySecond. It also requires a QueueUrl that comes from the AWS SQS queue, see reference for implementation of AmazonSQS.

public void sendMessage(String messageBody,Integer delaySecond){
        SendMessageRequest send_msg_request = new SendMessageRequest()
                .withQueueUrl(queueUrl)
                .withMessageBody(messageBody)
                .withDelaySeconds(delaySecond);
        sqs.sendMessage(send_msg_request);
    }

Then, the worker would receive the message from AmazonSQS with valid destination. As we send a map of messages, we will get the messages from the map and send the message to the correct client.

@JmsListener(destination ="queue.name")
    public void processMessage(String message){
        implementation for the messages;
    }

Integrate and Optimize Twilio APIs in Spring-MVC:

In this step, we would implement Twilio Configuration to the worker with an effectively method compare to the example code copied from Twilio Doc.

public class Example {
// Find your Account Sid and Token at twilio.com/console
      public static final String ACCOUNT_SID = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
      public static final String AUTH_TOKEN = "your_auth_token";
      public static void main(String[] args) {
          Twilio.init(ACCOUNT_SID, AUTH_TOKEN);
          Message message = Message.creator(
          new com.twilio.type.PhoneNumber("+1XXXXXXXXXX"),
          new com.twilio.type.PhoneNumber("+1XXXXXXXXXX"),
          "body")
          .create();
          System.out.println(message.getSid());
      }
}

We call our message sender class as ProcessServices. Follow the Twilio API instruction, we could implement this example code to the ProcessServices with several modifies.

First of all,  add the ACCOUNT_SID and AUTH_TOKEN to the application.properties in the core file which securities personal information . Secondly, initialize Twilio, which is the Twilio.init(ACCOUNT_SID, AUTH_TOKEN), before the ProcessServices has been initialized. Thus, create a getProcessService method on the Twilio Configuration which using the dependency injection.

@Bean
public ProcessService getProcessService(@Autowired @Qualifier("applicationProperties") PropertiesFactoryBean propertiesFactoryBean) throws IOException {
      String ACCOUNT_SID = propertiesFactoryBean.getObject().getProperty("ACCOUNT_SID");
      String AUTH_TOKEN = propertiesFactoryBean.getObject().getProperty("AUTH_TOKEN");
      Twilio.init(ACCOUNT_SID,AUTH_TOKEN);
      ProcessService processService = new ProcessService();
      return processService;
}

By getProcessService method, we initialized Twilio and implement two methods. 1. Construct the Message with all the information and then 2. Send the message.

public MessageCreator SMS(String receiveNumber,String sendNumber,String messageBody) {
            MessageCreator message = Message.creator(
            new com.twilio.type.PhoneNumber(receiveNumber),
            new com.twilio.type.PhoneNumber(sendNumber),
            messageBody);
            return message;
}
public void twillioSMSSend(MessageCreator creator){
     creator.create();
}

Unit Test with Mockito for Third Party Integration:

We would use the Mock to test our method that verifies the twilioSMSSend method. As the argument type on the twillioSMSSend is MessageCreator, we mock a MessageCreator names message on the test class, we also need to add a Mockito maven dependency,

<dependency>
      <groupId>org.mockito</groupId>
      <version>${version}</version>
      <artifactId>mockito-all</artifactId>
      <scope>test</scope>
</dependency>
private MessageCreator message = Mockito.mock(MessageCreator.class);

Then, input the ACCOUNT_SID and AUTH_TOKEN to initialize the Twilio. Finally, call the method and verify the number of times this method has been called.

@Test
public void SMSSendTest(){
      String ACCOUNT_SID = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
      String AUTH_TOKEN = "your_auth_token";

      Twilio.init(ACCOUNT_SID,AUTH_TOKEN);
      processService.twillioSMSSend(message);
      verify(message,times(1)).create();
      }

Reference:

AmazonSQS: https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/examples-sqs-messages.html

Author:

GitHub: https://github.com/xchris1015/basketball

Chris(Chang) Xu