SMS and MMS Notifications with Java and Servlets

This Java Servlets tutorial will walk you through how you can automatically notify your system administrators if - well, when - something goes wrong on your server.

We'll dive in for a deeper look at all the wiring behind the scenes. Soon you'll see how easy it is to work notifications into your own application.

See how EMC uses Twilio SMS to send IT alerts to 68,000 employees.

Sound good?  Let's get started!

Click the button below to move to the next step of the tutorial.

List Your Server Administrators

Here we create a list of administrators (and your choice of others) who should be notified if a server error occurs.

The only essential piece of data we need is a text-enabled phoneNumber for each person you list.

Loading Code Samples...
Language
[
  {
    "name": "Bob",
    "phoneNumber": "+12025550197"
  },
  {
    "name": "Alice",
    "phoneNumber": "+12025550890"
  }
]
src/main/resources/administrators.json
JSON Administrator list

src/main/resources/administrators.json

Next at the plate: we'll take a look at how to set up the Twilio REST client.

Configuring the Twilio Client

To send a message we'll need to initialize the TwilioRestClient (for details, see the Twilio Java Helper Library documentation).  

We'll have to read a TWILIO_ACCOUNT_SID and TWILIO_AUTH_TOKEN from environment variables.

The values for your account SID and Auth Token will come from the Twilio console:

Twilio Account Summary section of the console

Loading Code Samples...
Language
package com.twilio.notifications.utils;

import com.twilio.exception.TwilioException;
import com.twilio.http.TwilioRestClient;

public class Client {
    private Credentials credentials;
    private TwilioMessageCreator messageCreator;

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

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

    public void sendMessage(String to, String message, String mediaUrl) {
        try {
            this.messageCreator.create(to, this.credentials.getPhoneNumber(), message, mediaUrl);
        } catch (TwilioException exception) {
            exception.printStackTrace();
        }
    }
}
src/main/java/com/twilio/notifications/utils/Client.java
Configure the Twilio client from environment variables

src/main/java/com/twilio/notifications/utils/Client.java

Next, let's look at how we're handling application exceptions.

Handling the Application's Exceptions

Using a Servlet Filter, we can capture any unhandled exceptions thrown by any other Servlets or Filters set up to handle a given URL.

And that's where we'll insert our logic to send out notifications to the server administrators.

Loading Code Samples...
Language
package com.twilio.notifications.filter;

import com.twilio.notifications.models.Administrator;
import com.twilio.notifications.utils.Client;
import com.twilio.notifications.utils.Repository;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

@WebFilter(filterName = "ErrorFilter", urlPatterns = {"/launch"})
public class ErrorFilter implements Filter {
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        String errorMessage = "Generic error message";
        try {
            chain.doFilter(request, response);
        } catch (Throwable throwable) {
            String message = customMessage(throwable.getMessage());
            String mediaUrl = "http://goo.gl/ObTXdX";

            // Send a message to the administrators when something went unexpectedly wrong.
            Administrator[] administrators = new Repository().getAdministrators();
            for (Administrator administrator : administrators) {
                new Client().sendMessage(administrator.getPhoneNumber(), message, mediaUrl);
            }
        }

        Object error = errorMessage;
        request.setAttribute("error", error);
        request.getRequestDispatcher("error.jsp").forward(request, response);
    }

    public void destroy() {
    }

    private String customMessage(String exceptionMessage) {
        return String.format("It appears the server is having Exception: %s " +
                        "Go to: http://newrelic.com for more details. " +
                        "Image URL: http://goo.gl/ObTXdX",
                exceptionMessage);
    }
}
Handle all exceptions that come our way

Next up, let's look at how to craft a custom message upon spotting an exception.

Crafting a Custom Alert Message

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

Feel free to also include a picture with your notification message. Perhaps a screenshot of the application when the exception happened?  Some meme from a chain email?

Loading Code Samples...
Language
package com.twilio.notifications.filter;

import com.twilio.notifications.models.Administrator;
import com.twilio.notifications.utils.Client;
import com.twilio.notifications.utils.Repository;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

@WebFilter(filterName = "ErrorFilter", urlPatterns = {"/launch"})
public class ErrorFilter implements Filter {
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        String errorMessage = "Generic error message";
        try {
            chain.doFilter(request, response);
        } catch (Throwable throwable) {
            String message = customMessage(throwable.getMessage());
            String mediaUrl = "http://goo.gl/ObTXdX";

            // Send a message to the administrators when something went unexpectedly wrong.
            Administrator[] administrators = new Repository().getAdministrators();
            for (Administrator administrator : administrators) {
                new Client().sendMessage(administrator.getPhoneNumber(), message, mediaUrl);
            }
        }

        Object error = errorMessage;
        request.setAttribute("error", error);
        request.getRequestDispatcher("error.jsp").forward(request, response);
    }

    public void destroy() {
    }

    private String customMessage(String exceptionMessage) {
        return String.format("It appears the server is having Exception: %s " +
                        "Go to: http://newrelic.com for more details. " +
                        "Image URL: http://goo.gl/ObTXdX",
                exceptionMessage);
    }
}
Craft a custom exception message

Next, let's look at loading the list of administrators.

Reading the Administrators from the JSON File

Next, we read the admins from our JSON file.

We're relying on the Gson Java library to convert our JSON text file into the Administrator objects from our application.

Loading Code Samples...
Language
package com.twilio.notifications.utils;

import com.google.gson.Gson;
import com.twilio.notifications.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];
        }
    }
}
Administrators Repository Utilities
Read JSON Administrator list

Administrators Repository Utilities

And for our next trick, we'll show how the text messages themselves are sent.  Carry on!

