Over the weekend, I was researching various frameworks for implementing a REST API. Although I had already started the implementation using Tornado, I wanted to see what else was out there.
And am I glad I looked. I discovered Scalatra which seems to be exactly what I was looking for; a lightweight, sinatra-esque way to map URLs to actions that easily lends itself to testing. I especially like the uber-readable way the tests are written.
Who wouldn’t want to write tests like this?
// taken from http://github.com/alandipert/step class MyScalatraServletTests extends FunSuite with ShouldMatchers with ScalatraTests { // `MyScalatraServlet` is your app which extends ScalatraServlet route(classOf[MyScalatraServlet], "/*") test("simple get") { get("/path/to/something") { status should equal (200) body should include ("hi!") } } }
I cloned the repo, ran the examples and decided my search had ended.
However, while running the example was easy enough, I wasn’t sure of how to get started with an actual app. It looked especially cryptic since I haven’t ever used maven or sbt. I even considered bailing on scalatra for the well-known shores of tornadoweb. But, since I recently started working with Java at work, I decided to stick it out.
I’m glad I did because sbt is a pleasure to use, especially if you take the time to RTFM.
Anyway, here are the basic steps to help cut down the 0 to 60 time when starting scalatra
Pre-reqs:
Install java, I have java 1.6.
Setup sbt as per these instructions.
Good, now we are ready to start.
Create a new sbt project “HelloScalatra”
mkdir HelloScalatra cd HelloScalatra sbt # fill out the other inputs as you want but make sure you enter 2.8.0 as scala version.
Create a project definition for sbt and save it under project/build. Here’s a barebones one, refer to the docs if you want more info on creating sbt build configs.
// save as project/build/HelloScalatraBuild.scala import sbt._ class HelloScalatraBuild(info: ProjectInfo) extends DefaultWebProject(info) { // scalatra val sonatypeNexusSnapshots = "Sonatype Nexus Snapshots" at "https://oss.sonatype.org/content/repositories/snapshots" val sonatypeNexusReleases = "Sonatype Nexus Releases" at "https://oss.sonatype.org/content/repositories/releases" val scalatra = "org.scalatra" %% "scalatra" % "2.0.0-SNAPSHOT" // jetty val jetty6 = "org.mortbay.jetty" % "jetty" % "6.1.22" % "test" val servletApi = "org.mortbay.jetty" % "servlet-api" % "2.5-20081211" % "provided" }
Tell sbt to account for the new dependencies:
#from project root
sbt updateWe have the basic dependencies taken care of, so let’s create our class that will serve requests. Create “HelloScalatra.scala” under src/main/scala/com/helloscalatra with the following content:
// save as src/main/scala/com/helloscalatra/HelloScalatra.scala package com.helloscalatra import org.scalatra._ class HelloScalatra extends ScalatraServlet with UrlSupport { before { contentType = "text/html" } get("/") { <html> <head> <title> My first scalatra webapp</title> </head> <body> <h1> Hello Scalatra </h1> </body> </html> } protected def contextPath = request.getContextPath }
The last thing we need to do is setup web.xml to tell jetty what to do:
// save as src/main/webapp/WEB-INF/web.xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN" "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd"> <web-app> <servlet> <servlet-name>HelloScalatra</servlet-name> <servlet-class>com.helloscalatra.HelloScalatra</servlet-class> </servlet> <servlet-mapping> <servlet-name>HelloScalatra</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping> </web-app>
Great! We should be good to go ![]()
Go to project root and startup the sbt console:
sbt
and start jetty:
>jetty-runTADA!
Navigate over to localhost:8080 to see the webapp in action.
This was real helpful.
I found though, that I had to run the “reload” command before running the “update” command.
BTW, I’m glad I found scalatra too.
Do you know how I can package the code into a war file using sbt to be deployed into another jetty container rather than the one that comes with the framework?
Thank you!
Joyce
Hi Joyce,
I havent tried, but this thread may be of help: http://groups.google.com/group/scalatra-user/browse_thread/thread/955758566e0b028f/b53db2cbf38205ce?lnk=gst&q=war#b53db2cbf38205ce.
Note that this infomation is probably out of date so your best bet may be to post to the google group or ask on the irc channel for scalatra.
Ross is very good about answering questions.
Thanks for writing this up… it was just what I needed get me started!
Take also a look at http://bowlerframework.org/ if you’re interested in REST framework based on scalatra.
@Joyce
run the command :
sbt package
Then navigate to your /target/scala…/…war file
Drop this file into your /webapps/ directory of your jetty install
Good to go!