This is an excerpt from the Scala Cookbook (partially modified for the internet). This is Recipe 15.5, “How to create simple Scala web services with Scalatra.”
Problem
You want to be able to build new web services with Scalatra, a lightweight Scala web framework similar to the Ruby Sinatra library.
Solution
The recommended approach to create a new Scalatra project is to use Giter8, a great tool for building SBT directories for new projects.
Assuming you have Giter8 installed, use the g8
command to create a new project with a Scalatra template:
$ g8 scalatra/scalatra-sbt organization [com.example]: com.alvinalexander package [com.example.app]: com.alvinalexander.app name [My Scalatra Web App]: scalatra_version [2.2.0]: servlet_name [MyScalatraServlet]: scala_version [2.10.0]: version [0.1.0-SNAPSHOT]: Template applied in ./my-scalatra-web-app
When Giter8 finishes, move into the new directory it created:
$ cd my-scalatra-web-app
Start SBT in that directory, and then issue the container:start
command to start the Jetty server:
$ sbt > container:start // a lot of output here ... [info] Started SelectChannelConnector@0.0.0.0:8080 [success] Total time: 11 s, completed May 13, 2013 4:32:08 PM Then use the following command to enable continuous compilation: > ~ ;copy-resources;aux-compile 1. Waiting for source changes... (press enter to interrupt)
That command is nice; it automatically recompiles your source code when it changes. The Jetty server starts on port 8080
by default. If you switch to a browser and go to the URL http://localhost:8080/, you should see some default “Hello, world” output, indicating that Scalatra is running.
The content displayed at this URL comes from a class named MyScalatraServlet
, located in the project’s src/main/scala/com/alvinalexander/app directory:
package com.alvinalexander.app import org.scalatra._ import scalate.ScalateSupport class MyScalatraServlet extends MyScalatraWebAppStack { get("/") { <html> <body> <h1>Hello, world!</h1> Say <a href="hello-scalate">hello to Scalate</a>. </body> </html> } }
That’s the entire servlet. If you’re used to building web services with “heavier” tools, this can be quite a shock.
The get
method shown declares that it’s listening to GET
requests at the / URI. If you try accessing another URL like http://localhost:8080/foo in your browser, you’ll see output like this in the browser:
Requesting "GET /foo" on servlet "" but only have: GET /
This is because MyScalatraServlet
only has one method, and it’s programmed to listen for a GET
request at the / URI.
Add a new service
To demonstrate how the process of adding a new web service works, add a new method that listens to GET
requests at the /hello URI. To do this, just add the following method to the servlet:
get("/hello") { <p>Hello, world!</p> }
A few moments after saving this change to MyScalatraServlet
, you should see some output in your SBT console. An abridged version of the output looks like this:
[info] Compiling 1 Scala source to target/scala-2.10/classes... [success] Total time: 8 s [info] Generating target/scala-2.10/resource_managed/main/rebel.xml. [info] Compiling Templates in Template Directory: src/main/webapp/WEB-INF/templates [success] Total time: 1 s, completed May 28, 2013 1:56:36 PM 2. Waiting for source changes... (press enter to interrupt)
As a result of the ~ aux-compile
command, SBT automatically recompiles your source code. Once the code is recompiled, you can go to the http://localhost:8080/hello URL in your browser, where you’ll see the new output.
Congratulations. By following the steps in this recipe, you should have a web service up and running in a matter of minutes.
Discussion
Giter8 is a tool for creating SBT project directory structures based on templates. The template used in this example is just one of many Giter8 templates. Giter8 requires SBT and another tool named Conscript. Despite these requirements, the overall installation process is simple, and is described in Recipe 18.1.
In addition to the MyScalatraServlet
class, this list shows some of the most important files in your project:
project/build.scala project/plugins.sbt src/main/resources/logback.xml src/main/scala/com/alvinalexander/app/MyScalatraServlet.scala src/main/scala/com/alvinalexander/app/MyScalatraWebAppStack.scala src/main/scala/ScalatraBootstrap.scala src/main/webapp/WEB-INF/web.xml src/main/webapp/WEB-INF/templates/layouts/default.jade src/main/webapp/WEB-INF/templates/views/hello-scalate.jade src/test/scala/com/alvinalexander/app/MyScalatraServletSpec.scala
Notice that this includes a WEB-INF/web.xml file. If you’re used to the Java web programming world, you’ll find that this is a normal web.xml file, albeit a very small one. Excluding the boilerplate XML, it has only this entry:
<listener> <listener-class>org.scalatra.servlet.ScalatraListener</listener-class> </listener>
You’ll rarely need to edit this file. Recipe 15.6, “Replacing XML Servlet Mappings with Scalatra Mounts” shows one instance where you’ll need to make a small change to it, but that’s it.
As shown in the list of files, an interesting thing about the current Giter8 template for Scalatra is that it uses a project/build.scala file rather than a build.sbt file. You can find all of Scalatra’s dependencies in that file, including the use of tools like the Scalate template engine, specs2, Logback, and Jetty.
this post is sponsored by my books: | |||
#1 New Release |
FP Best Seller |
Learn Scala 3 |
Learn FP Fast |