RESTful Web Services with Scala

4.5 (6 reviews total)
By Jos Dirksen
  • Instant online access to over 7,500+ books and videos
  • Constantly updated with 100+ new titles each month
  • Breadth and depth in over 1,000+ technologies
  1. Getting Started with RESTful Web Services

About this book

RESTful web services are built to work best on the web. Scala provides a rich set of language constructs and advanced frameworks that you can use to create REST services. However, using Scala and these tools can be a complex task. There are many frameworks available and choosing the wrong framework or approach can cost a lot of time and lead to much frustration. By exploring the most popular Scala REST frameworks, you can make sure you choose the right tool.

RESTful Web Services with Scala begins with a brief explanation of the REST architecture and its implementation in Scala, as well as the impact that REST architecture has on Scala applications. You will understand the advantages of building Scala web services and how existing Scala applications can take advantage of REST. This book will teach developers about the different programming paradigms available in the Scala world to create RESTful services by exploring the most popular Scala-oriented REST frameworks. It discusses the various facets of RESTful web services such as building scalable APIs, working with standards like HTTP and MIME, designing the architecture, securing the web service, and more.

With this book, you will be able to build RESTful web services with various Scala frameworks such as Finch, Unfiltered, Scalatra, Akka-HTTP, and Play. You will create basic REST services using frameworks and then extend the REST services with custom functionality. By the end of the book, you'll be able to decide which framework is best suited for your requirements. We finish by looking at how we can use a number of advanced features provided by these frameworks, such as security, creating HTTP clients, working with HATEOAS, and more.

Publication date:
November 2015
Publisher
Packt
Pages
204
ISBN
9781785289408

 

Chapter 1. Getting Started with RESTful Web Services

Welcome to this book on how to create REST services with Scala. In this book, I'll introduce a couple of different Scala-based frameworks and show you how to create a RESTful service with them. Each of these frameworks has its own specific way of creating REST services; some are more functional, while others provide a rich domain-specific language (DSL). After reading this book and working through the examples, you'll be able to choose the approach that best suits you and your specific problem.

In this book, the following Scala frameworks will be discussed:

  • Akka HTTP / DSL: Akka HTTP is a new REST framework built on top of Akka Streams. It provides a DSL-based approach based on Spray. Spray is one of the best-known REST frameworks in the Scala world, and the newest version will run on top of Akka HTTP. We'll explore the features of this DSL and show you how it can be used to create a REST service.

  • Unfiltered: Unfiltered is a little REST framework which provides a very structured approach of creating REST services. This framework provides direct access to all parts of the HTTP request, and doesn't make assumptions on how you want to process REST services. This gives you complete control of how the request is processed and the response is produced.

  • Play 2: Play 2 is one of the most popular Scala frameworks, which provides functionality to create complete web applications. Play 2 also provides great support for creating standard REST services. We'll focus on the REST-specific features of Play 2.

  • Finagle and Finch: Finagle and Finch both come from the people at Twitter. With Finagle and Finch, it is possible to create REST services using a clean, functional programming approach.

  • Scalatra: The last framework we'll discuss is the Scalatra framework. Scalatra is a lightweight framework, based on the better-known Sinatra framework, with which it is very easy to create REST services.

Besides these frameworks, in the last chapter of this book we'll also provide some guidelines on how to work with advanced topics such as HATEOAS, linking, and JSON processing.

In this first chapter, we are not going to explore a framework, but we'll use this chapter to introduce some concepts and set up some tools:

  • We'll first have to make sure you can run all the examples provided with this book, so we'll show you how to get the code and setup SBT and an IDE

  • We'll also do a short introduction into what RESTful services are

  • And finally, we'll have a look at the API of the service that we'll implement using the different Scala frameworks

There are many different definitions of REST, so before we look into the technical details, let's first look at the definition of REST we'll use in this book.

 

Introduction to the REST framework


