Getting Started with Scala and Twilio

November 27, 2017
Written by

ScalaTwilioIntro

It’s functional, it’s object-oriented, it’s everything you never knew you wanted and more! In this post we’ll introduce Scala and give you the tools to build a Scala application that can send text messages using Twilio from the command line.

Scala is a JVM language that is notable for its combination of Object Oriented and Functional programming styles. Over the last fifteen years it’s gained popularity with use cases ranging from web programming to data engineering to distributed systems. Companies like Twitter, Stripe, and Twilio have all built large systems on top of the language.

Hello World

Let’s dive in. Here’s what you’ll need:

Check that you have Java and SBT installed:

~ $ java -version
java version "1.8.0_151"

~ $ sbt sbtVersion
[info] ...
[info] 0.13.6

With SBT installed, you can now access the Scala REPL with sbt console, try that now. Here’s a good cheat sheet for working in the REPL. Some things you’ll notice right away is that every value in Scala has a return type, and that those types can be inferred:

scala> 1 + 1
res0: Int = 2

scala> val greeting = "hello"
greeting: String = hello 

scala> def add(x: Int, y: Int): Int = x + y 
add: (x: Int, y: Int)Int

I recommend the Tour of Scala for a great introduction to the Scala syntax.

SBT is useful for more than just the console; it’s the tool that will manage your dependencies, execute your project, and run your tests. A neat feature was added last year that also makes it easy to build new projects from templates. The directory structure isn’t strict, but there are some best practices for organizing your files and project templates will set that up for you.

You can read more about SBT’s templates here. I created a template for our project so head over to your terminal and type the following. When it asks for the name of the project, you can name it whatever you like, I named mine hello.

~ $ sbt new robinske/hello-world.g8
....
name [Hello World template]: hello
Template applied in ./hello

After you cd into the directory, you can now run the project:

hello $ sbt
> run

This will take a while to download all of the dependencies the first time you run it. Once the dependencies are downloaded, you’ll be prompted for your name:

What is your name? Kelley
Ahoy, Kelley!

Pretty neat, you’ve just set up your first Scala project! We’ll use this base for the rest of our application.

Sending Text Messages with Scala

Now that you have a Hello World project in Scala you can extend that to send text messages. For the messaging, we’ll use the Twilio API. Twilio doesn’t have a specific Scala SDK but we don’t need one — the Java SDK works swimmingly.

To add a dependency, you’ll need to edit your build.sbt file, which is in the top level of your project. You’ll see a section for libraryDependencies that already contains the config library. Add another line for the Twilio library, which I found in the SBT tab on Maven.


libraryDependencies   = {
  Seq(
    "com.typesafe"   % "config" % "1.3.2",
    "com.twilio.sdk" % "twilio" % "7.15.5"
  )
}

Before you can use the Twilio library, you’ll need set up the SDK with your credentials. Sign up for a Twilio account if you don’t already have one and grab your Account SID and Auth Token from twilio.com/console. Save your account credentials as environment variables and overwrite the placeholder configuration in src/main/resources/application.conf with the following code.

twilio {
  account_sid = ${TWILIO_ACCOUNT_SID}
  auth_token = ${TWILIO_AUTH_TOKEN}
  from_number = ${TWILIO_PHONE_NUMBER}
}

As you’re adding code, you can run sbt ~compile. The ~ tells SBT to incrementally compile your project every time you save a file and will help catch errors in your program early and often.

In the src/main/scala/Main.scala file, we can replace our greeting example with our Twilio code. First we’ll need to grab some necessary imports for the Twilio library. These can be placed at the top of your file with the existing imports.


package hello

import com.typesafe.config.{Config, ConfigFactory}
import scala.io.StdIn.readLine
import com.twilio.Twilio
import com.twilio.`type`.PhoneNumber
import com.twilio.rest.api.v2010.account.Message

Now you can initialize the Twilio client with our Account SID and Auth Token. Since you already have our config defined, you can fetch your credentials.


object Main extends App {
  val config = ConfigFactory.load()

  val ACCOUNT_SID = config.getString("twilio.account_sid")
  val AUTH_TOKEN = config.getString("twilio.auth_token")

  Twilio.init(ACCOUNT_SID, AUTH_TOKEN)
}

As with Java, Scala is strongly typed. A method’s type signature provides documentation for the parameters and I often reference source code for this information. As we see below, the MessageCreator class requires two PhoneNumbers and one String.

Our from number is one of our stored config variables, so we can grab that and wrap it in the PhoneNumber data type that Twilio provides. Let’s hard-code our to number and body for now:


object Main extends App {
  val config = ConfigFactory.load()

  val ACCOUNT_SID = config.getString("twilio.account_sid")
  val AUTH_TOKEN = config.getString("twilio.auth_token")

  Twilio.init(ACCOUNT_SID, AUTH_TOKEN)

  val from = new PhoneNumber(config.getString("twilio.from_number"))
  val to = new PhoneNumber("+12315551234") // change this to your personal number for testing
  val body = "Do you wanna do something fun? Wanna go to Taco Bell? \uD83C\uDF2E"
}

Now that we have the necessary inputs, we can use those to construct and send our message.


