<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-3647364277628708564</id><updated>2012-02-16T03:54:50.048-08:00</updated><category term='MongoDB'/><category term='Scala'/><category term='g8'/><category term='Lift-Json'/><category term='scala mongodb casbah'/><category term='Maven'/><category term='REST'/><category term='Specs'/><category term='SBT'/><category term='scala scalatra mongodb casbah sbt g8'/><category term='Scalatra'/><category term='Casbah'/><category term='Java'/><category term='assembly'/><title type='text'>Janx Spirit</title><subtitle type='html'>Oh don't give me none more of that Old Janx Spirit.
No, don't you give me none more of that Old Janx Spirit.
For my head will fly, my tongue will lie, my eyes will fry and I may die.
Won't you pour me one more of that sinful Old Janx Spirit.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://janxspirit.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3647364277628708564/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://janxspirit.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Gregg</name><uri>http://www.blogger.com/profile/03402091100291504512</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_4Cpi3vSt5Is/TT-unx8TWYI/AAAAAAAAGx8/3yNKJUn2s8c/s400/P1112170.JPG'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>7</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-3647364277628708564.post-695456157178013283</id><published>2011-11-20T20:45:00.000-08:00</published><updated>2011-11-20T21:13:00.135-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='scala mongodb casbah'/><title type='text'>Introduction to Casbah - The Scala MongoDB Driver</title><content type='html'>I've been meaning to point out the sheer coolness of the Scala MongoDB driver - Casbah. Written and maintained by 10Gen's own Brendan McAdamas, it is a truly elegant way to interact with MongoDB. If you've been using the Java driver, this might be a fun way to try out some Scala.&lt;br /&gt;&lt;br /&gt;Here are some examples, none of which will be too surprising, since they look so much like interacting with Mongo via the shell client. Really that's the nice thing about Casbah - it's much closer to using the Python driver or JavaScript shell than the Java map-style driver. &lt;br /&gt;&lt;br /&gt;I'll demonstrate some more advanced usage in the future, but this will get you started.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: scala"&gt;&lt;br /&gt;    //connect to a MongoDB server&lt;br /&gt;    val mongo = MongoConnection("anduin")&lt;br /&gt;&lt;br /&gt;    //create/connect to a collection&lt;br /&gt;    val coll = mongo("casbah_examples")("movies")&lt;br /&gt;&lt;br /&gt;    //drop collection&lt;br /&gt;    coll.dropCollection&lt;br /&gt;&lt;br /&gt;    //create some documents&lt;br /&gt;    val pf = MongoDBObject("title" -&gt; "Pulp Fiction",&lt;br /&gt;                           "director" -&gt; "Quentin Tarantino",&lt;br /&gt;                           "foo" -&gt; "bar",&lt;br /&gt;                           "actors" -&gt; List("John Travolta", "Samuel L Jackson"),&lt;br /&gt;                           "year" -&gt; 1994)&lt;br /&gt;&lt;br /&gt;    val sw = MongoDBObject("title" -&gt; "Star Wars",&lt;br /&gt;                           "director" -&gt; "George Lucas",&lt;br /&gt;                           "cast" -&gt; List("Harrison Ford", "Carrie Fisher"),&lt;br /&gt;                           "year" -&gt; 1977)&lt;br /&gt;&lt;br /&gt;     val fc = MongoDBObject("title" -&gt; "Fight Club",&lt;br /&gt;                           "director" -&gt; "David Fincher",&lt;br /&gt;                           "cast" -&gt; List("Brad Pitt", "Edward Norton"),&lt;br /&gt;                           "year" -&gt; 1999)&lt;br /&gt;&lt;br /&gt;    //add some documents&lt;br /&gt;    coll += pf&lt;br /&gt;    coll += sw&lt;br /&gt;    coll += fc&lt;br /&gt;    val pfid = MongoDBObject("_id" -&gt; pf.get("_id"))&lt;br /&gt;&lt;br /&gt;    //update a document&lt;br /&gt;    //increment a value (or set it if the value does not exist)&lt;br /&gt;    coll.update(pfid, $inc("likes" -&gt; 1))&lt;br /&gt;&lt;br /&gt;    //set a value&lt;br /&gt;    coll.update(pfid, $set("year" -&gt; 1994))&lt;br /&gt;&lt;br /&gt;    //remove a field&lt;br /&gt;    coll.update(pfid, $unset("foo"))&lt;br /&gt;&lt;br /&gt;    //add a value to an array - create it if need be&lt;br /&gt;    coll.update(pfid, $push("comebackKids" -&gt; "John Travolta"))&lt;br /&gt;&lt;br /&gt;    //add a bunch of values to an array&lt;br /&gt;    coll.update(pfid, $pushAll("comebackKids" -&gt; ("Bruce Willis", "Uma Thurman")))&lt;br /&gt;&lt;br /&gt;    //add to a set (only adds values that were not there already)&lt;br /&gt;    coll.update(pfid, $addToSet("actors") $each("John Travolta","Groucho Marx","Harpo Marx","Alyssa Milano","Bruce Willis","Uma Thurman", "Jim Carrey"))&lt;br /&gt;&lt;br /&gt;    //remove last element of an array - use -1 to remove the first element&lt;br /&gt;    coll.update(pfid, $pop("actors" -&gt; 1))&lt;br /&gt;&lt;br /&gt;    //remove matching elements from a field&lt;br /&gt;    coll.update(pfid, $pull("actors" -&gt; "Alyssa Milano"))&lt;br /&gt;&lt;br /&gt;    //remove more than one matching element from a field&lt;br /&gt;    coll.update(pfid, $pullAll("actors" -&gt; ("Groucho Marx", "Harpo Marx")))&lt;br /&gt;&lt;br /&gt;    //rename a field&lt;br /&gt;    coll.update(pfid, $rename("actors" -&gt; "cast"))&lt;br /&gt;&lt;br /&gt;    //query documents&lt;br /&gt;    //find one by an exact field match&lt;br /&gt;    coll.findOne(MongoDBObject("title" -&gt; "Star Wars"))&lt;br /&gt;&lt;br /&gt;    //find by regex&lt;br /&gt;    coll.find(MongoDBObject("title" -&gt; ".*F".r))&lt;br /&gt;&lt;br /&gt;    //leave out the ids&lt;br /&gt;    coll.find(MongoDBObject(),MongoDBObject("_id" -&gt; 0))&lt;br /&gt;&lt;br /&gt;    //include only certain fields without ids&lt;br /&gt;    coll.find(MongoDBObject(), MongoDBObject("title" -&gt; 1, "cast" -&gt; 1, "_id" -&gt; 0))&lt;br /&gt;&lt;br /&gt;    //find most recent&lt;br /&gt;    coll.find(MongoDBObject()).sort(MongoDBObject("year" -&gt; -1)).limit(1)&lt;br /&gt;&lt;br /&gt;    //remove&lt;br /&gt;    coll.remove(MongoDBObject("title" -&gt; "Fight Club"))&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3647364277628708564-695456157178013283?l=janxspirit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://janxspirit.blogspot.com/feeds/695456157178013283/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://janxspirit.blogspot.com/2011/11/introduction-to-casbah-scala-mongodb.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3647364277628708564/posts/default/695456157178013283'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3647364277628708564/posts/default/695456157178013283'/><link rel='alternate' type='text/html' href='http://janxspirit.blogspot.com/2011/11/introduction-to-casbah-scala-mongodb.html' title='Introduction to Casbah - The Scala MongoDB Driver'/><author><name>Gregg</name><uri>http://www.blogger.com/profile/03402091100291504512</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_4Cpi3vSt5Is/TT-unx8TWYI/AAAAAAAAGx8/3yNKJUn2s8c/s400/P1112170.JPG'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3647364277628708564.post-1099701133287502706</id><published>2011-09-24T23:43:00.000-07:00</published><updated>2011-09-25T00:03:17.744-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='scala scalatra mongodb casbah sbt g8'/><title type='text'>Scalatra MongoDB Executable Jar Template</title><content type='html'>Just a quick note that I have updated my giter8 template for a simple Scalatra project using MongoDB. It now uses library versions that are available for Scala 2.9.1 and updates some dependency versions. These dependencies/plugins target SBT 0.10.1 and probably won't work well with other versions. I also added the assembly plugin to make it easy to build an executable jar. I didn't bother to branch since the old one was broken due to some dependency issues.&lt;br /&gt;&lt;br /&gt;To start a new project, do the following:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;Install &lt;a href="https://github.com/n8han/giter8"&gt;giter8&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;g8 JanxSpirit/scalatra-mongodb&lt;/li&gt;&lt;br /&gt;&lt;li&gt;cd *project-name*&lt;/li&gt;&lt;br /&gt;&lt;li&gt;sbt&lt;/li&gt;&lt;br /&gt;&lt;li&gt;jetty-run&lt;/li&gt;&lt;br /&gt;&lt;li&gt;browse to &lt;a href="http://localhost:8080/test"&gt;http://localhost:8080/test&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;If you want an executable jar, run 'assembly' at the SBT prompt&lt;/li&gt;&lt;br /&gt;&lt;li&gt;If you want to create a standalone shell command wrapping that jar, run something like 'cat src/main/resources/execute_jar.sh target/scalatra-mongodb-project-assembly-1.0.jar &gt; target/scalatra_mongo'&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt; &lt;br /&gt;&lt;br /&gt;Hopefully this template is helpful. Cheers!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3647364277628708564-1099701133287502706?l=janxspirit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://janxspirit.blogspot.com/feeds/1099701133287502706/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://janxspirit.blogspot.com/2011/09/scalatra-mongodb-executable-jar.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3647364277628708564/posts/default/1099701133287502706'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3647364277628708564/posts/default/1099701133287502706'/><link rel='alternate' type='text/html' href='http://janxspirit.blogspot.com/2011/09/scalatra-mongodb-executable-jar.html' title='Scalatra MongoDB Executable Jar Template'/><author><name>Gregg</name><uri>http://www.blogger.com/profile/03402091100291504512</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_4Cpi3vSt5Is/TT-unx8TWYI/AAAAAAAAGx8/3yNKJUn2s8c/s400/P1112170.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3647364277628708564.post-6660282404668275635</id><published>2011-06-12T13:44:00.000-07:00</published><updated>2011-06-12T14:30:06.341-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Scala'/><category scheme='http://www.blogger.com/atom/ns#' term='SBT'/><category scheme='http://www.blogger.com/atom/ns#' term='Scalatra'/><category scheme='http://www.blogger.com/atom/ns#' term='MongoDB'/><category scheme='http://www.blogger.com/atom/ns#' term='g8'/><category scheme='http://www.blogger.com/atom/ns#' term='Casbah'/><title type='text'>Scalatra MongoDB template project using SBT 0.10.x</title><content type='html'>I spent some time this weekend getting a basic Scalatra/Casbah/MongoDB project (much like the one I covered in &lt;a href="http://janxspirit.blogspot.com/2011/01/quick-webb-app-with-scala-mongodb.html"&gt;this post&lt;/a&gt;) set up using SBT 0.10.0.&lt;br /&gt;&lt;br /&gt;If you have looked at the newest version of &lt;a href="https://github.com/harrah/xsbt"&gt;SBT&lt;/a&gt;, you know that a lot has changed. SBT 0.7.x projects will not build under the newer versions without a bit of migration. I ran into some hiccups along the way, so I set up a template project to avoid having to figure it out again. It uses Nathen Hamblen's fantastic &lt;a href="https://github.com/n8han/giter8"&gt;giter8(g8)&lt;/a&gt; tool to allow you to set up a new project in seconds. Hopefully other g8 users find this template useful.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;Changes in SBT 0.10.x&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I just want to note some of the changes I ran into in setting up this very simple project:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;b&gt;build.sbt file&lt;/b&gt; - SBT 0.10.x offers an alternative to the /project/build/Project.scala configuration file - you can put a *.sbt file in the root of your project and configure your project there using the new SBT DSL. You can still configure your project using Scala, but the API and file locations have changed. See the SBT documentation for details.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;b&gt;"jetty" context for the Jetty dependency&lt;/b&gt; - this one confused me as I didn't see it documented anywhere. The Jetty dependency in build.sbt should not use the "test" scope as it did with SBT 0.7.x but rather the "jetty" scope. Using "test" will cause the jetty-run command to silently fail in a most unhelpful way.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;b&gt;Jetty support no longer built-in&lt;/b&gt; - Unlike SBT 0.7.x which provided commands like jetty-run, jetty-stop and prepare-webapp for any Project extending DefaultWebProject, SBT 0.10.x requires a &lt;a href="https://github.com/siasia/xsbt-web-plugin"&gt;plugin&lt;/a&gt; to support web applications. See the project's homepage for setup and my template project for an example.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;Template Project&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;You'll need to install SBT 0.10.x - &lt;a href="https://github.com/harrah/xsbt"&gt;README&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;You'll also need to install &lt;a href="https://github.com/n8han/giter8"&gt;g8&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Both tools are very easy one-time installs and worth having. Once they are installed, you should be able to run:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: bash"&gt;&lt;br /&gt;g8 JanxSpirit/scalatra-mongodb&lt;br /&gt;cd *name-of-app*&lt;br /&gt;sbt&lt;br /&gt;&gt; update&lt;br /&gt;&gt; jetty-run&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;You'll then be able to browse to &lt;a href="http://localhost:8080/test"&gt;the test resource&lt;/a&gt; to make sure it's working.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;What's inside&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The servlet provides two resources:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;'test' - a 'Hello World' type resource just to make sure everything is working.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;'msgs' - GET msgs to see all records currently in the database and a form to add another record - the form issues a POST to the same resource to add records&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;The project includes a few basic tests to get you started. Run 'sbt test' to see the test output.&lt;br /&gt;&lt;br /&gt;The template allows you to configure where your MongoDB server is running, the name of your servlet and other parameters.&lt;br /&gt;&lt;br /&gt;All source code is here: &lt;a href="https://github.com/JanxSpirit/scalatra-mongodb.g8"&gt;https://github.com/JanxSpirit/scalatra-mongodb.g8&lt;/a&gt; I'd welcome any comments or suggestions or pull requests. Happy coding!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3647364277628708564-6660282404668275635?l=janxspirit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://janxspirit.blogspot.com/feeds/6660282404668275635/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://janxspirit.blogspot.com/2011/06/scalatra-mongodb-template-project-using.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3647364277628708564/posts/default/6660282404668275635'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3647364277628708564/posts/default/6660282404668275635'/><link rel='alternate' type='text/html' href='http://janxspirit.blogspot.com/2011/06/scalatra-mongodb-template-project-using.html' title='Scalatra MongoDB template project using SBT 0.10.x'/><author><name>Gregg</name><uri>http://www.blogger.com/profile/03402091100291504512</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_4Cpi3vSt5Is/TT-unx8TWYI/AAAAAAAAGx8/3yNKJUn2s8c/s400/P1112170.JPG'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3647364277628708564.post-4243737576265422884</id><published>2011-06-05T17:18:00.001-07:00</published><updated>2011-06-05T17:18:20.542-07:00</updated><title type='text'>Java Without Semicolons: An Introduction to Scala - Part 1: Iteration</title><content type='html'>This series of posts was inspired by a suggestion from Martin Oedersky at Scala Days 2011 as well as something I have heard Dick Wall say on several occasions. To paraphrase Dick, you can get started with Scala by converting Java code to Scala with few changes beyond getting rid of the semicolons. It may not take advantage of many of Scala's more powerful features, but it's a great way to get started and an excellent jumping off point to learning Scala's richer language features.&lt;br /&gt;&lt;br /&gt;Scala is a deep and flexible language that allows an enormous degree of freedom to library developers and advanced users, but those features can be daunting to new developers trying to take them all in. So, what areas should a Java programmer getting started with Scala start with? This blog series will cover Scala features that Java programmers should be able to put to immediate use. In other words, I'll suggest some of the first things a newcomer to Scala can try after getting rid of the semicolons.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;Setup&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;You're encouraged to follow along with these examples in the Scala REPL and use them as a jumping off point for your own exploration. Installing Scala is easy - if you already have Java set up, just unzip the Scala distribution, set SCALA_HOME and add $SCALA_HOME/bin to your path. You can run the REPL by simply typing 'scala' in a shell. Further instructions at scala-lang.org or typesafe.com. I'll be using Scala 2.9.0.1 which is the latest version at the time of this writing.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;Iteration&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;As a longtime Java developer, I was immediately drawn to Scala's alternatives to for-loop iteration. Java loops are easy enough to write, but can be buggy and confusing to read and comprehend.&lt;br /&gt;&lt;br /&gt;This post will take a look at some functions Scala Collections provide to iterate that are as easy to read and understand as they are to write.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;Function Literals&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Assuming that Java is the only language you are familiar with, there's one important Scala language feature you'll need to understand in these examples, and that is function literals.&lt;br /&gt;&lt;br /&gt;A function literal is analogous to String or int literals in Java in that it is a value that can be provided directly where it is used.&lt;br /&gt;&lt;br /&gt;In Scala, you can define a function inline - that is pass a bit of functionality right where it is needed. This is what a simple function literal looks like:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: scala"&gt;x =&gt; x + 1&lt;/pre&gt;&lt;br /&gt;You can read this as "a function that take one argument x and returns the result of adding 1 to the value of x". &lt;br /&gt;&lt;br /&gt;Scala's collections have special functions that take functions as arguments to be applied to the members of the collection. So unlike a Java for loop, where you get a handle on each member in the collection one at a time and do something to it, in Scala you can tell the collection to apply some functionality to all of its members and the actual iteration over elements is handled internally. Building on our example:&lt;br /&gt;&lt;pre class="brush: scala"&gt;&lt;br /&gt;val someInts = List(4, 8, 15, 16, 23, 42)&lt;br /&gt;val incrementedInts = someInts.map(x =&gt; x + 1)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The map function takes a single-argument function as its argument. It applies that function to every element in the List and returns a new List whose contents are the result of applying the function argument. In the example above, each element of the list is incremented by 1 and the result looks like this:&lt;br /&gt;&lt;pre class="brush: scala"&gt;&lt;br /&gt;List(5, 9, 16, 17, 24, 43)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Note that the original list still exists unmodified.&lt;br /&gt;&lt;br /&gt;In Scala code you will often see a shorter form of function literals. Scala allows us to substitute a _ character for the function parameters in many cases, so the above map call could be written as:&lt;br /&gt;&lt;pre class="brush: scala"&gt;&lt;br /&gt;val incrementedInts = someInts.map(_ + 1)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The two are functionally identical, and it's up to you which you want to use.&lt;br /&gt;&lt;br /&gt;In some cases the function literal can be even shorter. When the function passed as an argument takes a single argument itself, Scala will automatically pass each element of the collection to it without even needing the _. The following examples are functionally equivalent and use the foreach function, which is executed only for side effects and does not return a value (it returns Unit, equivalent to Java's void return type).&lt;br /&gt;&lt;pre class="brush: scala"&gt;&lt;br /&gt;someInts.foreach(x =&gt; println(x))&lt;br /&gt;someInts.foreach(println(_))&lt;br /&gt;someInts.foreach(println)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now let's say we only want the subset of our list that is odd numbers. The filter function is useful for such operations. It takes a function argument that returns a boolean to determine whether an element should be included in the output:&lt;br /&gt;&lt;pre class="brush: scala"&gt;&lt;br /&gt;someInts.filter(x =&gt; x % 2 == 1)&lt;br /&gt;//someInts.filter(_ % 2 == 1)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Maybe we want the first number in the list that is greater than 20. We can use find:&lt;br /&gt;&lt;pre class="brush: scala"&gt;&lt;br /&gt;someInts.find(x =&gt; x &gt; 20)&lt;br /&gt;//someInts.find(_ &gt; 20)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;If you want to discover whether all elements of a collection satisfy some requirement, use forall, which takes a function that returns boolean and itself returns a boolean:&lt;br /&gt;&lt;pre class="brush: scala"&gt;&lt;br /&gt;someInts.forall(x =&gt; x &gt; 0)&lt;br /&gt;//someInts.forall(_ &gt; 0)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;You can get the first n elements that meet a certain requirement by using takeWhile. The following example returns a new list containing all of the words up to the first word that begins with a vowel:&lt;br /&gt;&lt;pre class="brush: scala"&gt;&lt;br /&gt;val words = List("the","quick","brown","fox","jumped","over","the","lazy","dog")&lt;br /&gt;words.takeWhile(w =&gt; !"aeiou".contains(w(0)))&lt;br /&gt;// returns List(the, quick, brown, fox, jumped)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;If you wanted to retain the remainder of the list separately, you can pass the same function to span, which returns a tuple of two Lists:&lt;br /&gt;&lt;pre class="brush: scala"&gt;&lt;br /&gt;words.span(w =&gt; !"aeiou".contains(w(0)))&lt;br /&gt;// returns (List(the, quick, brown, fox, jumped),List(over, the, lazy, dog))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The last example of these sort of collection iteration functions I'll demonstrate is foldLeft. It's a bit different in that it does not return a collection, but rather a single value as a result of applying a two-argument function to each element of a list and the result of the last function execution. You need to provide it a seed value, and the first iteration will execute the function with the seed value and first element of the list. In this example we'll get the sum of all numbers with more than one digit:&lt;br /&gt;&lt;pre class="brush: scala"&gt;&lt;br /&gt;someInts.foldLeft(0)((a,b) =&gt; if (b.toString.length &gt; 1) a+b else a)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;In the example, foldLeft is seeded with a 0. The function is then called with 0 and 4, returning 0. Then 0 and 8 returning 0. Then 0 and 15 returning 15, and so on. Folding operations take a bit of getting used to, but are a powerful functional programming paradigm.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;For Comprehension&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Scala does have a for loop structure that may look more familiar to java developers. In Scala it's called a for comprehension, and it can be used in very powerful ways. It can also be used to iterate over collections in a more imperative way:&lt;br /&gt;&lt;pre class="brush: scala"&gt;&lt;br /&gt;for (word &lt;- words) {&lt;br /&gt;  println(word)&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;But, often the functions on the various Scala collection classes allow you to perform common iteration tasks without using loops. This change can result in fewer more readable lines of code. In Java, even the contrived examples above would necessetate loops, temporary variables, temporary lists, and, in general, more boilerplate code not relating to business logic. The Scala collection libraries allow us to focus on the code that performs the actions we're really interested in. And it makes for some nifty one-liners:&lt;br /&gt;&lt;pre class="brush: scala"&gt;&lt;br /&gt;//find all numbers from 1 to a million that are evenly divisible by 3 and 5, &lt;br /&gt;//remove all instances of the digit '9' and sum the resulting numbers&lt;br /&gt;(1 to 1000000).filter(i =&gt; i % 3 == 0 &amp;&amp; i % 5 == 0).map(_.toString.replace("9","").toInt).sum &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;That's it for this installment. Hopefully someone getting started with Scala finds these examples helpful as a jumping off point.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3647364277628708564-4243737576265422884?l=janxspirit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://janxspirit.blogspot.com/feeds/4243737576265422884/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://janxspirit.blogspot.com/2011/06/java-without-semicolons-introduction-to.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3647364277628708564/posts/default/4243737576265422884'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3647364277628708564/posts/default/4243737576265422884'/><link rel='alternate' type='text/html' href='http://janxspirit.blogspot.com/2011/06/java-without-semicolons-introduction-to.html' title='Java Without Semicolons: An Introduction to Scala - Part 1: Iteration'/><author><name>Gregg</name><uri>http://www.blogger.com/profile/03402091100291504512</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_4Cpi3vSt5Is/TT-unx8TWYI/AAAAAAAAGx8/3yNKJUn2s8c/s400/P1112170.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3647364277628708564.post-6018475226456620273</id><published>2011-02-13T12:00:00.000-08:00</published><updated>2011-02-13T14:53:20.204-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Scala'/><category scheme='http://www.blogger.com/atom/ns#' term='Specs'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='REST'/><category scheme='http://www.blogger.com/atom/ns#' term='Lift-Json'/><category scheme='http://www.blogger.com/atom/ns#' term='Maven'/><title type='text'>Sneaking Scala Through the Alley - Test Java Maven Web Services with Scala Specs</title><content type='html'>It's been said before, but a great way to introduce Scala at work is in writing tests. In my case, that means writing functional tests for web services built with Maven. I've found the &lt;a href="http://code.google.com/p/specs/"&gt;Specs&lt;/a&gt; library excellent for this purpose, and after sorting out a bit of setup, it's integrated into my build well. Some things I like about this approach: &lt;br /&gt;&lt;ul&gt;&lt;li&gt;Tests are concise and quick to write&lt;/li&gt;&lt;li&gt;Specs can be written in natural language, user stories, or however you normally describe software functionality&lt;/li&gt;&lt;li&gt;Output is natural language, so identifying the source of any bugs, regressions, etc is easy&lt;/li&gt;&lt;li&gt;Test code is generally such that developers who are unfamiliar with Scala can understand it quickly&lt;/li&gt;&lt;li&gt;Scala and Specs make it trivial to write focused, single-assertion tests with little boilerplate&lt;/li&gt;&lt;li&gt;Write empty specs as requirements emerge and bugs are found then implement them when you have time&lt;/li&gt;&lt;li&gt;You get to use Scala at work&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;This example will use Maven and a very simple Java REST service built with Jersey. In the real world you'd probably be using Spring and a lot of other libraries, but I've tried to distill this example down to the barest essentials in order to focus on Specs and how it plays with Maven.&lt;br /&gt;&lt;br /&gt;Envision a beer service. It accepts requests for beer by type and size in ounces. It should return a 404 Not Found response if the beer is not a type it knows (Corona, Guiness or Fat Tire). If someone tries to order a beer smaller than a pint, the service should respond with a 400 Bad Request response. And if the service is able to fulfill the request, it should return a Json Beer representation.&lt;br /&gt;&lt;br /&gt;As you work with your design team to specify these behaviors, you can write a first pass at your specs. The great thing about specs is how well they translate from the plain English description above:&lt;br /&gt;&lt;pre class="brush: scala"&gt;&lt;br /&gt;"Calling GET /beer" should {&lt;br /&gt;  "when called with" in {&lt;br /&gt;    "a sizeOunces argument of 4" in {&lt;br /&gt;      "return status 400" &gt;&gt; { }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    "a beer name 'Budweiser'" in {&lt;br /&gt;      "return status 404" &gt;&gt; { }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    "beer name 'Guiness' and sizeOunces 16" in {&lt;br /&gt;      "return status 200" &gt;&gt; { }&lt;br /&gt;      "return a Beer representation" in {&lt;br /&gt;        "with" in {&lt;br /&gt;          "name 'Guiness'" &gt;&gt; {}&lt;br /&gt;          "sizeOunces 16" &gt;&gt; {}&lt;br /&gt;        }&lt;br /&gt;      }&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;You can read each spec from its outermost part to inner, for example: "Calling GET /beer should when called with beer name 'Guiness' and sizeOunces 16 return status 200". You can leave these specs empty until you implement the corresponding functionality. Some build environments like Hudson display the unimplemented tests separately from the passing or failing tests. These unimplemented tests are a great aspect of using Specs. They convey to others what the expected functionality is, though it may not yet be implemented, and it serves as a checklist for you the developer. As new requirements emerge, you can immediately write empty specs that reflect them.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;Setting up pom.xml&lt;/span&gt;&lt;br /&gt;In order to use Scala in a Maven project, you'll need to set up a few plugins, dependencies. etc. I'll highlight the ones that may be unfamiliar to Java developers, and the entire pom.xml is shown below.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Repositories&lt;/span&gt;&lt;br /&gt;I'm not going to get into repository configuration much, since everyone's setup is different. One repository to be aware of when doing Scala development is Scala Tools. It's built into SBT, but you'll need to add it to your Maven repository or project pom to use it in a Maven project.&lt;br /&gt;&lt;pre class="brush: xml"&gt;&lt;br /&gt;        &amp;lt;repository&amp;gt;&lt;br /&gt;            &amp;lt;id&amp;gt;scala-tools.org&amp;lt;/id&amp;gt;&lt;br /&gt;            &amp;lt;name&amp;gt;Scala-tools Maven2 Repository&amp;lt;/name&amp;gt;&lt;br /&gt;            &amp;lt;url&amp;gt;http://scala-tools.org/repo-releases&amp;lt;/url&amp;gt;&lt;br /&gt;        &amp;lt;/repository&amp;gt;&lt;br /&gt;&lt;/pre&gt; &lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Dependencies&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Scala&lt;/span&gt;&lt;br /&gt;This example uses version 2.8.0 of the Scala library.&lt;br /&gt;&lt;pre class="brush: xml"&gt;&lt;br /&gt;        &amp;lt;!-- Scala --&amp;gt;&lt;br /&gt;        &amp;lt;dependency&amp;gt;&lt;br /&gt;            &amp;lt;groupId&amp;gt;org.scala-lang&amp;lt;/groupId&amp;gt;&lt;br /&gt;            &amp;lt;artifactId&amp;gt;scala-library&amp;lt;/artifactId&amp;gt;&lt;br /&gt;            &amp;lt;version&amp;gt;2.8.0&amp;lt;/version&amp;gt;&lt;br /&gt;        &amp;lt;/dependency&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Specs&lt;/span&gt;&lt;br /&gt;&lt;a href="http://code.google.com/p/specs/"&gt;Specs&lt;/a&gt; is a library for &lt;a href="http://en.wikipedia.org/wiki/Behavior_Driven_Development"&gt;Behavior Driven Development&lt;/a&gt; in Scala. It integrates easily with mock libraries, ScalaTest for generating test data, and various IDEs and build tools. Scala Specs can be run as JUnit tests, allowing integration into Java development environments like Eclipse, IntelliJ and NetBeans as well as CI systems like Hudson and Bamboo. It has an excellent lightweight syntax that is easy to read and write. I'll only be scratching the surface of Specs' functionality here, but you should check out the excellent documentation for more examples.&lt;br /&gt;&lt;pre class="brush: xml"&gt;&lt;br /&gt;        &amp;lt;!-- Specs --&amp;gt;&lt;br /&gt;        &amp;lt;dependency&amp;gt;&lt;br /&gt;            &amp;lt;groupId&amp;gt;org.scala-tools.testing&amp;lt;/groupId&amp;gt;&lt;br /&gt;            &amp;lt;artifactId&amp;gt;specs_2.8.0&amp;lt;/artifactId&amp;gt;&lt;br /&gt;            &amp;lt;version&amp;gt;1.6.5&amp;lt;/version&amp;gt;&lt;br /&gt;        &amp;lt;/dependency&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Dispatch&lt;/span&gt;&lt;br /&gt;&lt;a href="http://dispatch.databinder.net/About"&gt;Dispatch&lt;/a&gt; is a wrapper around HttpClient that provides a very terse DSL syntax and the ability to make Http calls in a Scalactic way. The overloaded operators throw some people off so if you prefer to use HttpClient or any other Http library, that works too. I have found that once I got familiar with Dispatch syntax, I quite like it, and it meshes well with Specs to allow me to quickly bang out a lot of test calls.&lt;br /&gt;&lt;pre class="brush: xml"&gt;&lt;br /&gt;        &amp;lt;!-- Dispatch --&amp;gt;&lt;br /&gt;        &amp;lt;dependency&amp;gt;&lt;br /&gt;            &amp;lt;groupId&amp;gt;net.databinder&amp;lt;/groupId&amp;gt;&lt;br /&gt;            &amp;lt;artifactId&amp;gt;dispatch-http_2.8.0&amp;lt;/artifactId&amp;gt;&lt;br /&gt;            &amp;lt;version&amp;gt;0.7.7&amp;lt;/version&amp;gt;&lt;br /&gt;            &amp;lt;scope&amp;gt;test&amp;lt;/scope&amp;gt;&lt;br /&gt;        &amp;lt;/dependency&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Lift-Json&lt;/span&gt;&lt;br /&gt;Dispatch provides support for Json through the &lt;a href="https://github.com/lift/lift/tree/master/framework/lift-base/lift-json/"&gt;lift-json&lt;/a&gt; library, which is a part of the Lift framework. It provides straightforward serialization and deserialization of Scala case classes as well as clear XPath-like parsing of Json.&lt;br /&gt;&lt;pre class="brush: xml"&gt;&lt;br /&gt;        &amp;lt;dependency&amp;gt;&lt;br /&gt;            &amp;lt;groupId&amp;gt;net.databinder&amp;lt;/groupId&amp;gt;&lt;br /&gt;            &amp;lt;artifactId&amp;gt;dispatch-lift-json_2.8.0&amp;lt;/artifactId&amp;gt;&lt;br /&gt;            &amp;lt;version&amp;gt;0.7.7&amp;lt;/version&amp;gt;&lt;br /&gt;            &amp;lt;scope&amp;gt;test&amp;lt;/scope&amp;gt;&lt;br /&gt;        &amp;lt;/dependency&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;And the rest...&lt;/span&gt;&lt;br /&gt;You'll also need to add JUnit and Jersey for this example project. See the complete pom.xml below for specifics.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;Build&lt;/span&gt;&lt;br /&gt;You'll need to tell Maven to look for Scala tests.&lt;br /&gt;&lt;pre class="brush: xml"&gt;&lt;br /&gt;        &amp;lt;testSourceDirectory&amp;gt;${project.basedir}/src/test/scala&amp;lt;/testSourceDirectory&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Compile the Scala Tests&lt;/span&gt;&lt;br /&gt;Configure the Scala compiler plugin so that your Scala tests get built like so:&lt;br /&gt;&lt;pre class="brush: scala"&gt;&lt;br /&gt;            &amp;lt;!-- Compile Scala --&amp;gt;&lt;br /&gt;            &amp;lt;plugin&amp;gt;&lt;br /&gt;                &amp;lt;groupId&amp;gt;org.scala-tools&amp;lt;/groupId&amp;gt;&lt;br /&gt;                &amp;lt;artifactId&amp;gt;maven-scala-plugin&amp;lt;/artifactId&amp;gt;&lt;br /&gt;                &amp;lt;executions&amp;gt;&lt;br /&gt;                    &amp;lt;execution&amp;gt;&lt;br /&gt;                        &amp;lt;id&amp;gt;scala-compile-first&amp;lt;/id&amp;gt;&lt;br /&gt;                        &amp;lt;phase&amp;gt;process-resources&amp;lt;/phase&amp;gt;&lt;br /&gt;                        &amp;lt;goals&amp;gt;&lt;br /&gt;                            &amp;lt;goal&amp;gt;add-source&amp;lt;/goal&amp;gt;&lt;br /&gt;                            &amp;lt;goal&amp;gt;compile&amp;lt;/goal&amp;gt;&lt;br /&gt;                        &amp;lt;/goals&amp;gt;&lt;br /&gt;                    &amp;lt;/execution&amp;gt;&lt;br /&gt;                    &amp;lt;execution&amp;gt;&lt;br /&gt;                        &amp;lt;id&amp;gt;scala-test-compile&amp;lt;/id&amp;gt;&lt;br /&gt;                        &amp;lt;phase&amp;gt;process-test-resources&amp;lt;/phase&amp;gt;&lt;br /&gt;                        &amp;lt;goals&amp;gt;&lt;br /&gt;                            &amp;lt;goal&amp;gt;testCompile&amp;lt;/goal&amp;gt;&lt;br /&gt;                        &amp;lt;/goals&amp;gt;&lt;br /&gt;                    &amp;lt;/execution&amp;gt;&lt;br /&gt;                &amp;lt;/executions&amp;gt;&lt;br /&gt;            &amp;lt;/plugin&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Surefire&lt;/span&gt;&lt;br /&gt;Clarify that you would indeed like to run the Scala tests by telling the Maven Surefire plugin when and what to run. In this example we flout JUnit convention and run things that end in Spec. Observant types will notice that the configuration says **/*Spec.java even though we're writing tests in Scala. Just go with it.&lt;br /&gt;&lt;pre class="brush: xml"&gt;&lt;br /&gt;            &amp;lt;!-- Tests --&amp;gt;&lt;br /&gt;            &amp;lt;plugin&amp;gt;&lt;br /&gt;                &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;&lt;br /&gt;                &amp;lt;artifactId&amp;gt;maven-surefire-plugin&amp;lt;/artifactId&amp;gt;&lt;br /&gt;                &amp;lt;version&amp;gt;2.4.3&amp;lt;/version&amp;gt;&lt;br /&gt;                &amp;lt;configuration&amp;gt;&lt;br /&gt;                    &amp;lt;useSystemClassLoader&amp;gt;false&amp;lt;/useSystemClassLoader&amp;gt;&lt;br /&gt;                    &amp;lt;argLine&amp;gt;-Xmx512m&amp;lt;/argLine&amp;gt;&lt;br /&gt;                    &amp;lt;includes&amp;gt;&lt;br /&gt;                        &amp;lt;include&amp;gt;**/*Spec.java&amp;lt;/include&amp;gt;&lt;br /&gt;                    &amp;lt;/includes&amp;gt;&lt;br /&gt;                &amp;lt;/configuration&amp;gt;&lt;br /&gt;            &amp;lt;/plugin&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Start and Stop Jetty&lt;/span&gt;&lt;br /&gt;This configuration will run Jetty for the duration of the build. The sophisticated among you may wish to start and stop the server at different phases of the build. Determining an appropriate strategy is left as an exercise to the reader.&lt;br /&gt;&lt;pre class="brush: xml"&gt;&lt;br /&gt;            &amp;lt;!-- Run Jetty --&amp;gt;&lt;br /&gt;            &amp;lt;plugin&amp;gt;&lt;br /&gt;                &amp;lt;groupId&amp;gt;org.mortbay.jetty&amp;lt;/groupId&amp;gt;&lt;br /&gt;                &amp;lt;artifactId&amp;gt;maven-jetty-plugin&amp;lt;/artifactId&amp;gt;&lt;br /&gt;                &amp;lt;version&amp;gt;6.1.24&amp;lt;/version&amp;gt;&lt;br /&gt;                &amp;lt;configuration&amp;gt;&lt;br /&gt;                    &amp;lt;connectors&amp;gt;&lt;br /&gt;                        &amp;lt;connector implementation=&amp;quot;org.mortbay.jetty.nio.SelectChannelConnector&amp;quot;&amp;gt;&lt;br /&gt;                            &amp;lt;port&amp;gt;2342&amp;lt;/port&amp;gt;&lt;br /&gt;                        &amp;lt;/connector&amp;gt;&lt;br /&gt;                    &amp;lt;/connectors&amp;gt;&lt;br /&gt;                    &amp;lt;stopKey&amp;gt;stop&amp;lt;/stopKey&amp;gt;&lt;br /&gt;                    &amp;lt;stopPort&amp;gt;9999&amp;lt;/stopPort&amp;gt;&lt;br /&gt;                &amp;lt;/configuration&amp;gt;&lt;br /&gt;                &amp;lt;executions&amp;gt;&lt;br /&gt;                    &amp;lt;execution&amp;gt;&lt;br /&gt;                        &amp;lt;id&amp;gt;start-jetty&amp;lt;/id&amp;gt;&lt;br /&gt;                        &amp;lt;phase&amp;gt;process-classes&amp;lt;/phase&amp;gt;&lt;br /&gt;                        &amp;lt;goals&amp;gt;&lt;br /&gt;                            &amp;lt;goal&amp;gt;run&amp;lt;/goal&amp;gt;&lt;br /&gt;                        &amp;lt;/goals&amp;gt;&lt;br /&gt;                        &amp;lt;configuration&amp;gt;&lt;br /&gt;                            &amp;lt;daemon&amp;gt;true&amp;lt;/daemon&amp;gt;&lt;br /&gt;                        &amp;lt;/configuration&amp;gt;&lt;br /&gt;                    &amp;lt;/execution&amp;gt;&lt;br /&gt;                    &amp;lt;execution&amp;gt;&lt;br /&gt;                        &amp;lt;id&amp;gt;stop-jetty&amp;lt;/id&amp;gt;&lt;br /&gt;                        &amp;lt;phase&amp;gt;post-integration-test&amp;lt;/phase&amp;gt;&lt;br /&gt;                        &amp;lt;goals&amp;gt;&lt;br /&gt;                            &amp;lt;goal&amp;gt;stop&amp;lt;/goal&amp;gt;&lt;br /&gt;                        &amp;lt;/goals&amp;gt;&lt;br /&gt;                    &amp;lt;/execution&amp;gt;&lt;br /&gt;                &amp;lt;/executions&amp;gt;&lt;br /&gt;            &amp;lt;/plugin&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;Beer Service&lt;/span&gt;&lt;br /&gt;With the Maven setup behind us, we'll throw together a simple Jersey service so there's something to test. Here's a Beer JavaBean and a service class to serve some Beers.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;/src/main/java/com/janxspirit/Beer.java&lt;/span&gt;&lt;br /&gt;&lt;pre class="brush: java"&gt;&lt;br /&gt;package com.janxspirit;&lt;br /&gt;&lt;br /&gt;import javax.xml.bind.annotation.XmlElement;&lt;br /&gt;import javax.xml.bind.annotation.XmlRootElement;&lt;br /&gt;&lt;br /&gt;@XmlRootElement&lt;br /&gt;public class Beer {&lt;br /&gt;    &lt;br /&gt;    private String name;&lt;br /&gt;    private int sizeOunces;&lt;br /&gt;&lt;br /&gt;    public Beer() {}&lt;br /&gt;&lt;br /&gt;    public Beer(String name, int sizeOunces) {&lt;br /&gt;        this.name = name;&lt;br /&gt;        this.sizeOunces = sizeOunces;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @XmlElement(name = &amp;quot;name&amp;quot;)&lt;br /&gt;    public String getName() {&lt;br /&gt;        return name;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void setName(String name) {&lt;br /&gt;        this.name = name;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @XmlElement(name = &amp;quot;sizeOunces&amp;quot;)&lt;br /&gt;    public int getSizeOunces() {&lt;br /&gt;        return sizeOunces;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void setSizeOunces(int sizeOunces) {&lt;br /&gt;        this.sizeOunces = sizeOunces;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;/src/main/java/com/janxspirit/BeerResource.java&lt;/span&gt;&lt;br /&gt;&lt;pre class="brush: java"&gt;&lt;br /&gt;package com.janxspirit;&lt;br /&gt;&lt;br /&gt;import java.util.ArrayList;&lt;br /&gt;import java.util.List;&lt;br /&gt;import javax.ws.rs.Path;&lt;br /&gt;import javax.ws.rs.GET;&lt;br /&gt;import javax.ws.rs.PathParam;&lt;br /&gt;import javax.ws.rs.Produces;&lt;br /&gt;import javax.ws.rs.QueryParam;&lt;br /&gt;import javax.ws.rs.core.Response;&lt;br /&gt;import javax.ws.rs.core.Response.Status;&lt;br /&gt;&lt;br /&gt;@Path(&amp;quot;/&amp;quot;)&lt;br /&gt;public class RestResource {&lt;br /&gt;&lt;br /&gt;    private List beerList;&lt;br /&gt;&lt;br /&gt;    public RestResource() {&lt;br /&gt;        beerList = new ArrayList();&lt;br /&gt;        beerList.add(&amp;quot;Corona&amp;quot;);&lt;br /&gt;        beerList.add(&amp;quot;Guiness&amp;quot;);&lt;br /&gt;        beerList.add(&amp;quot;Fat Tire&amp;quot;);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @GET&lt;br /&gt;    @Produces(&amp;quot;application/json&amp;quot;)&lt;br /&gt;    @Path(&amp;quot;beers/{name}&amp;quot;)&lt;br /&gt;    public Response getBeer(@PathParam(&amp;quot;name&amp;quot;) String name, @QueryParam(&amp;quot;sizeOunces&amp;quot;) int sizeOunces) {&lt;br /&gt;        if (name == null || !beerList.contains(name)) {&lt;br /&gt;            return Response.status(Status.NOT_FOUND).entity(String.format(&amp;quot;Sorry we don't have any %s&amp;quot;, name)).build();&lt;br /&gt;        }&lt;br /&gt;        if (sizeOunces &amp;lt; 8) {&lt;br /&gt;            return Response.status(Status.BAD_REQUEST).entity(&amp;quot;Sorry no kid-size beers.&amp;quot;).build();&lt;br /&gt;        }&lt;br /&gt;        Beer beer = new Beer(name, sizeOunces);&lt;br /&gt;        System.out.println(String.format(&amp;quot;Pouring %s ounces of %s&amp;quot;, sizeOunces, name));&lt;br /&gt;        return Response.ok(beer).build();&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;/src/main/java/JsonContextResolver.java&lt;/span&gt;&lt;br /&gt;In order to get the default Json library to render the responses correctly, you need to add a class like the following. There are other ways, but in general its unfortunate that Jersey doesn't do the right thing out of the box at least presenting integer attributes unquoted in Json. We explicitly set the sizeOunces property to be non-String below.&lt;br /&gt;&lt;pre class="brush: java"&gt;&lt;br /&gt;package com.janxspirit;&lt;br /&gt;&lt;br /&gt;import com.sun.jersey.api.json.JSONConfiguration;&lt;br /&gt;import com.sun.jersey.api.json.JSONJAXBContext;&lt;br /&gt;import javax.ws.rs.ext.ContextResolver;&lt;br /&gt;import javax.ws.rs.ext.Provider;&lt;br /&gt;import javax.xml.bind.JAXBContext;&lt;br /&gt;&lt;br /&gt;@Provider&lt;br /&gt;public class JsonContextResolver implements ContextResolver&amp;lt;JAXBContext&amp;gt; {&lt;br /&gt;&lt;br /&gt;     private JAXBContext context;&lt;br /&gt;     private Class[] types = {Beer.class};&lt;br /&gt;&lt;br /&gt;     public JsonContextResolver() throws Exception {&lt;br /&gt;         this.context =&lt;br /&gt;    new JSONJAXBContext(&lt;br /&gt;      JSONConfiguration.mapped().nonStrings(&amp;quot;sizeOunces&amp;quot;).build(), types);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public JAXBContext getContext(Class&amp;lt;?&amp;gt; objectType) {&lt;br /&gt;        for (Class type : types) {&lt;br /&gt;             if (type == objectType) {&lt;br /&gt;                 return context;&lt;br /&gt;             }&lt;br /&gt;         }&lt;br /&gt;         return null;&lt;br /&gt;     }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;web.xml&lt;/span&gt;&lt;br /&gt;A last bit of setup is to configure your web.xml to fire up the Jersey servlet. This goes in the usual place - src/main/webapp/WEB-INF/web.xml&lt;br /&gt;&lt;pre class="brush: xml"&gt;&lt;br /&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;&amp;lt;web-app version=&amp;quot;2.5&amp;quot; xmlns=&amp;quot;http://java.sun.com/xml/ns/javaee&amp;quot; xmlns:xsi=&amp;quot;http://www.w3.org/2001/XMLSchema-instance&amp;quot; xsi:schemaLocation=&amp;quot;http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd&amp;quot;&amp;gt;&lt;br /&gt;    &amp;lt;display-name&amp;gt;scala_test_jersey&amp;lt;/display-name&amp;gt;&lt;br /&gt;    &amp;lt;servlet&amp;gt;&lt;br /&gt;        &amp;lt;servlet-name&amp;gt;RestResourcer&amp;lt;/servlet-name&amp;gt;&lt;br /&gt;        &amp;lt;servlet-class&amp;gt;com.sun.jersey.spi.container.servlet.ServletContainer&amp;lt;/servlet-class&amp;gt;&lt;br /&gt;        &amp;lt;init-param&amp;gt;&lt;br /&gt;            &amp;lt;param-name&amp;gt;com.sun.jersey.config.property.packages&amp;lt;/param-name&amp;gt;&lt;br /&gt;            &amp;lt;param-value&amp;gt;com.janxspirit&amp;lt;/param-value&amp;gt;&lt;br /&gt;        &amp;lt;/init-param&amp;gt;&lt;br /&gt;    &amp;lt;/servlet&amp;gt;&lt;br /&gt;    &amp;lt;servlet-mapping&amp;gt;&lt;br /&gt;        &amp;lt;servlet-name&amp;gt;RestResourcer&amp;lt;/servlet-name&amp;gt;&lt;br /&gt;        &amp;lt;url-pattern&amp;gt;/*&amp;lt;/url-pattern&amp;gt;&lt;br /&gt;    &amp;lt;/servlet-mapping&amp;gt;&lt;br /&gt;&amp;lt;/web-app&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;Writing the Specs&lt;/span&gt;&lt;br /&gt;Now the fun part! This is actually much less involved than all the boilerplate above, but hopefully the setup is helpful in getting you to the good stuff more quickly.&lt;br /&gt;&lt;br /&gt;The first thing I did was create a simple case class and a function to convert the Dispatch responses into a simple object with a status code and body. I'd love to hear any better approaches to this, but in any event, this does work.&lt;br /&gt;&lt;pre class="brush: scala"&gt;&lt;br /&gt;  def toResponse(req: Request): StatusCodeBody = {&lt;br /&gt;    val http = new Http&lt;br /&gt;    http x (req as_str) {&lt;br /&gt;      case (status, _, ent, _) =&amp;gt; StatusCodeBody(status, EntityUtils.toString(ent.get))&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;case class StatusCodeBody (status: Int, body: String)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now we fill in the empty spec bodies. In most cases that's a one-liner to make the Http call and then a simple equality test against the response object. Here's what a simple call to the service looks like:&lt;br /&gt;&lt;pre class="brush: scala"&gt;&lt;br /&gt;        val app = &amp;quot;scala_test_jersey&amp;quot;&lt;br /&gt;        val getBeerRes = toResponse(:/(&amp;quot;localhost&amp;quot;, 2342) / app / &amp;quot;beers&amp;quot; / &amp;quot;Budweiser&amp;quot;)&lt;br /&gt;        &amp;quot;return status 404&amp;quot; &amp;gt;&amp;gt; { getBeerRes.status must_== 404 }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;As you can see, assembling an Http call with dispatch is very straightforward. If you don't like the overloaded operators, I suggest you use trusty old HttpClient.&lt;br /&gt;&lt;br /&gt;Here's all you need to do to add a query param to a request:&lt;br /&gt;&lt;pre class="brush: scala"&gt;&lt;br /&gt;        val getBeerRes = toResponse(:/(&amp;quot;localhost&amp;quot;, 2342) / app / &amp;quot;beers&amp;quot; / &amp;quot;Corona&amp;quot; &amp;lt;&amp;lt;? Map(&amp;quot;sizeOunces&amp;quot; -&amp;gt; 4))&lt;br /&gt;        &amp;quot;return status 400&amp;quot; &amp;gt;&amp;gt; { getBeerRes.status must_== 400 }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;These examples also show one of the Specs matchers 'must_==' The Specs library provides a lot of &lt;a href="http://code.google.com/p/specs/wiki/MatchersGuide"&gt;matchers&lt;/a&gt; and if you need some new ones, it's very easy to create them.&lt;br /&gt;&lt;br /&gt;For the last two specs we'll do another simple check of the Http response code as well as deserialize the Json response body and inspect the result. To do that, I've created a simple case class. Lift-Json takes care of the rest. Here's what that looks like:&lt;br /&gt;&lt;pre class="brush: scala"&gt;&lt;br /&gt;case class JsonBeer(name: String, sizeOunces: Int)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre class="brush: scala"&gt;&lt;br /&gt;        val getBeerRes = toResponse(:/(&amp;quot;localhost&amp;quot;, 2342) / app / &amp;quot;beers&amp;quot; / &amp;quot;Guiness&amp;quot; &amp;lt;&amp;lt;? Map(&amp;quot;sizeOunces&amp;quot; -&amp;gt; 16))&lt;br /&gt;        &amp;quot;return status 200&amp;quot; &amp;gt;&amp;gt; { getBeerRes.status must_== 200 }&lt;br /&gt;        &amp;quot;return a Beer representation&amp;quot; in {&lt;br /&gt;          val beer = parse(getBeerRes.body).extract[JsonBeer]&lt;br /&gt;          &amp;quot;with&amp;quot; in {&lt;br /&gt;            &amp;quot;name 'Guiness'&amp;quot; &amp;gt;&amp;gt; {beer.name mustEqual &amp;quot;Guiness&amp;quot;}&lt;br /&gt;            &amp;quot;sizeOunces 16&amp;quot; &amp;gt;&amp;gt; {beer.sizeOunces must_== 16}&lt;br /&gt;          }&lt;br /&gt;        }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Pretty slick.&lt;br /&gt;&lt;br /&gt;And now the moment of truth. You can run&lt;br /&gt;&lt;pre class="brush: bash"&gt;&lt;br /&gt;mvn clean test&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;or get fancier and run it in your IDE. This screenshot shows output in Netbeans.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-wYU7-y0WPfY/TVgrnYk7yxI/AAAAAAAAAaw/uFQVWOtp99A/s1600/netbeans_tests.jpg"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 400px; height: 78px;" src="http://3.bp.blogspot.com/-wYU7-y0WPfY/TVgrnYk7yxI/AAAAAAAAAaw/uFQVWOtp99A/s400/netbeans_tests.jpg" alt="" id="BLOGGER_PHOTO_ID_5573252494483245842" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;There's a bit more setup for the spec class. I've set these tests to share variables and run sequentially. The complete code for BeerSpec.scala and pom.xml is below. &lt;br /&gt;&lt;br /&gt;I hope this setup guide has been helpful and encourages some folks to dip their toe in with Scala testing. Happy coding!&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;/src/test/scala/BeerSpec.scala&lt;/span&gt;&lt;br /&gt;&lt;pre class="brush: scala"&gt;&lt;br /&gt;import org.specs._&lt;br /&gt;import dispatch._&lt;br /&gt;import net.liftweb.json.JsonParser._&lt;br /&gt;import net.liftweb.json.JsonAST._&lt;br /&gt;import net.liftweb.json.JsonDSL._&lt;br /&gt;import org.apache.http.util.EntityUtils&lt;br /&gt;&lt;br /&gt;class BeerSpec extends SpecificationWithJUnit {&lt;br /&gt;&lt;br /&gt;  implicit val formats = net.liftweb.json.DefaultFormats // Brings in default date formats etc.&lt;br /&gt;  val app = &amp;quot;scala_test_jersey&amp;quot;&lt;br /&gt;  setSequential()&lt;br /&gt;  shareVariables()&lt;br /&gt;&lt;br /&gt;  &amp;quot;Calling GET /beers&amp;quot; should {&lt;br /&gt;    &amp;quot;when called with&amp;quot; in {&lt;br /&gt;&lt;br /&gt;      &amp;quot;name 'Budweiser'&amp;quot; in {&lt;br /&gt;        val getBeerRes = toResponse(:/(&amp;quot;localhost&amp;quot;, 2342) / app / &amp;quot;beers&amp;quot; / &amp;quot;Budweiser&amp;quot;)&lt;br /&gt;        &amp;quot;return status 404&amp;quot; &amp;gt;&amp;gt; { getBeerRes.status must_== 404 }&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      &amp;quot;name 'Corona' and sizeOunces 4&amp;quot; in {&lt;br /&gt;        val getBeerRes = toResponse(:/(&amp;quot;localhost&amp;quot;, 2342) / app / &amp;quot;beers&amp;quot; / &amp;quot;Corona&amp;quot; &amp;lt;&amp;lt;? Map(&amp;quot;sizeOunces&amp;quot; -&amp;gt; 4))&lt;br /&gt;        &amp;quot;return status 400&amp;quot; &amp;gt;&amp;gt; { getBeerRes.status must_== 400 }&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      &amp;quot;beer name 'Guiness' and sizeOunces 16&amp;quot; in {&lt;br /&gt;        val getBeerRes = toResponse(:/(&amp;quot;localhost&amp;quot;, 2342) / app / &amp;quot;beers&amp;quot; / &amp;quot;Guiness&amp;quot; &amp;lt;&amp;lt;? Map(&amp;quot;sizeOunces&amp;quot; -&amp;gt; 16))&lt;br /&gt;        &amp;quot;return status 200&amp;quot; &amp;gt;&amp;gt; { getBeerRes.status must_== 200 }&lt;br /&gt;        &amp;quot;return a Beer representation&amp;quot; in {&lt;br /&gt;          val beer = parse(getBeerRes.body).extract[JsonBeer]&lt;br /&gt;          &amp;quot;with&amp;quot; in {&lt;br /&gt;            &amp;quot;name 'Guiness'&amp;quot; &amp;gt;&amp;gt; {beer.name mustEqual &amp;quot;Guiness&amp;quot;}&lt;br /&gt;            &amp;quot;sizeOunces 16&amp;quot; &amp;gt;&amp;gt; {beer.sizeOunces must_== 16}&lt;br /&gt;          }&lt;br /&gt;        }&lt;br /&gt;      }&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  def toResponse(req: Request): StatusCodeBody = {&lt;br /&gt;    val http = new Http&lt;br /&gt;    http x (req as_str) {&lt;br /&gt;      case (status, _, ent, _) =&amp;gt; StatusCodeBody(status, EntityUtils.toString(ent.get))&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;case class JsonBeer(name: String, sizeOunces: Int)&lt;br /&gt;case class StatusCodeBody (status: Int, body: String)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;pom.xml&lt;/span&gt;&lt;br /&gt;&lt;pre class="brush: xml"&gt;&lt;br /&gt;&amp;lt;project xmlns=&amp;quot;http://maven.apache.org/POM/4.0.0&amp;quot; xmlns:xsi=&amp;quot;http://www.w3.org/2001/XMLSchema-instance&amp;quot;&lt;br /&gt;  xsi:schemaLocation=&amp;quot;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd&amp;quot;&amp;gt;&lt;br /&gt;    &amp;lt;modelVersion&amp;gt;4.0.0&amp;lt;/modelVersion&amp;gt;&lt;br /&gt;    &amp;lt;groupId&amp;gt;com.janxspirit&amp;lt;/groupId&amp;gt;&lt;br /&gt;    &amp;lt;artifactId&amp;gt;scala_test_jersey&amp;lt;/artifactId&amp;gt;&lt;br /&gt;    &amp;lt;packaging&amp;gt;war&amp;lt;/packaging&amp;gt;&lt;br /&gt;    &amp;lt;version&amp;gt;1.0-SNAPSHOT&amp;lt;/version&amp;gt;&lt;br /&gt;    &amp;lt;name&amp;gt;scala_test_jersey&amp;lt;/name&amp;gt;&lt;br /&gt;    &amp;lt;url&amp;gt;http://maven.apache.org&amp;lt;/url&amp;gt;&lt;br /&gt;  &lt;br /&gt;    &amp;lt;repositories&amp;gt;&lt;br /&gt;        &amp;lt;repository&amp;gt;&lt;br /&gt;            &amp;lt;id&amp;gt;scala-tools.org&amp;lt;/id&amp;gt;&lt;br /&gt;            &amp;lt;name&amp;gt;Scala-tools Maven2 Repository&amp;lt;/name&amp;gt;&lt;br /&gt;            &amp;lt;url&amp;gt;http://scala-tools.org/repo-releases&amp;lt;/url&amp;gt;&lt;br /&gt;        &amp;lt;/repository&amp;gt;&lt;br /&gt;    &amp;lt;/repositories&amp;gt;&lt;br /&gt;    &lt;br /&gt;    &amp;lt;dependencies&amp;gt;&lt;br /&gt;&lt;br /&gt;        &amp;lt;!-- Scala --&amp;gt;&lt;br /&gt;        &amp;lt;dependency&amp;gt;&lt;br /&gt;            &amp;lt;groupId&amp;gt;org.scala-lang&amp;lt;/groupId&amp;gt;&lt;br /&gt;            &amp;lt;artifactId&amp;gt;scala-library&amp;lt;/artifactId&amp;gt;&lt;br /&gt;            &amp;lt;version&amp;gt;2.8.0&amp;lt;/version&amp;gt;&lt;br /&gt;        &amp;lt;/dependency&amp;gt;&lt;br /&gt;        &lt;br /&gt;        &amp;lt;!-- Dispatch --&amp;gt;&lt;br /&gt;        &amp;lt;dependency&amp;gt;&lt;br /&gt;            &amp;lt;groupId&amp;gt;net.databinder&amp;lt;/groupId&amp;gt;&lt;br /&gt;            &amp;lt;artifactId&amp;gt;dispatch-http_2.8.0&amp;lt;/artifactId&amp;gt;&lt;br /&gt;            &amp;lt;version&amp;gt;0.7.7&amp;lt;/version&amp;gt;&lt;br /&gt;            &amp;lt;scope&amp;gt;test&amp;lt;/scope&amp;gt;&lt;br /&gt;        &amp;lt;/dependency&amp;gt;&lt;br /&gt;        &amp;lt;dependency&amp;gt;&lt;br /&gt;            &amp;lt;groupId&amp;gt;net.databinder&amp;lt;/groupId&amp;gt;&lt;br /&gt;            &amp;lt;artifactId&amp;gt;dispatch-lift-json_2.8.0&amp;lt;/artifactId&amp;gt;&lt;br /&gt;            &amp;lt;version&amp;gt;0.7.7&amp;lt;/version&amp;gt;&lt;br /&gt;            &amp;lt;scope&amp;gt;test&amp;lt;/scope&amp;gt;&lt;br /&gt;        &amp;lt;/dependency&amp;gt;&lt;br /&gt;&lt;br /&gt;        &amp;lt;!-- Specs --&amp;gt;&lt;br /&gt;        &amp;lt;dependency&amp;gt;&lt;br /&gt;            &amp;lt;groupId&amp;gt;org.scala-tools.testing&amp;lt;/groupId&amp;gt;&lt;br /&gt;            &amp;lt;artifactId&amp;gt;specs_2.8.0&amp;lt;/artifactId&amp;gt;&lt;br /&gt;            &amp;lt;version&amp;gt;1.6.5&amp;lt;/version&amp;gt;&lt;br /&gt;        &amp;lt;/dependency&amp;gt;&lt;br /&gt;&lt;br /&gt;        &amp;lt;!-- JUnit --&amp;gt;&lt;br /&gt;        &amp;lt;dependency&amp;gt;&lt;br /&gt;            &amp;lt;groupId&amp;gt;junit&amp;lt;/groupId&amp;gt;&lt;br /&gt;            &amp;lt;artifactId&amp;gt;junit&amp;lt;/artifactId&amp;gt;&lt;br /&gt;            &amp;lt;version&amp;gt;4.8.1&amp;lt;/version&amp;gt;&lt;br /&gt;        &amp;lt;/dependency&amp;gt;&lt;br /&gt;&lt;br /&gt;        &amp;lt;!-- Jersey --&amp;gt;&lt;br /&gt;        &amp;lt;dependency&amp;gt;&lt;br /&gt;            &amp;lt;groupId&amp;gt;com.sun.jersey&amp;lt;/groupId&amp;gt;&lt;br /&gt;            &amp;lt;artifactId&amp;gt;jersey-json&amp;lt;/artifactId&amp;gt;&lt;br /&gt;            &amp;lt;version&amp;gt;1.3&amp;lt;/version&amp;gt;&lt;br /&gt;        &amp;lt;/dependency&amp;gt;&lt;br /&gt;        &amp;lt;dependency&amp;gt;&lt;br /&gt;            &amp;lt;groupId&amp;gt;com.sun.jersey&amp;lt;/groupId&amp;gt;&lt;br /&gt;            &amp;lt;artifactId&amp;gt;jersey-server&amp;lt;/artifactId&amp;gt;&lt;br /&gt;            &amp;lt;version&amp;gt;1.3&amp;lt;/version&amp;gt;&lt;br /&gt;        &amp;lt;/dependency&amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;/dependencies&amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;build&amp;gt;&lt;br /&gt;        &amp;lt;testSourceDirectory&amp;gt;${project.basedir}/src/test/scala&amp;lt;/testSourceDirectory&amp;gt;&lt;br /&gt;        &amp;lt;pluginManagement&amp;gt;&lt;br /&gt;            &amp;lt;plugins&amp;gt;&lt;br /&gt;                &amp;lt;plugin&amp;gt;&lt;br /&gt;                    &amp;lt;groupId&amp;gt;org.scala-tools&amp;lt;/groupId&amp;gt;&lt;br /&gt;                    &amp;lt;artifactId&amp;gt;maven-scala-plugin&amp;lt;/artifactId&amp;gt;&lt;br /&gt;                    &amp;lt;version&amp;gt;2.9.1&amp;lt;/version&amp;gt;&lt;br /&gt;                &amp;lt;/plugin&amp;gt;&lt;br /&gt;                &amp;lt;plugin&amp;gt;&lt;br /&gt;                    &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;&lt;br /&gt;                    &amp;lt;artifactId&amp;gt;maven-compiler-plugin&amp;lt;/artifactId&amp;gt;&lt;br /&gt;                    &amp;lt;version&amp;gt;2.0.2&amp;lt;/version&amp;gt;&lt;br /&gt;                &amp;lt;/plugin&amp;gt;&lt;br /&gt;            &amp;lt;/plugins&amp;gt;&lt;br /&gt;        &amp;lt;/pluginManagement&amp;gt;&lt;br /&gt;        &amp;lt;plugins&amp;gt;&lt;br /&gt;&lt;br /&gt;            &amp;lt;!-- Compile Scala --&amp;gt;&lt;br /&gt;            &amp;lt;plugin&amp;gt;&lt;br /&gt;                &amp;lt;groupId&amp;gt;org.scala-tools&amp;lt;/groupId&amp;gt;&lt;br /&gt;                &amp;lt;artifactId&amp;gt;maven-scala-plugin&amp;lt;/artifactId&amp;gt;&lt;br /&gt;                &amp;lt;executions&amp;gt;&lt;br /&gt;                    &amp;lt;execution&amp;gt;&lt;br /&gt;                        &amp;lt;id&amp;gt;scala-compile-first&amp;lt;/id&amp;gt;&lt;br /&gt;                        &amp;lt;phase&amp;gt;process-resources&amp;lt;/phase&amp;gt;&lt;br /&gt;                        &amp;lt;goals&amp;gt;&lt;br /&gt;                            &amp;lt;goal&amp;gt;add-source&amp;lt;/goal&amp;gt;&lt;br /&gt;                            &amp;lt;goal&amp;gt;compile&amp;lt;/goal&amp;gt;&lt;br /&gt;                        &amp;lt;/goals&amp;gt;&lt;br /&gt;                    &amp;lt;/execution&amp;gt;&lt;br /&gt;                    &amp;lt;execution&amp;gt;&lt;br /&gt;                        &amp;lt;id&amp;gt;scala-test-compile&amp;lt;/id&amp;gt;&lt;br /&gt;                        &amp;lt;phase&amp;gt;process-test-resources&amp;lt;/phase&amp;gt;&lt;br /&gt;                        &amp;lt;goals&amp;gt;&lt;br /&gt;                            &amp;lt;goal&amp;gt;testCompile&amp;lt;/goal&amp;gt;&lt;br /&gt;                        &amp;lt;/goals&amp;gt;&lt;br /&gt;                    &amp;lt;/execution&amp;gt;&lt;br /&gt;                &amp;lt;/executions&amp;gt;&lt;br /&gt;            &amp;lt;/plugin&amp;gt;&lt;br /&gt;&lt;br /&gt;            &amp;lt;!-- Compile Java --&amp;gt;&lt;br /&gt;            &amp;lt;plugin&amp;gt;&lt;br /&gt;                &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;&lt;br /&gt;                &amp;lt;artifactId&amp;gt;maven-compiler-plugin&amp;lt;/artifactId&amp;gt;&lt;br /&gt;                &amp;lt;executions&amp;gt;&lt;br /&gt;                    &amp;lt;execution&amp;gt;&lt;br /&gt;                        &amp;lt;phase&amp;gt;compile&amp;lt;/phase&amp;gt;&lt;br /&gt;                        &amp;lt;goals&amp;gt;&lt;br /&gt;                            &amp;lt;goal&amp;gt;compile&amp;lt;/goal&amp;gt;&lt;br /&gt;                        &amp;lt;/goals&amp;gt;&lt;br /&gt;                    &amp;lt;/execution&amp;gt;&lt;br /&gt;                &amp;lt;/executions&amp;gt;&lt;br /&gt;                &amp;lt;configuration&amp;gt;&lt;br /&gt;                    &amp;lt;source&amp;gt;1.6&amp;lt;/source&amp;gt;&lt;br /&gt;                    &amp;lt;target&amp;gt;1.6&amp;lt;/target&amp;gt;&lt;br /&gt;                &amp;lt;/configuration&amp;gt;&lt;br /&gt;            &amp;lt;/plugin&amp;gt;&lt;br /&gt;&lt;br /&gt;            &amp;lt;!-- Tests --&amp;gt;&lt;br /&gt;            &amp;lt;plugin&amp;gt;&lt;br /&gt;                &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;&lt;br /&gt;                &amp;lt;artifactId&amp;gt;maven-surefire-plugin&amp;lt;/artifactId&amp;gt;&lt;br /&gt;                &amp;lt;version&amp;gt;2.4.3&amp;lt;/version&amp;gt;&lt;br /&gt;                &amp;lt;configuration&amp;gt;&lt;br /&gt;                    &amp;lt;useSystemClassLoader&amp;gt;false&amp;lt;/useSystemClassLoader&amp;gt;&lt;br /&gt;                    &amp;lt;argLine&amp;gt;-Xmx512m&amp;lt;/argLine&amp;gt;&lt;br /&gt;                    &amp;lt;includes&amp;gt;&lt;br /&gt;                        &amp;lt;include&amp;gt;**/*Spec.java&amp;lt;/include&amp;gt;&lt;br /&gt;                    &amp;lt;/includes&amp;gt;&lt;br /&gt;                &amp;lt;/configuration&amp;gt;&lt;br /&gt;            &amp;lt;/plugin&amp;gt;&lt;br /&gt;&lt;br /&gt;            &amp;lt;!-- Run Jetty --&amp;gt;&lt;br /&gt;            &amp;lt;plugin&amp;gt;&lt;br /&gt;                &amp;lt;groupId&amp;gt;org.mortbay.jetty&amp;lt;/groupId&amp;gt;&lt;br /&gt;                &amp;lt;artifactId&amp;gt;maven-jetty-plugin&amp;lt;/artifactId&amp;gt;&lt;br /&gt;                &amp;lt;version&amp;gt;6.1.24&amp;lt;/version&amp;gt;&lt;br /&gt;                &amp;lt;configuration&amp;gt;&lt;br /&gt;                    &amp;lt;connectors&amp;gt;&lt;br /&gt;                        &amp;lt;connector implementation=&amp;quot;org.mortbay.jetty.nio.SelectChannelConnector&amp;quot;&amp;gt;&lt;br /&gt;                            &amp;lt;port&amp;gt;2342&amp;lt;/port&amp;gt;&lt;br /&gt;                        &amp;lt;/connector&amp;gt;&lt;br /&gt;                    &amp;lt;/connectors&amp;gt;&lt;br /&gt;                    &amp;lt;stopKey&amp;gt;stop&amp;lt;/stopKey&amp;gt;&lt;br /&gt;                    &amp;lt;stopPort&amp;gt;9999&amp;lt;/stopPort&amp;gt;&lt;br /&gt;                &amp;lt;/configuration&amp;gt;&lt;br /&gt;                &amp;lt;executions&amp;gt;&lt;br /&gt;                    &amp;lt;execution&amp;gt;&lt;br /&gt;                        &amp;lt;id&amp;gt;start-jetty&amp;lt;/id&amp;gt;&lt;br /&gt;                        &amp;lt;phase&amp;gt;process-classes&amp;lt;/phase&amp;gt;&lt;br /&gt;                        &amp;lt;goals&amp;gt;&lt;br /&gt;                            &amp;lt;goal&amp;gt;run&amp;lt;/goal&amp;gt;&lt;br /&gt;                        &amp;lt;/goals&amp;gt;&lt;br /&gt;                        &amp;lt;configuration&amp;gt;&lt;br /&gt;                            &amp;lt;daemon&amp;gt;true&amp;lt;/daemon&amp;gt;&lt;br /&gt;                        &amp;lt;/configuration&amp;gt;&lt;br /&gt;                    &amp;lt;/execution&amp;gt;&lt;br /&gt;                    &amp;lt;execution&amp;gt;&lt;br /&gt;                        &amp;lt;id&amp;gt;stop-jetty&amp;lt;/id&amp;gt;&lt;br /&gt;                        &amp;lt;phase&amp;gt;post-integration-test&amp;lt;/phase&amp;gt;&lt;br /&gt;                        &amp;lt;goals&amp;gt;&lt;br /&gt;                            &amp;lt;goal&amp;gt;stop&amp;lt;/goal&amp;gt;&lt;br /&gt;                        &amp;lt;/goals&amp;gt;&lt;br /&gt;                    &amp;lt;/execution&amp;gt;&lt;br /&gt;                &amp;lt;/executions&amp;gt;&lt;br /&gt;            &amp;lt;/plugin&amp;gt;&lt;br /&gt;        &amp;lt;/plugins&amp;gt;&lt;br /&gt;    &amp;lt;/build&amp;gt;&lt;br /&gt;&amp;lt;/project&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3647364277628708564-6018475226456620273?l=janxspirit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://janxspirit.blogspot.com/feeds/6018475226456620273/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://janxspirit.blogspot.com/2011/01/sneaking-scala-through-alley-test-java.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3647364277628708564/posts/default/6018475226456620273'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3647364277628708564/posts/default/6018475226456620273'/><link rel='alternate' type='text/html' href='http://janxspirit.blogspot.com/2011/01/sneaking-scala-through-alley-test-java.html' title='Sneaking Scala Through the Alley - Test Java Maven Web Services with Scala Specs'/><author><name>Gregg</name><uri>http://www.blogger.com/profile/03402091100291504512</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_4Cpi3vSt5Is/TT-unx8TWYI/AAAAAAAAGx8/3yNKJUn2s8c/s400/P1112170.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-wYU7-y0WPfY/TVgrnYk7yxI/AAAAAAAAAaw/uFQVWOtp99A/s72-c/netbeans_tests.jpg' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3647364277628708564.post-7078829507266914901</id><published>2011-01-27T22:30:00.000-08:00</published><updated>2011-02-01T14:47:47.439-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Scala'/><category scheme='http://www.blogger.com/atom/ns#' term='SBT'/><category scheme='http://www.blogger.com/atom/ns#' term='assembly'/><title type='text'>Create an Executable Scala Jar with SBT</title><content type='html'>A friend was asking about building an executable Jar with Scala and SBT. This ended up working for me.&lt;br /&gt;&lt;br /&gt;In a fresh SBT project, create the following files:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;project/build/AssemblyProject.scala&lt;/span&gt;&lt;br /&gt;(this file is lifted in its entirety from &lt;a href="http://technically.us/git?p=sling.git&amp;amp;a=blob&amp;amp;f=project/build/AssemblyProject.scala&amp;amp;h=2231d9c9c54b5cde7d54c52c360cc778a41e4e3e&amp;amp;hb=HEAD"&gt;here&lt;/a&gt; - thanks to Nathan Hamblen)&lt;br /&gt;&lt;pre class="brush: scala"&gt;&lt;br /&gt;import sbt._&lt;br /&gt;&lt;br /&gt;trait AssemblyProject extends BasicScalaProject {&lt;br /&gt;def assemblyExclude(base: PathFinder) = base / "META-INF" ** "*"&lt;br /&gt;def assemblyOutputPath = outputPath / assemblyJarName&lt;br /&gt;def assemblyJarName = artifactID + "-assembly-" + version + ".jar"&lt;br /&gt;def assemblyTemporaryPath = outputPath / "assembly-libs"&lt;br /&gt;def assemblyClasspath = runClasspath&lt;br /&gt;def assemblyExtraJars = mainDependencies.scalaJars&lt;br /&gt;def assemblyPaths(tempDir: Path, classpath: PathFinder, extraJars: PathFinder, exclude: PathFinder =&gt; PathFinder) = {&lt;br /&gt;val (libs, directories) = classpath.get.toList.partition(ClasspathUtilities.isArchive)&lt;br /&gt;for(jar &lt;- extraJars.get ++ libs) FileUtilities.unzip(jar, tempDir, log).left.foreach(error)  &lt;br /&gt;val base = (Path.lazyPathFinder(tempDir :: directories) ##)    (descendents(base, "*") --- exclude(base)).get }   &lt;br /&gt;lazy val assembly = assemblyTask(assemblyTemporaryPath, assemblyClasspath, assemblyExtraJars, assemblyExclude) dependsOn(compile)  &lt;br /&gt;def assemblyTask(tempDir: Path, classpath: PathFinder, extraJars: PathFinder, exclude: PathFinder =&gt; PathFinder) =&lt;br /&gt; packageTask(Path.lazyPathFinder(assemblyPaths(tempDir, classpath, extraJars, exclude)), assemblyOutputPath, packageOptions)&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;project/build/Project.scala&lt;/span&gt;&lt;br /&gt;&lt;pre class="brush: scala"&gt;&lt;br /&gt;import sbt._&lt;br /&gt;&lt;br /&gt;class ExecutableProject(info: ProjectInfo) extends DefaultProject(info) with AssemblyProject {&lt;br /&gt;override def mainClass = Some("RunMe")&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;src/main/scala/RunMe.scala&lt;/span&gt;&lt;br /&gt;&lt;pre class="brush: scala"&gt;&lt;br /&gt;object RunMe {&lt;br /&gt;def main(args: Array[String]) = {&lt;br /&gt;println("I run.")&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Now in your sbt shell, run:&lt;br /&gt;&lt;pre class="brush: bash"&gt;reload&lt;br /&gt;compile&lt;br /&gt;assembly&lt;br /&gt;&lt;/pre&gt;That will create an executable jar in the target/scala_*version* directory. You can run it with something like:&lt;br /&gt;&lt;pre class="brush: bash"&gt;java -jar target/scala_2.8.1/runme_2.8.1-assembly-1.0.jar&lt;br /&gt;I run.&lt;br /&gt;&lt;/pre&gt;Thanks to Nathan Hamblen for the AssemblyProject trait.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3647364277628708564-7078829507266914901?l=janxspirit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://janxspirit.blogspot.com/feeds/7078829507266914901/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://janxspirit.blogspot.com/2011/01/create-executable-scala-jar-with-sbt.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3647364277628708564/posts/default/7078829507266914901'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3647364277628708564/posts/default/7078829507266914901'/><link rel='alternate' type='text/html' href='http://janxspirit.blogspot.com/2011/01/create-executable-scala-jar-with-sbt.html' title='Create an Executable Scala Jar with SBT'/><author><name>Gregg</name><uri>http://www.blogger.com/profile/03402091100291504512</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_4Cpi3vSt5Is/TT-unx8TWYI/AAAAAAAAGx8/3yNKJUn2s8c/s400/P1112170.JPG'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3647364277628708564.post-1629987560599789255</id><published>2011-01-25T22:13:00.000-08:00</published><updated>2011-01-29T10:31:39.635-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Scala'/><category scheme='http://www.blogger.com/atom/ns#' term='SBT'/><category scheme='http://www.blogger.com/atom/ns#' term='Scalatra'/><category scheme='http://www.blogger.com/atom/ns#' term='MongoDB'/><category scheme='http://www.blogger.com/atom/ns#' term='Casbah'/><title type='text'>A Quick WebApp with Scala, MongoDB, Scalatra and Casbah</title><content type='html'>Here's a nice way to get a web service up and running quickly using Scala, Scalatra, SBT and MongoDB. I'm going to assume you have Scala installed but nothing beyond that. Feel free to skip the episodes you've already seen.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;Install SBT&lt;/span&gt;&lt;br /&gt;Simple Build Tool (SBT) is a build tool for Scala, and it's just super. To install it, download the jar from here: &lt;a href="http://code.google.com/p/simple-build-tool/downloads/list"&gt;http://code.google.com/p/simple-build-tool/downloads/list&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Put that jar someplace and the make a little script along the lines of this:&lt;br /&gt;&lt;pre class="brush:bash"&gt;java -Xmx1512M -XX:+CMSClassUnloadingEnabled -XX:MaxPermSize=512m -jar `dirname $0`/sbt-launch.jar "$@"&lt;br /&gt;&lt;/pre&gt;Save that alongside the jar you downloaded. Make it executable and add it to your PATH.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;MongoDB&lt;/span&gt;&lt;br /&gt;MongoDB ( &lt;a href="http://www.mongodb.org/"&gt;http://www.mongodb.org&lt;/a&gt; ) is a document database, meaning it persists JSON-like documents of arbitrary structure. It's very fast and offers very flexible ad hoc querying. A MongoDB document looks like this:&lt;br /&gt;&lt;pre class="brush: js"&gt;{&lt;br /&gt;_id : ObjectId("4d2167a24d2fa1a764a6f0fa"),&lt;br /&gt;date : "Sun Jan 02 2011 22:07:30 GMT-0800 (PST)",&lt;br /&gt;body : "My blog post!",&lt;br /&gt;upvotes : 3,&lt;br /&gt;downvotes : 0,&lt;br /&gt;comments : [&lt;br /&gt;{&lt;br /&gt;author : "The Dude",&lt;br /&gt;body : "The Dude abides"&lt;br /&gt;},&lt;br /&gt;{&lt;br /&gt;author : "Walter",&lt;br /&gt;body : "Over the line!"&lt;br /&gt;}&lt;br /&gt;]&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;You don't create joins in the database - each document is schema-less and unrelated to other documents, even those in its collection (sort of like a SQL table in MongoDB parlance), But you can do cool stuff like index on those nested comments. Here's how to install it and get started:&lt;br /&gt;&lt;br /&gt;Download the tarball for your architecture: http://www.mongodb.org/downloads&lt;br /&gt;&lt;br /&gt;Expand it somewhere and add the bin directory to your PATH if you want to.&lt;br /&gt;&lt;br /&gt;Run something like this to start the MongoDB server:&lt;br /&gt;&lt;pre class="brush: bash"&gt;$MONGO_HOME/bin/mongod --dbpath=/path/to/place/to/save/mongodb/data&lt;br /&gt;&lt;/pre&gt;Connect to it and try it out like so:&lt;br /&gt;&lt;pre class="brush: bash"&gt;$MONGO_HOME/bin/mongo&lt;br /&gt;&lt;/pre&gt;'mongo' is the MongoDB shell, which is a complete Javascript environment and connects to the local server on the default port. Create the example document above like this:&lt;br /&gt;&lt;pre class="brush: bash"&gt;&amp;gt; use temp&lt;br /&gt;switched to db temp&lt;br /&gt;&amp;gt; db.demo.insert({date:new Date(), body:'My blog post!', upvotes: 3, dowvotes: 0, comments: [{author: 'The Dude', body: 'The Dude abides'},{author: 'Walter', body: 'Over the line!'}]})&lt;br /&gt;&amp;gt; db.demo.find()&lt;br /&gt;&lt;/pre&gt;It's an excellent tool and a lot of fun. There are great docs at http://mongodb.org&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;Creating the SBT Project&lt;/span&gt;&lt;br /&gt;Let's create an application. Make yourself a directory, navigate to it and run sbt. It will guide you through a wizard experience thusly:&lt;br /&gt;&lt;pre class="brush: bash"&gt;$ sbt&lt;br /&gt;Project does not exist, create new project? (y/N/s) y&lt;br /&gt;Name: Demo&lt;br /&gt;Organization: com.demo&lt;br /&gt;Version [1.0]:&lt;br /&gt;Scala version [2.7.7]: 2.8.1&lt;br /&gt;sbt version [0.7.4]:&lt;br /&gt;Getting Scala 2.7.7 ...&lt;br /&gt;...more stuff...&lt;br /&gt;[success] Successfully initialized directory structure.&lt;br /&gt;...more stuff...&lt;br /&gt;[info] Building project Demo 1.0 against Scala 2.8.1&lt;br /&gt;[info]    using sbt.DefaultProject with sbt 0.7.4 and Scala 2.7.7&lt;br /&gt;&amp;gt;&lt;br /&gt;&lt;/pre&gt;Leave that shell open to the sbt prompt. In your editor of choice, create a file in your project directory named&lt;br /&gt;&lt;pre class="brush: bash"&gt;project/build/Project.scala&lt;br /&gt;&lt;/pre&gt;Add the following to it:&lt;br /&gt;&lt;pre class="brush: scala"&gt;import sbt._&lt;br /&gt;class build(info: ProjectInfo) extends DefaultWebProject(info) {&lt;br /&gt;// scalatra&lt;br /&gt;val sonatypeNexusSnapshots = "Sonatype Nexus Snapshots" at "https://oss.sonatype.org/content/repositories/snapshots"&lt;br /&gt;val sonatypeNexusReleases = "Sonatype Nexus Releases" at "https://oss.sonatype.org/content/repositories/releases"&lt;br /&gt;val scalatra = "org.scalatra" %% "scalatra" % "2.0.0.M2"&lt;br /&gt;&lt;br /&gt;// jetty&lt;br /&gt;val jetty6 = "org.mortbay.jetty" % "jetty" % "6.1.22" % "test"&lt;br /&gt;val servletApi = "org.mortbay.jetty" % "servlet-api" % "2.5-20081211" % "provided"&lt;br /&gt;&lt;br /&gt;//casbah&lt;br /&gt;val casbah = "com.mongodb.casbah" %% "casbah" % "2.0.1"&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;In your sbt shell, run&lt;br /&gt;&lt;pre class="brush: bash"&gt;reload&lt;br /&gt;&lt;/pre&gt;and then&lt;br /&gt;&lt;pre class="brush: bash"&gt;update&lt;br /&gt;&lt;/pre&gt;SBT will download dependencies ending with a message of success.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;Add a Scalatra GET handler&lt;/span&gt;&lt;br /&gt;Scalatra is  refreshingly simple. To create a Scalatra servlet with a simple GET handler, using Scala's support for XML literals, create a file like src/main/scala/WebApp.scala with the following content:&lt;br /&gt;&lt;pre class="brush: scala"&gt;import org.scalatra._&lt;br /&gt;&lt;br /&gt;class WebApp extends ScalatraServlet {&lt;br /&gt;get("/hello") {&lt;br /&gt;&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Hello!&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&amp;lt;body&amp;gt;&amp;lt;h1&amp;gt;Hello&amp;lt;/h1&amp;gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;web.xml&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;One last bit of setup is to add the Scaltra servlet to the web.xml. Create a file named /src/main/webapp/WEB-INF/web.xml with the following content:&lt;br /&gt;&lt;pre class="brush: xml"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;br /&gt;&amp;lt;!DOCTYPE web-app&lt;br /&gt;PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"&lt;br /&gt;"http://java.sun.com/j2ee/dtds/web-app_2_2.dtd"&amp;gt;&lt;br /&gt;&amp;lt;web-app&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;servlet&amp;gt;&lt;br /&gt;&amp;lt;servlet-name&amp;gt;WebApp&amp;lt;/servlet-name&amp;gt;&lt;br /&gt;&amp;lt;servlet-class&amp;gt;WebApp&amp;lt;/servlet-class&amp;gt;&lt;br /&gt;&amp;lt;/servlet&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;servlet-mapping&amp;gt;&lt;br /&gt;&amp;lt;servlet-name&amp;gt;WebApp&amp;lt;/servlet-name&amp;gt;&lt;br /&gt;&amp;lt;url-pattern&amp;gt;/*&amp;lt;/url-pattern&amp;gt;&lt;br /&gt;&amp;lt;/servlet-mapping&amp;gt;&lt;br /&gt;&amp;lt;/web-app&amp;gt;&lt;br /&gt;&lt;/pre&gt;Back at the SBT prompt you just need to&lt;br /&gt;&lt;pre class="brush: bash"&gt;reload&lt;/pre&gt;and then do the following to start jetty and listen for source file changes:&lt;br /&gt;&lt;pre class="brush: bash"&gt;jetty-run&lt;br /&gt;~prepare-webapp&lt;br /&gt;&lt;/pre&gt;Open a browser to http://localhost:8080/hello and you should get a working Scalatra app. Change the message to something more interesting, like "Hello World" or "Goodnight Moon", save the source file, and SBT will recompile and redeploy.  Just reload the web browser to see your changes.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;Parameters&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Add a path parameter to your GET call thusly:&lt;br /&gt;&lt;pre class="brush: scala"&gt;&lt;br /&gt;get("/hello/:name") {&lt;br /&gt;&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Hello!&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&amp;lt;body&amp;gt;&amp;lt;h1&amp;gt;Hello {params("name")}!&amp;lt;/h1&amp;gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Save the file, browse to http://localhost:8080/hello/handsome&lt;br /&gt;&lt;br /&gt;Oh yeah!&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;A Form&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Add a form like this:&lt;br /&gt;&lt;pre class="brush: scala"&gt; get("/msgs") {&lt;br /&gt;&amp;lt;body&amp;gt;&lt;br /&gt;&amp;lt;form method="POST" action="/msgs"&amp;gt;&lt;br /&gt;Author: &amp;lt;input type="text" name="author"/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;Message: &amp;lt;input type="text" name="msg"/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;&amp;lt;input type="submit"/&amp;gt;&lt;br /&gt;&amp;lt;/form&amp;gt;&lt;br /&gt;&amp;lt;/body&amp;gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;You can see the fruits of your labor at http://localhost:8080/msgs&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;Casbah&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Casbah is the officially supported Scala driver for Mongo. It wraps the Java driver and makes accessing MongoDB straightforward using idiomatic Scala. &lt;a href="http://api.mongodb.org/scala/casbah/2.0.2/index.html"&gt;http://api.mongodb.org/scala/casbah/2.0.2/index.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;You already have the driver dependency in your project, but you'll need a few new imports:&lt;br /&gt;&lt;pre class="brush: scala"&gt;import com.mongodb._&lt;br /&gt;import com.mongodb.casbah.Imports._&lt;br /&gt;import scala.xml._&lt;br /&gt;&lt;/pre&gt;And a MongoDB connection that can be shared across the application:&lt;br /&gt;&lt;pre class="brush: scala"&gt;val mongo = MongoConnection()&lt;br /&gt;val coll = mongo("blog")("msgs")&lt;br /&gt;&lt;/pre&gt;Add a method to handle the form POST:&lt;br /&gt;&lt;pre class="brush: scala"&gt;&lt;br /&gt;post("/msgs") {&lt;br /&gt;val builder = MongoDBObject.newBuilder&lt;br /&gt;builder += "author" -&gt; params("author")&lt;br /&gt;builder += "msg" -&gt; params("msg")&lt;br /&gt;&lt;br /&gt;coll += builder.result.asDBObject&lt;br /&gt;redirect("/msgs")&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Slick, right? That's all it takes to add a new document to the "msgs" collection in the "blog" db. You don't even need to create the db and collection first - just make sure MongoDB is running on the local host at the default port 27017.&lt;br /&gt;&lt;br /&gt;Now you should adjust the form page to display the existing messages. This code treats iterates over the whole collection - in a real-world application you'd want paging, querying, filtering etc.&lt;br /&gt;&lt;br /&gt;Add this code to your get() method just after the body tag:&lt;br /&gt;&lt;pre class="brush: scala"&gt; &lt;br /&gt;&amp;lt;ul&amp;gt;&lt;br /&gt;{for (l &lt;- coll) yield &amp;lt;li&amp;gt;          &lt;br /&gt; From: {l.getOrElse("author", "???")} -                           &lt;br /&gt; {l.getOrElse("msg", "???")}&amp;lt;/li&amp;gt;}                       &lt;br /&gt; &amp;lt;/ul&amp;gt;&lt;/pre&gt;  &lt;br /&gt;Once your app builds and you reload the page, your form should work to add new messages with authors and display them.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;In Conclusion&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I've found this stack a great way to whip up a quick example, prototype or test. You can use SBT to build a war (the 'package' command) and deploy it to any container you want.&lt;br /&gt;&lt;br /&gt;I've barely scratched the surface of any of these bits, but hopefully piqued some interest in some cool tools. There are great docs and examples for all of these projects, so dig in and have fun!&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;Source code:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;project/build/Project.scala:&lt;/span&gt;&lt;br /&gt;&lt;pre class="brush: scala"&gt;&lt;br /&gt;import sbt._&lt;br /&gt;class build(info: ProjectInfo) extends DefaultWebProject(info) {&lt;br /&gt;// scalatra&lt;br /&gt;val sonatypeNexusSnapshots = "Sonatype Nexus Snapshots" at "https://oss.sonatype.org/content/repositories/snapshots"&lt;br /&gt;val sonatypeNexusReleases = "Sonatype Nexus Releases" at "https://oss.sonatype.org/content/repositories/releases"&lt;br /&gt;val scalatra = "org.scalatra" %% "scalatra" % "2.0.0.M2"&lt;br /&gt;&lt;br /&gt;// jetty&lt;br /&gt;val jetty6 = "org.mortbay.jetty" % "jetty" % "6.1.22" % "test" servletApi = "org.mortbay.jetty" % "servlet-api" % "2.5-20081211" % "provided"&lt;br /&gt;&lt;br /&gt;//casbah&lt;br /&gt;val casbah = "com.mongodb.casbah" %% "casbah" % "2.0.1"&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;src/main/scala/WebApp.scala:&lt;/span&gt;&lt;br /&gt;&lt;pre class="brush: scala"&gt;&lt;br /&gt;import org.scalatra._&lt;br /&gt;import com.mongodb.casbah.Imports._&lt;br /&gt;import scala.xml._&lt;br /&gt;import com.mongodb._&lt;br /&gt;&lt;br /&gt;class WebApp extends ScalatraServlet {&lt;br /&gt;&lt;br /&gt;val mongo = MongoConnection()&lt;br /&gt;val coll = mongo("blog")("msgs")&lt;br /&gt;&lt;br /&gt;get("/hello/:name") {&lt;br /&gt;&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Hello!&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&amp;lt;body&amp;gt;&amp;lt;h1&amp;gt;Hello {params("name")}!&amp;lt;/h1&amp;gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;get("/msgs") {&lt;br /&gt;&amp;lt;body&amp;gt;&lt;br /&gt; &amp;lt;ul&amp;gt;&lt;br /&gt;   {for (l &amp;lt;- coll) yield &amp;lt;li&amp;gt;        &lt;br /&gt;   From: {l.getOrElse("author", "???")} -       &lt;br /&gt;   {l.getOrElse("msg", "???")}&amp;lt;/li&amp;gt;}           &lt;br /&gt; &amp;lt;/ul&amp;gt;&lt;br /&gt; &amp;lt;form method="POST" action="/msgs"&amp;gt;&lt;br /&gt;   Author: &amp;lt;input type="text" name="author"/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;   Message: &amp;lt;input type="text" name="msg"/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;   &amp;lt;input type="submit"/&amp;gt;&lt;br /&gt; &amp;lt;/form&amp;gt;&lt;br /&gt;&amp;lt;/body&amp;gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;post("/msgs") {&lt;br /&gt;val builder = MongoDBObject.newBuilder&lt;br /&gt;builder += "author" -&amp;gt; params("author")&lt;br /&gt;builder += "msg" -&amp;gt; params("msg")&lt;br /&gt;&lt;br /&gt;coll += builder.result.asDBObject&lt;br /&gt;redirect("/msgs")&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3647364277628708564-1629987560599789255?l=janxspirit.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://janxspirit.blogspot.com/feeds/1629987560599789255/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://janxspirit.blogspot.com/2011/01/quick-webb-app-with-scala-mongodb.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3647364277628708564/posts/default/1629987560599789255'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3647364277628708564/posts/default/1629987560599789255'/><link rel='alternate' type='text/html' href='http://janxspirit.blogspot.com/2011/01/quick-webb-app-with-scala-mongodb.html' title='A Quick WebApp with Scala, MongoDB, Scalatra and Casbah'/><author><name>Gregg</name><uri>http://www.blogger.com/profile/03402091100291504512</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_4Cpi3vSt5Is/TT-unx8TWYI/AAAAAAAAGx8/3yNKJUn2s8c/s400/P1112170.JPG'/></author><thr:total>4</thr:total></entry></feed>