In this book, when we talk about REST, we talk about REST as described in the dissertation of Roy Fielding (https://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm). Basically, REST is a software architecture style, which, when following the guidelines, can be used to create performant, reliable, and maintainable services. To better understand what REST is, it is a good idea to start with the constraints a service must follow to be RESTful. In his dissertation, Roy Fielding defines the following set of constraints:

  • Client-server: This constraint means that clients and servers are separated from each other through a standardized interface. The advantage of this approach is that clients don't need to worry about persistency, databases, messaging, scalability, and other server-side concepts; instead, they can focus on user-oriented functionality. Another advantage is that clients and servers can be developed independently since the only dependency between them is the standardized contract. Note that if you require a very strict contract between the client and the server, a WSDL/SOAP-based service might be a better option than going for a RESTful approach.

  • Stateless: Besides having a separate client and server, communication between these two components will have to be stateless. This means that each request the client sends should contain all the information necessary for the server. Note that for authentication, the server can temporarily store some session/user information in a persistent store, but all the real application state should be stored at the client. The big advantage of this approach is that this way it is very easy to scale out the servers horizontally by just adding more instances.

  • Cacheable: In a RESTful architecture, clients are allowed to cache responses. It is up to the server side to indicate which responses might be cached and for how long. The goal of this constraint is to minimize interactions between the client and the server by avoiding sending requests, whose response will stay the same. This, of course, improves performance at the client side and reduces bandwidth.

  • Layered system: This constraint describes that in a RESTful architecture, it is possible to create a layered system, where each layer has its own specific functionality. For instance, in between the client and the server, there might be a firewall, a load balancer, a reverse proxy, and so on. The client, however, doesn't notice these different layers.

  • Uniform interface: From all the constraints, this is perhaps the most interesting one. This constraint defines what a uniform interface (the contract between the client and the server) should look similar to. This constraint itself consists of the following four sections:

    • Identification of resources: In requests, each resource should be uniquely identified. Most often, this is done through a form of URI. Note that the technical representation of a resource doesn't matter. A resource, identified through a URI, can be represented in JSON, CSV, XML, and PDF while still remaining the same resource.

    • Manipulation of resources through these representations: When a client has a representation of a resource (for example, a JSON message), the client can modify this resource by updating the representation and sending it to the server.

    • Self-descriptive messages: Each message sent between the client and the server should be self-descriptive. The client need not know anything else to be able to parse and process the message. It should be able to learn from the message exactly what it can do with the resource.

    • Hypermedia as the engine of application state: This constraint, also called HATEOAS, implies that a user of an API doesn't need to know beforehand what it can do with a specific resource. Through the use of links in the resource and the definition of media-types, a client can explore and learn the actions it can take on a resource.

    • Code on demand: Code on demand is the only constraint that is optional. When comparing this constraint with the others, it is also one that is a bit different than the others. The idea behind this constraint is that servers could temporarily extend the functionality of clients by transferring executable code. In practice, this constraint is not seen that often though; most RESTful services deal with sending static responses, not executable code.

It's important to note that these constraints don't say anything about an implementation technology.

Tip

Often, when talking about REST, people immediately focus on HTTP and JSON. A RESTful architecture doesn't force you to adopt these technologies. On the other hand, most often, RESTful architectures are implemented on top of HTTP and currently use JSON as the message format. In this book, we will also focus on using HTTP and JSON to implement RESTful services.

The constraints mentioned here give an overview of how a service should act to be considered RESTful. However, when creating a service, it is often very hard to comply with all these constraints, and in some cases, not all the constraints might be that useful, or might be very hard to implement. Many people noticed this, and a couple of years ago, a more pragmatic view on REST was presented by Richardson's Maturity Model (http://martinfowler.com/articles/richardsonMaturityModel.html).

In Richardson's Maturity Model, you don't have to follow all the constraints to be considered RESTful; instead, a number of levels of maturity are defined that indicate how RESTful your service is. The higher the level, the more mature your service is, which will result in a more maintainable, more scalable, and easier-to-use service. This model defines the following levels:

The levels are described like this:

  • Level 0 describes the situation where you just send XML or JSON objects to a single HTTP endpoint. Basically, you're not doing REST, but you're doing RPC over HTTP.

  • Level 1 tackles the question of handling complexity by using divide and conquer, breaking a large service endpoint down into multiple resources

  • Level 2 introduces a standard set of verbs so that we can handle similar situations in the same way, removing unnecessary variation

  • Level 3 introduces discoverability, providing a way of making a protocol more self-documenting

In this book, we'll mostly focus on supporting REST at Level 2. So, we'll work with well-defined resources and use the appropriate HTTP verbs to indicate what we want to do with a resource.

In Chapter 7, JSON, HATEOAS, and Documentation, of this book, we'll address HATEOAS, which can help us reach maturity Level 3.

Now that we've got the theory out of the way, let's get the code, set up your favorite IDE, and define the API for the REST service we'll implement.

 

Getting the source code


There are a couple of different ways of getting the code for this book. We provide a download link at the book's website (https://www.packtpub.com/books/content/support/23321) from where you can download a ZIP file with the latest sources from GitHub (https://github.com/josdirksen/rest-with-scala/archive/master.zip), or even better, just use Git to clone the source repository.

Downloading the ZIP file

If you've downloaded the ZIP file, just unzip it to a directory of your choice:

Joss-MacBook-Pro:Downloads jos$ unzip rest-with-scala-master.zip

Using Git to clone the repository

Cloning the repository is also very easy if you've already got Git installed. If you haven't got Git installed, follow the instructions at https://git-scm.com/book/en/v2/Getting-Started-Installing-Git.

Once Git is installed, just run the following command:

Joss-MacBook-Pro:git jos$ git clone https://github.com/josdirksen/rest-with-scala
Cloning into 'rest-with-scala'...
remote: Counting objects: 4, done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 4 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (4/4), done.
Checking connectivity... done.

At this point, you've got the sources in a directory of your choice. Next, we need to make sure we can download all the frameworks' dependencies and run the samples. For this, we'll use SBT (more information can be found at http://www.scala-sbt.org/), which is the most common build tool for Scala-based projects.

 

Setting up Scala and SBT to run the examples


To run the examples provided in this book, we need to install Scala and SBT. Depending on your operating system, different steps need to be taken.

Installing Java

Before we can install SBT and Scala, we first need to install Java. Scala requires at least a Java Runtime version of 1.6 or higher. If you haven't installed Java on your system yet, follow the instructions at http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html.

Installing Scala and SBT

Once you have Java installed, installing Scala and SBT is just as easy. To install Scala, just go to http://www.scala-lang.org/download/ and download the binaries for your system. To install SBT, you can follow the instructions at http://www.scala-sbt.org/download.html.

To check whether everything is installed, run the following commands in a terminal:

Joss-MacBook-Pro:~ jos$ java -version
java version "1.8.0_40"
Java(TM) SE Runtime Environment (build 1.8.0_40-b27)
Java HotSpot(TM) 64-Bit Server VM (build 25.40-b25, mixed mode)
Joss-MacBook-Pro:~ jos$ scala -version
Scala code runner version 2.11.6 -- Copyright 2002-2013, LAMP/EPFL
Joss-MacBook-Pro:~ jos$ sbt -v
[process_args] java_version = '1.8.0_40'
# Executing command line:
java
-Xms1024m
-Xmx1024m
-XX:ReservedCodeCacheSize=128m
-XX:MaxMetaspaceSize=256m
-jar
/usr/local/Cellar/sbt/0.13.8/libexec/sbt-launch.jar

[info] Set current project to jos (in build file:/Users/jos/)

To exit SBT, hit Ctrl + C.

Running the examples

Now that you've got Java, Scala, and SBT installed, we can run the examples. You can, of course, run the examples from your IDE (see the next section on how to set up IntelliJ IDEA and Eclipse), but often, using SBT directly is just as easy. To run the examples, take the following steps:

  1. Open a terminal and go to the directory where you've extracted the source ZIP file or cloned the repository.

  2. To test the configuration, we've created a simple HelloWorld example. From the console, execute sbt runCH01-HelloWorld:

    Joss-MacBook-Pro:rest-with-scala jos$ sbt runCH01-HelloWorld
    [info] Loading project definition from /Users/jos/dev/git/rest-with-scala/project
    [info] Set current project to rest-with-scala (in build file:/Users/jos/dev/git/rest-with-scala/)
    [info] Compiling 2 Scala sources to /Users/jos/dev/git/rest-with-scala/chapter-01/target/scala-2.11/classes...
    [info] Running org.restwithscala.chapter1.HelloWorld
    SBT successfully ran HelloWorld, configuration seems ok!
    Press <enter> to exit.
    
    [success] Total time: 18 s, completed Jun 13, 2015 2:34:41 PM
    Joss-MacBook-Pro:rest-with-scala jos$
    
  3. You might see a lot of output when the various dependencies are loaded, but after a while, you should see the message, SBT successfully ran HelloWorld, configuration seems ok!.

  4. All the examples in this book wait for user input to terminate. So, once you're done playing around with the example, just hit Enter to terminate the running program.

In each chapter, we'll see the sbt command we need to execute. If you want to know all the examples you can run, you can also run the sbt alias command, which generates the following output:

Joss-MacBook-Pro:rest-with-scala jos$ sbt alias
[info] Loading project definition from /Users/jos/dev/git/rest-with-scala/project
[info] Set current project to rest-with-scala (in build file:/Users/jos/dev/git/rest-with-scala/)
        runCH01-HelloWorld = ; chapter01/runCH01HelloWorld
        runCH01-EchoServer = ; chapter01/runCH01EchoServer

Besides running the examples directly from the command line, it is also possible to run them from an IDE. In the following section, we'll see how to import the examples in IntelliJ IDEA and Eclipse.

 

Setting up the IDE


With SBT and Scala installed, you have everything you need to run the examples. Sometimes, however, it is easier to play around and experiment with the examples directly from an IDE. The two most popular IDEs for working with Scala are IntelliJ IDEA and Eclipse. Both have great Scala plugins and excellent support for SBT.

Setting up IntelliJ IDEA

IntelliJ provides a community and a commercial version of its IDE, both of which can be used to run and play around with the examples in this book. The following steps are shown for the community edition, but can be applied in the same manner for the commercial variant:

  1. The first thing to do is download the IDE. You can download a version for your OS from https://www.jetbrains.com/idea/download/. Once downloaded, run the installer and start the IDE. When you run IntelliJ for the first time, you're asked whether you want to install the featured plugins. Scala is one of them:

  2. From here, click on Install below the Scala column to install Scala support in IntelliJ. After installing, click on Start using IntelliJ IDEA. After IntelliJ is started, you're shown a screen where you can import an existing project:

  3. From here, select Import Project, and on the screen that opens, navigate to the directory where we extracted the downloaded sources, select that directory, and click on OK. On the screen that opens, select the Import Project from external model radio button and next, select SBT.

  4. Now click on Next and fill in the screen that opens:

    1. Check the Download sources and docs checkbox.

    2. For Project SDK, click on New, select JDK, and navigate to the directory where you installed the JDK 1.8.

    3. And finally, click on Finish.

IntelliJ will now import all the projects and download all the required dependencies. Once done, you're shown a screen like this, where you see all the projects and can run the examples directly from the IDE:

An alternative to using IntelliJ IDEA with great Scala support is Eclipse.

Setting up Eclipse

The Scala community provides a packaged version of Eclipse that contains everything you need for developing Scala.

  1. To install this version of Eclipse, first download the version for your OS from their download site at http://scala-ide.org/download/sdk.html.

  2. Once downloaded, extract the archive to a directory of your choice, start Eclipse, and select a location to store your file. Once started, you'll see an empty editor:

  3. Before we can import the project, we must first create the required Eclipse project configuration. To do this, open a terminal and navigate to the directory where you extracted or cloned the sources. From that directory, run sbt eclipse:

    Joss-MacBook-Pro:rest-with-scala jos$ sbt eclipse
    [info] Loading project definition from /Users/jos/dev/git/rest-with-scala/project
    [info] Updating {file:/Users/jos/dev/git/rest-with-scala/project/}rest-with-scala-build...
    [info] Resolving org.fusesource.jansi#jansi;1.4 ...
    [info] Done updating.
    [info] Set current project to rest-with-scala (in build file:/Users/jos/dev/git/rest-with-scala/)
    [info] About to create Eclipse project files for your project(s).
    [info] Successfully created Eclipse project files for project(s):
    [info] chapter-01
    
  4. Now we can import the project. Go to File | Import from the menu and choose to import Existing projects into Workspace. On the next screen, select the directory with the sources as the root directory, and Eclipse should show you all the projects:

  5. Now click on Finish, and the projects will be imported. Now you can edit and run the samples directly from Eclipse.

 

Testing the REST API


Before we look at the API of the service we're going to create, we'll have a quick look at how to test your REST API. We can, of course, create a REST client in Scala and use that, but since a big advantage of REST services is that they can be read and understood by humans, we'll use a simple browser-based (Chrome in this case) REST client called Postman. Note that you can, of course, also use different REST clients. The reason we chose Postman is that with Postman, it is easy to create different kinds of request; it has HATEOAS support and also allows us to share requests, so you don't have to make them by hand.

Installing Postman

Postman runs as a Chrome plugin, so to use this REST client, you need to use Chrome. Once you've started Chrome, open the URL, https://chrome.google.com/webstore/detail/postman-rest-client/fdmmgilgnpjigdojojpjoooidkmcomcm?hl=en in your browser (or just search on Google for Chrome Postman).

Tip

Note that there are two versions of Postman: a simple Chrome plugin, which, at the time of writing, is version 0.8.4.14, and a Chrome app, which currently is at version 3.0.0.6. For this book, we'll use the simpler Chrome plugin, so make sure you install 0.8.4.14 in your browser.

Once installed, open up this app by going to chrome://apps and selecting the application or clicking on the newly added button at the top-right of your screen. When you open this plugin, you should see the following window:

One interesting aspect of Postman is that you can very easily share REST queries. In the sources for this chapter, you can find a directory called common.

Importing request collection

In this directory, there are a number of files which contain the requests for each individual chapter. For instance, for this chapter, these are contained in the file, ch01_requests.json. Each file contains a number of requests that you can use to test the REST frameworks in this book. To import all these requests, take the following steps:

  1. On the left-hand side of the screen, click on the Collections tab.

  2. To the right of this tab, two icons pop up. Click on the right icon, which is called import collection.

  3. On the screen that pops up, click on choose files, navigate to the common directory, and select all the ch0#_requests.json files and open them.

Now, you'll have a number of collections, one for each chapter, where you can find sample requests for the different chapters.

To run a request, just click on a collection. This will show all the requests for that chapter. Click on a request. Now clicking on the Send button will send the request to the server. In the upcoming chapters, we will see which request you can use to test the functionality of a specific Scala REST framework.

Testing the REST service

At this point, we've got Scala and SBT installed, and can use Postman as the REST client. The final step is to see whether everything is working correctly. For this, we'll start a very simple HTTP service, which echoes back a specific request parameter.

Tip

For this example, we've used HTTP4S. This is a basic HTTP server that allows you to quickly create HTTP services. If you're interested, you can find more information about this library at http://http4s.org/. The source code for our simple echo service can be found in the chapter-01/src/main/scala directory.

To run this example, we need to take a couple of steps:

  1. First, open a console window and go to the directory where you downloaded and extracted the sources or cloned the Git repository.

  2. From that directory, run the sbt runCH01-EchoServer command. This will start up the echo service:

    Joss-MacBook-Pro:rest-with-scala jos$ sbt runCH01-EchoServer
    [info] Loading project definition from /Users/jos/dev/git/rest-with-scala/project
    [info] Set current project to rest-with-scala (in build file:/Users/jos/dev/git/rest-with-scala/)
    [info] Running org.restwithscala.chapter1.EchoService
    11:31:24.624 [run-main-0] DEBUG o.http4s.blaze.channel.ServerChannel - Starting server loop on new thread
    Server available on port 8080
    

    Tip

    Downloading the example code

    You can download the example code files from your account at http://www.packtpub.com for all the Packt Publishing books you have purchased. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you.

  3. Now that we've got a server running, open up your Chrome browser, and from there, open Postman (remember, either use the added button or the chrome://apps URL). In the list of collections, click on the request labeled Echo 'hello'. This will open the request. You can now run this request by clicking on the Send button. The result, if everything is configured correctly, will be something like this:

  4. By changing the value of the msg request parameter, you can test that the server is really echoing the user's input.

  5. There are a couple of other requests in this collection that show some features of our current server. You can check what happens when the request parameter is omitted and when a call is made to an unknown URL.

At this point, the only thing left to do in this chapter is to look at the API we'll create using the different frameworks outlined in the upcoming chapters.

 

The REST service and model


To show the features of the various frameworks in this book and how they solve problems in a different manner, we'll define a simple API, which we'll implement with the REST frameworks. For this book, we'll implement a simple to-do list API.

API description

We want to create a RESTful API, so the most important part is to start with the description of the resources that can be managed through this API. For this API, we define the following resources:

Entity

Description

Task

A task is something that needs to be done. The JSON for a task looks similar to this:

{
  "id": long,
  "title": string,
  "content": string,
  "notes": [noteList],
  "status": Status,
     "assignedTo": Person,
}

Project

A project will allow us to group tasks together, and by assigning persons to a project, we can determine who can work on a specific task:

{
  "id": string,
  "title": string,
  "tasks": [task],
  "members": [person],
  "updated": datetime
}

Person

A person is someone who can work on a task and when done, close the task. A person can only work on those tasks to which he is assigned, or when he is part of the project to which a task belongs:

{
  "id": string,
  "name": string
}

Note

Notes can be added to tasks to provide additional information on how the task should be performed:

{
  "id": string,
  "text": string,
}

Without going into too much detail here, we want to support approximately the following functionality in our API:

  • CRUD functionality: We want to support some basic CRUD operations. It should be possible to perform the following actions:

    • Create, update, and delete a new task, project, person, and note.

    • Get a list of tasks, projects, persons, and notes.

    • Search through a list of tasks.

    • Add a note to a task. It should also be possible to update and delete the existing notes.

  • Advanced functions: Besides the standard CRUD-like functionality, we also want to provide some more advanced features:

    • Assign a task to a specific project

    • Assign a person to a task

    • Assign a person to a project

    • Move a task from one project to another

Note that we won't implement all the functionality for each framework. We'll mainly use this API to explain how we can use the various REST frameworks.

 

Summary


That's it for the first chapter. In this chapter, we introduced what REST is, and which level of the Robertsons Maturity Model we'll be aiming at (Level 2). We'll explain HATEOAS in the final chapter. At this point, you should have Scala and SBT installed, and should be able to run all the examples in this book using SBT and test them using the supplied requests in Postman. We also saw how to use IDEs to play around with the code. And finally, we introduced the high-level API that we'll implement in the upcoming chapters.

In the next chapter, we'll dive into the first of the Scala frameworks we'll explore. The first one is Finch, which is a REST library on top of the networking library, Finagle. Both of these were initially created by Twitter.

About the Author

  • Jos Dirksen

    Jos Dirksen has worked as a software developer and architect for more than a decade. He has a lot of experience in a large range of technologies, ranging from backend technologies, such as Java and Scala, to frontend development using HTML5, CSS, and JavaScript. Besides working with these technologies, Jos also regularly speaks at conferences and likes to write about new and interesting technologies on his blog. He also likes to experiment with new technologies and see how they can best be used to create beautiful data visualizations. He is currently working as a freelance full-stack engineer on various Scala and JavaScript project. Previously, Jos has worked in many different roles in the private and public sectors, ranging from private companies such as ING, ASML, Malmberg, and Philips to organizations in the public sector, such as the Department of Defense.

    Browse publications by this author

Latest Reviews

(6 reviews total)
Very interesting. It exceeded my expectations.
Warrig en geen prettige opmaak
Excellent
Book Title
Access this book, plus 7,500 other titles for FREE
Access now