object Main extends App {
  val config = ConfigFactory.load()

  val ACCOUNT_SID = config.getString("twilio.account_sid")
  val AUTH_TOKEN = config.getString("twilio.auth_token")

  Twilio.init(ACCOUNT_SID, AUTH_TOKEN)

  val from = new PhoneNumber(config.getString("twilio.from_number"))
  val to = new PhoneNumber("+12315551234") // change this to your personal number for testing
  val body = "Do you wanna do something fun? Wanna go to Taco Bell? uD83CuDF2E"

  val message = Message.creator(to, from, body).create()
  println(s"Message sent to $to with ID ${message.getSid}")
}

At this point, we can try running our program from the command line with sbt run – try that now and you should see a message come through.

Accepting User Input

Let’s make a few improvements to our design so we don’t have to rely on those hard-coded values. To accept user input in Scala, we’ll use the readLine method from the standard library’s IO package. The method returns a String and we can save that to a variable for something like:


object Main extends App {
  val config = ConfigFactory.load()

  val ACCOUNT_SID = config.getString("twilio.account_sid")
  val AUTH_TOKEN = config.getString("twilio.auth_token")

  Twilio.init(ACCOUNT_SID, AUTH_TOKEN)

  val from = new PhoneNumber(config.getString("twilio.from_number"))
  val to = new PhoneNumber(readLine("Who are we texting? "))
  val body = readLine("What do you want to say? ")

  Message.creator(to, from, body).create()
  println(s"Message sent to $to with ID ${message.getSid}")
}

Try running the program again and texting yourself and your friends different messages.

hello $ sbt
[info] ...
> run
[info] Running me.krobinson.twilio.Main 
Who are we texting? 2315551234
What do you want to say? Happy Monday!
Message sent to 2315551234 with ID SMcxxxxxxxxxxxxxxxxxxxxx
[success]

Adding Resiliency

Let’s improve our message sender by handling errors better.. Because we’re using the Java SDK, most of the methods will throw Exceptions when they encounter an error. For example, here’s what happens if we try to send a text to an invalid number:

> run
[info] Running me.krobinson.twilio.Main 
Who are we texting? 12345
What do you want to say? Hello!
[error] (run-main-1) com.twilio.exception.ApiException: The 'To' number 12345 is not a valid phone number.

        <long stack trace> 

There are a lot of ways we can handle this error in Scala and we’ll be using Scala’s Try and pattern matching to catch this one. For our program, runtime exceptions would happen in Message.creator(to, from, body).create() so that’s what we want to focus on error handling.

First we’ll import some utilities.


import com.typesafe.config.{Config, ConfigFactory}
import scala.io.StdIn.readLine
import com.twilio.Twilio
import com.twilio.`type`.PhoneNumber
import com.twilio.rest.api.v2010.account.Message
import scala.util.{Failure, Success, Try}

Wrap your message creation in a Try; this type will either return a successfully computed value (Success) or result in an exception (Failure).


object Main extends App {
  val config = ConfigFactory.load()

  val ACCOUNT_SID = config.getString("twilio.account_sid")
  val AUTH_TOKEN = config.getString("twilio.auth_token")

  Twilio.init(ACCOUNT_SID, AUTH_TOKEN)

  val from = new PhoneNumber(config.getString("twilio.from_number"))
  val to = new PhoneNumber(readLine("Who are we texting? "))
  val body = readLine("What do you want to say? ")
  Try(Message.creator(to, from, body).create()) match {
    case Success(message) =>
      println(s"Message sent to $to with ID ${message.getSid}")
    case Failure(error) =>
      println(s"Encountered an exception: n${error.getMessage}")
  }
}

Now when you try to send a message to an invalid number you’ll receive a more friendly error message that you can customize.

> run
[info] Running me.krobinson.twilio.Main 
Who are we texting? 12345
What do you want to say? Hello!
Encountered an exception: 
The 'To' number 12345 is not a valid phone number.

Neat!

Next Steps

Congratulations! You’ve successfully built a Scala application that can send custom text messages. There are many ways you can extend this project, like easily adding emojis!

There are many other reasons to continue exploring what’s possible with Scala. You might be interested in using Scala to take advantage of the JVM ecosystem with less verbose code. Perhaps you’re looking to process terabytes of data using Apache Spark, a popular library written in Scala and with Scala APIs. Whatever your need may be, the Scala community has grown to support the breadth of applications developers are building.

You can find a completed version of this application over on my github: https://github.com/robinske/hello-twilio-scala. Hopefully you’re inspired to learn a bit more about Scala and if you’re looking for additional resources, I can recommend the following:

  • Coursera Scala courses – learn about functional programming, concurrency, big data and more in these courses developed by the Scala Center.
  • Scala exercises – challenge yourself with introductory puzzles in the browser for Scala and popular Scala libraries.
  • Scala eBooks – read more in these free eBooks from Underscore.io, a Scala consultancy.

For more information about the language and its features, including a more in depth look at why (and why not) to use Scala, I talked about this at the GOTO Chicago conference last year. If you have any questions or comments about Scala, I always love hearing from you! Have fun getting started and I can’t wait to see what you build.