Tuesday, September 25, 2007

Fast Web Development With Scala

I am currently experimenting with Scala. It seems quite convenient for web applications. Using Tomcat, it is possible to have a very productive developer environment.
Here is a sample Embedded Tomcat you can start in a Scala project:
import java.io._;
import org.apache.catalina._;
import org.apache.catalina.startup._;

object TomcatScalaServer {
  
  val CATALINAHOME : File = new File("../newsbeef.com");
  val WEBAPPS : File = new File(CATALINAHOME,"webapps");
  val ROOT : File = new File(CATALINAHOME,"web");
  val HOSTNAME : String = "localhost";
  val PORT : int 8080;
  
  def await() {
     whiletrue ) {
          try {
            System.out.println("sleeping 100s");
              Thread.sleep100000 );
          catch {
            case ie : InterruptedException =>;
          }
      }
  }
  
  def start() {
    val server = new Embedded();
    server.setCatalinaHome(CATALINAHOME.getAbsolutePath());

    val engine = server.createEngine();
    engine.setDefaultHost(HOSTNAME);

    val host = server.createHost(HOSTNAME, WEBAPPS.getAbsolutePath());
    engine.addChild(host);

    val context = server.createContext("", ROOT.getAbsolutePath());
     context.setParentClassLoader(Thread.currentThread().getContextClassLoader());
     context.setReloadable(true);
    host.addChild(context);

    server.addEngine(engine);

    val http = server.createConnector(HOSTNAME, PORT, false);
    server.addConnector(http);

    server.start();
  }
  
  def main(args: Array[String]) {
    start();
    await();
  }

}

Here is a sample Scala Servlet outputing html directly. This is a simple example, but it shows something important. With Scala, the view layer can just be regular scala classes. There is no need for JSP or other templating languages as Scala already embbeds XML very nicely. By using the reloadable feature of Tomcat (there are also other pure Scala ways) and Eclipse autocompile, changes are instantanously taken in account.
import javax.servlet.http._;

class ScalaServlet extends HttpServlet {

  override def init() {
  }
  
  override def doGet(request : HttpServletRequest , response : HttpServletResponse{
    service(request, response)
  }
  
  override def service(req: HttpServletRequest,resp: HttpServletResponse) { 
    val pw = resp.getWriter();
    var output = <html>
    <head><title>Scala Servlet Test</title></head>
    <body>
      <h1>Hello World!</h1>
    </body>
    </html>
    pw.println(output);
    pw.flush();
  }
}

Now I am eagerly waiting for improvements in the Eclipse Scala plugin (Organise imports, class navigation).

5 comments :

  1. Actually I've never written a servlet, since seeing the examples when they originally came out I was turned off by the verbosity. Scala might actually win me over to tomcat.
    Thanks...

    ReplyDelete
  2. Looks absolutely usable, I guess I should give tomcat a try after a long time of absence..

    Thanks for sharing!

    ReplyDelete
  3. Or just use Jetty:

    Server server = new Server();
    SelectChannelConnector connector = new SelectChannelConnector();
    connector.setPort(8080);
    server.addConnector(connector);

    WebAppContext web = new WebAppContext();
    web.setContextPath("/wia");
    web.setWar("src/webapp");
    server.addHandler(web);

    try {
    server.start();
    server.join();
    } catch (Exception e) {
    e.printStackTrace();
    System.exit(100);
    }

    could even be written shorter if you want. And Scala or Java... in this case (or Tomcat's) it doesn't matter much does it?

    ReplyDelete
  4. Jetty or Tomcat don't really matter in this case, it is just that Tomcat is more popular, and contrary to what many people think, can also start as fast as Jetty and be embedded just as simply.

    Java or Scala makes a difference, because of features that makes Scala neat, for example XML handling. One could imagine a web system purely built with Scala classes, Scala being used as templating/component language directly.

    ReplyDelete
  5. Lift makes nice use of the ability to directly use X(H)ML. Not something to go overboard with if you ask me, but nice to have some times.

    Btw, what I meant with Jetty:

    import org.mortbay.jetty.Server
    import org.mortbay.jetty.webapp.WebAppContext

    object JettyRunner {

    def main(args: Array[String]) {
    val server = new Server(8080)
    val web = new WebAppContext(server, "src/main/webapp", "/wia")
    server.start()
    server.join()
    }
    }

    That's nice and short, no? I know that Tomcat is as useable, but with older versions you had to provide an absolute path and stuff (kind of like what you do in your example). And that sucks.

    ReplyDelete