Atmosphere, Scala, SBT & Akka — Step-by-step
Atmosphere is a popular java library for writing real-time, browser-based applications. It’s killer feature is that it switches between websockets, long-polling and other transports based on browser support.
However, all the examples use maven and are mostly in java. It took me a while, but I’ll help you set one up in Scala with an application that also uses SBT and Akka very quickly.
Because I’m helpful, I’ll show you how to add debugging and logging support, too. All the code for this demo lives on my github.
Scalatra and Play have plugins for Atmosphere, but I found those to be brittle whilst also overly restrictive of the Scala/Akka versions you can use.
The Process
- Create an SBT project, with the atmosphere dependencies in your build file
- Add the webapp folder, and wire up the atmosphere servlet in your web.xml
- Create an atmosphere handler
- Add dependencies to build.sbt to detect handlers via annotations
- Tell sbt to output classes in webapp/WEB-INF/classes so atmosphere can find them during testing/debugging
- Add a html page to test the back-end
- Add xsbt-web plugin to test/debug the application
- Add logging dependency to see application output
- Add Akka dependency
- Create an actor system and use it to fulfill atmosphere requests
Create an Empty Atmosphere Project
Navigate to the directory where you would like to create the application, then create the sbt folder structure:
https://gist.github.com/NTCoding/6597699.js
In the root of the project, create a build.sbt file:
https://gist.github.com/NTCoding/6597723.js
And fill it with the following content:
https://gist.github.com/NTCoding/6597752.js
Now initialise the sbt project, so it’s prepared to pull in the atmosphere dependencies:
https://gist.github.com/NTCoding/6597779.js
To complete setting up the project, add a web.xml file in src/main/webapp/WEB-INF with the following instructions that tell the project to send all requests on the path /search to the atmosphere servlet (line 18):
https://gist.github.com/NTCoding/6597791.js
Create an Atmosphere Handler
With the project outline setup and the dependencies in place, we can create an atmosphere handler to handle http requests and send asynchronous responses down to the browser via websockets, long-polling or another transport.
Add the following scala class in the folder src/main/scala/atmo_demo. Name the file Searcher.scala:
https://gist.github.com/NTCoding/6597819.js
This won’t compile until you append the following dependencies to build.sbt:
https://gist.github.com/NTCoding/6597840.js
You should now go back to the sbt prompt, execute the “reload” command, and then the “compile” command and everything should be fine.
Because the class had attributes telling atmosphere it was a handler, the following two dependencies also need to be added so the annotations are detected at runtime:
https://gist.github.com/NTCoding/6597860.js
Output Classes to WEB-INF Where Atmosphere Looks
Atmosphere will look for all classes with the annotation @ManagedService shown in the previous example. It will look in the WEB-INF/classes folder, by default.
SBT on the other hand outputs classes to target/Scala-x.x. But we can tell SBT to output classes to the WEB-INF folder easily by appending the following to build.sbt:
https://gist.github.com/NTCoding/6597883.js
Testing the Application is Working — Logging and Debugging
To test the application so far is working, first the xsbt-web plugin needs to be added to run the application. Secondly, the slf4j logging framework should be imported so the application logs can be seen in the console.
Create the folder “project” in the root of the project. Then inside it create a file called plugins.sbt with the following content:
https://gist.github.com/NTCoding/6597910.js
Next import the sbt commands for this plugin by adding the following to build.sbt:
https://gist.github.com/NTCoding/6597930.js
One more step is required to get the debugging step working — add jetty to the list of dependencies in build.sbt:
https://gist.github.com/NTCoding/6598039.js
To test this is working, go back to the sbt prompt, execute the “reload” command and then the “container:start” command. The output should be minimal, but confirm the application is working:
https://gist.github.com/NTCoding/6598049.js
Add a Touch of Logging
By adding some logging at this stage we can see in more detail how both the application and atmosphere started up. Simply add the following dependency to bulid.sbt:
https://gist.github.com/NTCoding/6598055.js
Running “reload” then “container:stop” and finally “container:start” again, this time produces the more informative:
https://gist.github.com/NTCoding/6598023.js
If you look around line 8 you can see that it looked in WEB-INF/class and found our Searcher class because of the annotations added to it.
Quickly add the following log message to the Searcher class so we can see messages passing through the system when it is up and running:
https://gist.github.com/NTCoding/6598006.js
Creating a Front-End
Atmosphere has it’s own javascript library for managing the connection to the server. All you need to do is configure the connection, then add your message sending and handling.
There’s a plain html page in the webapp folder on my github that has a text box and a button.
Notice that in the page there is a reference to atmosphere.js in the webapp/javascript folder. There is also a reference to jquery and application.js which sends messages to the server when someone enters them into the search box. It also handles responses by displaying them in a message box.
If you go onto my github you can copy down those 4 files into your project so you can now test it….
Test it out…
If you now run “container:stop” and then “container:start” at the sbt command prompt the application should have successfully started up on port 8080.
If it has, navigate to localhost:8080 then type in your search term and click the button. Keep an eye on the console logs in the browser and console window where you ran “container:start”. You should be able to see messages flowing from client to server and server to client.
Akka Support
If you want to put your real-time streaming front-end on top of a concurrent, distributed back-end then Akka is the only part missing from this demo.
The simplest way to do this is to first add a dependency on akka:
https://gist.github.com/NTCoding/6597984.js
Then update the searcher class to create an Actor System and spin up actors as needed like so:
https://gist.github.com/NTCoding/6597962.js
Now, at an SBT prompt, execute the commands “reload”, “compile”, “container:stop” and finally “container:start”. Your application will again be running on localhost:8080.
If you go to that url and enter a search term, this time you will see the transformed message coming back from the actor.
You are now free to enjoy the benefits of this Fat Tech Stack.