Send and Receive SMS With Java Using Nexmo

The Nexmo SMS API is a service that allows you to send and receive SMS messages anywhere in the world. Nexmo provides REST APIs, but it's much easier to use the Java client library we've written for you.

In this tutorial we'll cover how to send and receive SMS messages with Java!
GitHub icon View the source code on GitHub

Prerequisites

Before starting, there are a few things you're going to need to have installed on your development machine. Hopefully you already have a basic understanding of Java programming — we're not going to be doing any very complicated programming, but it'll help you to get up and running. As well as a basic understanding of Java, you'll also need:

This tutorial assumes that you're running on OSX or Linux. It should work on Windows as well, but you'll have to adapt a couple of the simple shell commands to the windows command line.

Getting Your API Keys

First, sign up for a Nexmo account. Then go to the Dashboard, buy a phone number from Numbers and download your API keys from the Settings page.

Getting Your API Keys

Using the Nexmo Client Library for Java

Now we're going to set up your Gradle project and download the Nexmo Client Library for Java.

First, create a directory to contain your project. Inside this directory, run gradle init. If you haven't used Gradle before, don't worry — we're not going to do anything too complicated! Open the file build.gradle and change the contents to the following:

// We're creating a Java Application:
apply plugin: 'application'
apply plugin: 'java'

// Download dependencies from Maven Central:
repositories {
    mavenCentral()
}

// Install the Nexmo Client library:
dependencies {
    compile 'com.nexmo:client:3.1.0'
}

// We'll create this class to contain our code:
mainClassName = "getstarted.SendSMS"

Now, if you open your console in the directory that contains this build.gradle file, you can run:

gradle build

This command will download the Nexmo client library and store it for later. If you had any source code, it would also compile that — but you haven't written any yet — so let's fix that!

Because of the mainClassName we set in your Gradle build file, you're going to need to create a class called SendSMS in the package getstarted. In production code, you'd want the package to be something like com.mycoolcompany.smstool. But this isn't production code, so getstarted will do.

Gradle uses the same directory structure as Maven, so you're going to need to create the following directory structure inside your project directory: src/main/java/getstarted

On MacOS and Linux, you can create this path by running:

mkdir -p src/main/java/getstarted

Inside the getstarted directory, create a file called SendSMS.java, open it in your favourite text editor (Sublime, Atom, vim, etc.), and we'll start with some boilerplate code:

package getstarted;
 
import com.nexmo.client.NexmoClient;
import com.nexmo.client.auth.AuthMethod;
import com.nexmo.client.auth.TokenAuthMethod;
import com.nexmo.client.sms.SmsSubmissionResult;
import com.nexmo.client.sms.messages.TextMessage;

 
public class SendSMS {

 
    public static void main(String[] args) throws Exception {
        // Our code will go here!
    }
}

All this does is import the necessary parts of the Nexmo client library, and create a method to contain our code. It's worth running gradle run now, which should run your main method. It won't do anything yet, but this is where we get to the interesting bit.

Send SMS Messages with Java

Put the following in your main method:

AuthMethod auth = new TokenAuthMethod(API_KEY, API_SECRET);
NexmoClient client = new NexmoClient(auth);

