For a little educational project intended as a community resource to help people learn Scala I am looking for a simple way to serve and process web pages in a background thread.
Minimal background: Scalatron is a multi-player game in which players pit bot programs (written in Scala) against each other. It is accompanied by a step-by-step Scala tutorial. Currently players need to use an IDE on their local machines to compile bots, which are then published into the game by copying them into a shared network directory. This is cumbersome. For the next version it would be nice to offer browser-based bot editing and publishing to maximally simplify the setup for both organizers and players.
I already got a background thread working that will compile Scala source code arriving on the server on the fly (obviating the need for a full IDE). Next I have to run a tiny web server to provide an access point for players and to handle bot uploads (this gets rid of the network share).
The requirements are very basic: initially I envisage serving a single page with an edit box and a "Go" button (= upload to server, compile & publish into game); I expect no more than 20 concurrent users with not more than one bot upload across all users every 5 or 10 seconds; I need to hold minimal state for each users (just a name) and I need to return compiler error messages to the user. Note that game screen updates would NOT be displayed in the browser but on a projector attached to the server machine. And primarily to allow for the simplest possible setup (double click on the game server .jar) I think it would be nice to run the web server in a background thread within the existing game server.
What is the most appropriate way to do this? Should I use some existing framework, like Play or Lift? Is there existing code for doing something very similar to this? Is it even reasonable to plan to run a web server in a background thread like this? Any advice is appreciated.
One of the most used small, embeddable web servers / servlet containers in the Java world is Jetty. Since Scala can easily use Java libraries, it should be easy to use this from Scala.
This page shows some simple examples (in Java) on how to start it as an embedded HTTP server.
Embedded web servers is exactly what Unfiltered was made for. The basic philosophy for Unfiltered is that the web server is just a library you call from your code, instead of your code being something the web framework calls.
Embedding Jetty is fairly easy, being one of the primary goals for the Jetty project. If you needs are simple, this is the quickest route. I suspect you will quickly need a more robust solution (models, routing, templates, etc) so using a framework like Lift or Play Framework would be a better idea.
Here are a couple of different examples of embedding Java containers and Scala frameworks:
- Netty + Finagle
- Jetty + Lift
While both of these talk about running the application on Heroku, you can just run them as Scala applications standalone.
val webServer = new Thread("Web Server") {
def response(text: String, code: String = "200 OK") =
"""HTTP/1.0 """ + code + """
Content-Type: text/html
Content-Length: """ + text.length + """
""" + text
override def run {
for(port <- env.webPort) {
val ss = new ServerSocket(port)
while (true) try {
val s = ss.accept
try { s.getOutputStream.write(response(someStuff.toString).getBytes)
} finally { s.close }
} catch { case ie: InterruptedException => return }
}
}
}
See also scala kittens
As you want to provide a framework, I think that the best solution is to use an existing framework, that way you won't have to bother with re-inventing stuff.
From my personal experience, which is really subjective, I would suggest you to use Lift as I know that it is very powerful for the support of sessions, global snippets and other stuff. You can try to extend the classical chat app that is used as an example of how lift works, testing wether it is useful for your use or not shouldn't be long.