SMS and MMS Notifications with Java and Spark

January 10, 2017
Written by
Jose Oliveros
Contributor
Opinions expressed by Twilio contributors are their own
Reviewed by
Kat King
Twilion
Paul Kamp
Twilion

sms-mms-java-spark

Today we'll look at a Spark sample application that demonstrates how to send SMS alerts to your system administrators when something goes wrong on your server. We'll do a deep dive on all of the plumbing so you can see how easy it'll be to add notifications to your own application.

Let's get started!

List Your Server Administrators, and Whomever Else

Here we create a JSON list of administrators who should be notified if a server error occurs.

The only essential piece of data we need is a phone_number for each administrator.

This is a migrated tutorial. Clone the code from https://github.com/TwilioDevEd/server-notifications-spark/

{
    "name": "Bob"

Next, let's take a look at configuring the Twilio REST Client.

Configuring the Twilio REST Client

To send a message we'll need to initialize the TwilioRestClient defined in the Twilio Java Helper Library. It requires reading a TWILIO_ACCOUNT_SID and TWILIO_AUTH_TOKEN from environment variables.

The values for your account SID and Auth Token will be in the Twilio console:

Twilio Account Summary section of the console

Click the eyeball to show your Auth Token to copy and paste.

package utils;

import com.twilio.exception.TwilioException;
import com.twilio.http.TwilioRestClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Client {

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


    private Credentials credentials;
    private TwilioMessageCreator messageCreator;

    public Client() {
        this.credentials = new Credentials();
        this.messageCreator = new TwilioMessageCreator(
                new TwilioRestClient.Builder(credentials.getAccountSid(), credentials.getAuthToken()).build()
        );
    }

    public Client(TwilioMessageCreator messageCreator, Credentials credentials) {
        this.credentials = credentials;
        this.messageCreator = messageCreator;
    }

    public void sendMessage(String to, String message, String mediaUrl) {
        try {
            messageCreator.create(to, credentials.getPhoneNumber(), message, mediaUrl);
        } catch (TwilioException e) {
            logger.error("An exception occurred trying to send the message \"{}\" to {}." +
                    " \nTwilio returned: {} \n", message, to, e.getMessage());
        }
    }
}

Next up, we will look at how to handle application exceptions.

Handling the Application Exceptions

In a Spark application, we can handle exceptions of a configured type for all routes and filters by using exception mapping.  This is also where we'll eventually loop through the list and send our alerts.

import logging.LoggingFilter;
import models.Administrator;
import utils.Client;
import utils.Repository;

import static spark.Spark.afterAfter;
import static spark.Spark.exception;
import static spark.Spark.get;

public class App {
    public static void main(String[] args) {
        get("/", (request, response) -> {
            throw new Exception("Impossible happened");
        });

        // http://sparkjava.com/documentation.html#exception-mapping
        exception(Exception.class, (e, request, response) -> {
            String message = String.format("It appears the server is having Exception: %s " +
                    "Help from a friendly bot is on the way. ",
                    e.getMessage());

            String mediaUrl = "https://farm8.staticflickr.com/7090/6941316406_80b4d6d50e_z_d.jpg";

            Administrator[] administrators = new Repository().getAdministrators();
            for(Administrator administrator : administrators) {
                new Client().sendMessage(administrator.getPhoneNumber(), message, mediaUrl);
            }

            response.body("Something unexpected happened. Keep calm, administrators were notified.");
        });

        // Log all requests and responses
        afterAfter(new LoggingFilter());
    }
}

Now let's look at how to create a custom message for our notifications.

Create a Custom Alert Message

Here we create an alert message to send out via text message.

You might also decide to include a picture with your alert message and make it an MMS. Perhaps a screenshot of the application when the crash happened?  An 'Everything is Okay' meme image?

import logging.LoggingFilter;
import models.Administrator;
import utils.Client;
import utils.Repository;

import static spark.Spark.afterAfter;
import static spark.Spark.exception;
import static spark.Spark.get;

public class App {
    public static void main(String[] args) {
        get("/", (request, response) -> {
            throw new Exception("Impossible happened");
        });

        // http://sparkjava.com/documentation.html#exception-mapping
        exception(Exception.class, (e, request, response) -> {
            String message = String.format("It appears the server is having Exception: %s " +
                    "Help from a friendly bot is on the way. ",
                    e.getMessage());

            String mediaUrl = "https://farm8.staticflickr.com/7090/6941316406_80b4d6d50e_z_d.jpg";

            Administrator[] administrators = new Repository().getAdministrators();
            for(Administrator administrator : administrators) {
                new Client().sendMessage(administrator.getPhoneNumber(), message, mediaUrl);
            }

            response.body("Something unexpected happened. Keep calm, administrators were notified.");
        });

        // Log all requests and responses
        afterAfter(new LoggingFilter());
    }
}

Let's move forward and look at loading the list of administrators.

Reading the Administrators from a JSON File

Next, we read the admins - and any other lucky people - from our JSON file. We use the Gson Java library to convert our JSON text file into Administrator objects.

package utils;

import com.google.gson.Gson;
import models.Administrator;

import java.io.FileNotFoundException;
import java.io.FileReader;

public class Repository {
    private String filePath;

    public Repository() {
        this.filePath = getClass().getClassLoader().getResource("administrators.json").getPath();
    }

    public Repository(String filePath) {
        this.filePath = filePath;
    }

    public Administrator[] getAdministrators() {
        try {
            return new Gson().fromJson(new FileReader(filePath), Administrator[].class);
        } catch (FileNotFoundException e) {
            e.printStackTrace();

            return new Administrator[0];
        }
    }
}

And next, we will see how to send a text message.

Sending a Text Message

There are three parameters needed to send an SMS using the Twilio REST API: From, To, and Body.

US and Canadian phone numbers can also send an image with the message.  Other countries will have the image URL automatically shortened and appended to the body.

package utils;

import com.twilio.exception.TwilioException;
import com.twilio.http.TwilioRestClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Client {

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


    private Credentials credentials;
    private TwilioMessageCreator messageCreator;

    public Client() {
        this.credentials = new Credentials();
        this.messageCreator = new TwilioMessageCreator(
                new TwilioRestClient.Builder(credentials.getAccountSid(), credentials.getAuthToken()).build()
        );
    }

    public Client(TwilioMessageCreator messageCreator, Credentials credentials) {
        this.credentials = credentials;
        this.messageCreator = messageCreator;
    }

    public void sendMessage(String to, String message, String mediaUrl) {
        try {
            messageCreator.create(to, credentials.getPhoneNumber(), message, mediaUrl);
        } catch (TwilioException e) {
            logger.error("An exception occurred trying to send the message \"{}\" to {}." +
                    " \nTwilio returned: {} \n", message, to, e.getMessage());
        }
    }
}

And that's a wrap!

We've just implemented an automated server notification system for Java and Spark that can push server alerts if anything goes wrong.

Let's see what else you can do with the Twilio Java SDK, next.

Where to Next?

We love Java here at Twilio.  Here're just a couple more examples of using our Java SDK to easily add some features in your application:

Automated Survey

How well is your team doing when interacting with customers?  Instantly collect structured data from your users with a survey conducted over a voice call or SMS.

Appointment Reminders

A simple tutorial to prevent no-shows at your business - send your customers automatic appointment notifications.

Did this help?

Thanks for building with us today.  Tweet us a comment @twilio to let us know what you think and what you're building!