Fill in API_KEY and API_SECRET with the values you copied from the Nexmo Dashboard. This code creates a NexmoClient object that can be used to send SMS messages. (You would need to provide other AuthMethods to be able to make voice calls, but that's a subject for another tutorial.) Now we have a configured client object, we can send an SMS message:

TextMessage message = new TextMessage(FROM_NUMBER, TO_NUMBER, "Hello from Nexmo!");
SmsSubmissionResult[] responses = client.getSmsClient().submitMessage(message);
for (SmsSubmissionResult response : responses) {
    System.out.println(response);
}

Again, you'll want to replace FROM_NUMBER and iTO_NUMBER with strings containing the Nexmo number you bought, and your own mobile phone number. Once you've done that, save and run gradle run again. You should see something like this printed to the screen:

SMS-SUBMIT-RESULT -- STATUS:0 ERR:null DEST:4412341234 MSG-ID:0C0000002D9C9A89 CLIENT-REF:null PRICE:0.0333000

... and you should receive a text message! If it didn't work, check out if something was printed after ERR: in the line above, and maybe wait a few more seconds for the message to appear.

So you just learned how to send an SMS message with Nexmo! You can either stop there, or for bonus points, we can build a Web service around it, which will be useful in an upcoming section where we'll be writing a webhook to receive SMS messages sent to your Nexmo number.

Building a Web Service to Send SMS

We're going to build a tiny HTTP service and then test it with Postman. Fortunately Gradle makes this quite easy. Open your build.gradle file and add the following to the top:

apply plugin: 'war'
apply from: 'https://raw.github.com/akhikhl/gretty/master/pluginScripts/gretty.plugin'

The first line tells Gradle it should build a war file, using source files in src/main/java and src/main/webapp. The second line adds the ability to fire up your webapp straight from Gradle using the Jetty servlet container!

I'm going to suggest you run gradle appRun now (note that you use "appRun" and not "run" to run the web server!) It'll take a while the first time, while it downloads some dependencies.

Eventually, you should see something like this:

11:11:59 INFO  Jetty 9.2.15.v20160210 started and listening on port 8080
11:11:59 INFO  project runs at:
11:11:59 INFO    http://localhost:8080/project
Press any key to stop the server.
<===========--> 87% EXECUTING
> :appRun

This means Jetty is now running your (empty) web service. Fire up the URL you see, to check it's running OK. It should look a bit like this:

Jetty is now running your (empty) web service. Fire up the URL you see, to check it's running OK. It should look a bit like this

Now let's write a servlet! Create a file called src/main/java/getstarted/SendSMSServlet.java. It's going to look similar to our last class:

public class SendSMSServlet extends HttpServlet {
    private String FROM_NUMBER;
    private NexmoClient client;
 
    public void init(ServletConfig config) {
        // Load configuration from the servlet container:
        FROM_NUMBER = config.getInitParameter("from_number");
        String api_key = config.getInitParameter("api_key");
        String api_secret = config.getInitParameter("api_secret");
 
        client = new NexmoClient(new TokenAuthMethod(api_key, api_secret));
    }
 
    protected void doPost(HttpServletRequest req,
                      HttpServletResponse resp)
               throws ServletException,
                      java.io.IOException {
        try {
            // Extract form parameters from the request:
            String to_number = req.getParameter("to");
            String message = req.getParameter("message");
 
            SmsSubmissionResult[] responses = client.getSmsClient().submitMessage(
                new TextMessage(FROM_NUMBER, to_number, message));
            for (SmsSubmissionResult response : responses) {
                resp.getWriter().println(response);
            }
        } catch (NexmoClientException nce) {
            throw new ServletException(nce);
        }
    }
}

And then we need to configure the servlet in our servlet container by creating the following at src/main/webapp/WEB-INF/web.xml:

<web-app>
    <servlet>
        <servlet-name>send-sms</servlet-name>
        <servlet-class>getstarted.SendSMSServlet</servlet-class>
        <init-param>
            <param-name>from_number</param-name>
            <param-value>YOUR_NEXMO_NUMBER</param-value>
        </init-param>
        <init-param>
            <param-name>api_key</param-name>
            <param-value>YOUR_API_KEY</param-value>
        </init-param>
        <init-param>
            <param-name>api_secret</param-name>
            <param-value>YOUR_API_SECRET</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>send-sms</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
</web-app>

Replace the placeholders with your own values, and then run gradle appRun. If everything builds correctly, let's fire up Postman and make a POST request, like this:

Make a POST request in Postman

After making the POST request you should receive a text message. So now you've built a REST Web service for sending SMS messages! In reality, there's lots more things you'd want to do before deploying this, like adding authentication (otherwise anyone could send a message using your Nexmo account!), a nice Web form for posting to the service, and improving the error handling — but this is a good start!

Now that we've learned how to send SMS messages with Java, let's extend this service to receive SMS messages sent to your Nexmo number.

Receive SMS Messages with Java

When Nexmo receives an SMS message on a Nexmo number, it looks up the webhook endpoint (URL) associated with that number and calls that URL with a big blob of JSON describing the message that was just received.

When Nexmo receives an SMS message on a Nexmo number, it looks up the webhook endpoint (URL) associated with that number and calls that URL with a big blob of JSON describing the message that was just received

What we're going to do in this section is write a servlet that can handle the incoming SMS message. The problem is that while we're developing on our local machine, we are likely to be firewalled from the Internet, so Nexmo's servers can't reach us! One way around this would be to continuously deploy to a public web server, but that is a complete pain. Fortunately there is an excellent tool called Ngrok that can help us with this problem. You can read more about connecting your local development server to the Internet using Ngrok on our blog.

Developing Webhooks with Ngrok

When you run Ngrok, it creates a new subdomain of ngrok.io, and then it tunnels all requests to that domain name to a web service running on your machine. Handy!

So go install Ngrok (I'll wait here). Once you've done that, run ngrok in your terminal:

ngrok http 8080

Jetty uses the 8080 port by default, so we'll use that to make life easier. You can see from the screenshot that Ngrok has allocated me the random URL http://8b771613.ngrok.io, which is now tunneling to localhost:8080, where I'll be running Jetty in a moment.

Jetty uses the 8080 port by default, so we'll use that to make life easier. You can see from the screenshot that Ngrok has allocated me the random URL http://8b771613.ngrok.io, which is now tunneling to localhost:8080, where I'll be running Jetty in a moment

Leave Ngrok running in a terminal window (it'll happily run until you shut it down), and we want to keep the URL and tunnel running for a while. What we'd like to do now is to configure Nexmo to point to our Ngrok URL, but it won't do so unless the URL is returning 200 messages. So we need to write a small stub servlet first.

A Servlet to Receive the SMS Message

In src/main/java/getstarted/InboundSMSServlet.java, paste the following:

package getstarted;
 
import javax.servlet.*;
import javax.servlet.http.*;
 
import java.util.Collections;
 
public class InboundSMSServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req,
                         HttpServletResponse resp)
            throws ServletException,
                   java.io.IOException {
        System.out.println("Received: " + req.getMethod());
        for (String param : Collections.list(req.getParameterNames())) {
            String value = req.getParameter(param);
            System.out.println(param + ": " + value);
        }
    }
}

All the Servlet does is to print the received parameters to the console–useful for debugging! Now configure your web.xml with the following:

<servlet>
    <servlet-name>inbound-sms</servlet-name>
    <servlet-class>getstarted.InboundSMSServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>send-sms</servlet-name>
    <url-pattern>/send</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>inbound-sms</servlet-name>
    <url-pattern>/inbound</url-pattern>
</servlet-mapping>

Note that I've reconfigured the send-sms mapping so the url-pattern is now /send instead of the wildcard mapping it was before. Now if you run gradle appRun, Jetty should start up and you're ready to configure your Nexmo web-hook.

Configure Nexmo to Call Your Webhook

Sign into your Nexmo account and go to Your Numbers. Find the number you want to configure, hit 'Edit' and then enter the ngrok URL with /YOUR_PROJECT_NAME/inbound at the end.

Now, if you send a text message to the number, you should see some lines printed on your console:

Received: GET
messageId: 0B0000004A2D09D9
to: 447520615146
text: Hello Nexmo!
msisdn: 447720123123
type: text
keyword: HELLO
message-timestamp: 2017-04-27 14:41:32

And That's It!

So now you can receive SMS messages! At the moment, all we're doing is printing them out to the console. It's often useful to store them in a database of some kind, but you can do anything you want with them now:

  • build a Slack bot to post them to your Slack channel
  • pass them through Google Translate and then forward the messages to your phone
  • forward them to Twitter?

The possibilities are endless!

 

Documentation Links

The following documentation links will be useful for working with SMS messages:

Mark Smith Developer Advocate @Nexmo; Comedy Python Programmer;
 

Comments