Sending a Text Message

There are the 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 picture url automatically shortened.

Loading Code Samples...
Language
package com.twilio.notifications.utils;

import com.twilio.exception.TwilioException;
import com.twilio.http.TwilioRestClient;

public class Client {
    private Credentials credentials;
    private TwilioMessageCreator messageCreator;

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

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

    public void sendMessage(String to, String message, String mediaUrl) {
        try {
            this.messageCreator.create(to, this.credentials.getPhoneNumber(), message, mediaUrl);
        } catch (TwilioException exception) {
            exception.printStackTrace();
        }
    }
}
src/main/java/com/twilio/notifications/utils/Client.java
Send our custom crafted message to the administrator list.

src/main/java/com/twilio/notifications/utils/Client.java

And that's it!

We've just implemented an automated server notification system that can send your administrators push alerts if anything goes wrong.  Twilio makes it easy to incorporate these important - and useful - functions for your own use cases.

Carry on and we'll look at some other useful ways our customers have used Twilio.

Where to Next?

We've built a lot of sample applications with Twilio and Java, and we'd love to share them all.  However, we'll limit our suggestions to just two:

Automated Survey

Instantly collect structured data from your users with a survey conducted over a voice call or SMS text messages.  That will help you quantify the impact of your support call handling, for starters.

Appointment Reminders

If you're having issues with customers missing booked meetings, this tutorial is where you should head next.  We look at sending automatic reminders as a meeting approaches.

Did this help?

Thanks for checking out this tutorial! Tweet to us @twilio to let us know what you thought or what you're building next!

Agustin Camino
David Prothero
Kevin Whinnery
Paul Kamp
Andrew Baker
Samuel Mendes

Need some help?

We all do sometimes; code is hard. Get help now from our support team, or lean on the wisdom of the crowd browsing the Twilio tag on Stack Overflow.

1 / 1
Loading Code Samples...
[
  {
    "name": "Bob",
    "phoneNumber": "+12025550197"
  },
  {
    "name": "Alice",
    "phoneNumber": "+12025550890"
  }
]
package com.twilio.notifications.utils;

import com.twilio.exception.TwilioException;
import com.twilio.http.TwilioRestClient;

public class Client {
    private Credentials credentials;
    private TwilioMessageCreator messageCreator;

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

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

    public void sendMessage(String to, String message, String mediaUrl) {
        try {
            this.messageCreator.create(to, this.credentials.getPhoneNumber(), message, mediaUrl);
        } catch (TwilioException exception) {
            exception.printStackTrace();
        }
    }
}
package com.twilio.notifications.filter;

import com.twilio.notifications.models.Administrator;
import com.twilio.notifications.utils.Client;
import com.twilio.notifications.utils.Repository;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

@WebFilter(filterName = "ErrorFilter", urlPatterns = {"/launch"})
public class ErrorFilter implements Filter {
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        String errorMessage = "Generic error message";
        try {
            chain.doFilter(request, response);
        } catch (Throwable throwable) {
            String message = customMessage(throwable.getMessage());
            String mediaUrl = "http://goo.gl/ObTXdX";

            // Send a message to the administrators when something went unexpectedly wrong.
            Administrator[] administrators = new Repository().getAdministrators();
            for (Administrator administrator : administrators) {
                new Client().sendMessage(administrator.getPhoneNumber(), message, mediaUrl);
            }
        }

        Object error = errorMessage;
        request.setAttribute("error", error);
        request.getRequestDispatcher("error.jsp").forward(request, response);
    }

    public void destroy() {
    }

    private String customMessage(String exceptionMessage) {
        return String.format("It appears the server is having Exception: %s " +
                        "Go to: http://newrelic.com for more details. " +
                        "Image URL: http://goo.gl/ObTXdX",
                exceptionMessage);
    }
}
package com.twilio.notifications.filter;

import com.twilio.notifications.models.Administrator;
import com.twilio.notifications.utils.Client;
import com.twilio.notifications.utils.Repository;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

@WebFilter(filterName = "ErrorFilter", urlPatterns = {"/launch"})
public class ErrorFilter implements Filter {
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        String errorMessage = "Generic error message";
        try {
            chain.doFilter(request, response);
        } catch (Throwable throwable) {
            String message = customMessage(throwable.getMessage());
            String mediaUrl = "http://goo.gl/ObTXdX";

            // Send a message to the administrators when something went unexpectedly wrong.
            Administrator[] administrators = new Repository().getAdministrators();
            for (Administrator administrator : administrators) {
                new Client().sendMessage(administrator.getPhoneNumber(), message, mediaUrl);
            }
        }

        Object error = errorMessage;
        request.setAttribute("error", error);
        request.getRequestDispatcher("error.jsp").forward(request, response);
    }

    public void destroy() {
    }

    private String customMessage(String exceptionMessage) {
        return String.format("It appears the server is having Exception: %s " +
                        "Go to: http://newrelic.com for more details. " +
                        "Image URL: http://goo.gl/ObTXdX",
                exceptionMessage);
    }
}
package com.twilio.notifications.utils;

import com.google.gson.Gson;
import com.twilio.notifications.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];
        }
    }
}
package com.twilio.notifications.utils;

import com.twilio.exception.TwilioException;
import com.twilio.http.TwilioRestClient;

public class Client {
    private Credentials credentials;
    private TwilioMessageCreator messageCreator;

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

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

    public void sendMessage(String to, String message, String mediaUrl) {
        try {
            this.messageCreator.create(to, this.credentials.getPhoneNumber(), message, mediaUrl);
        } catch (TwilioException exception) {
            exception.printStackTrace();
        }
    }
}