Features

There are comprehensive usage guides for many languages.

Scalibility is easy, just throw more nodes to the pool.

Scalability

Hello World example

import xitrum.Action
import xitrum.annotation.GET

@GET("url/to/HelloAction")
class HelloAction extends Action {
  def execute() {
    val urlToHelloActor = url[HelloActor]
    respondHtml(
      <xml:group>
        <p>Hello {remoteIp}!</p>
        <a href={urlToHelloActor}>Actor example</a>
      </xml:group>
    )
  }
}

The above action runs directly on Netty's IO thread pool. It's very fast if your action is simple. If it's more complex, avoid blocking request receiving and response responding, by running it on another thread pool, by extending xitrum.FutureAction.

Actor example

import scala.concurrent.duration._
import akka.actor.ReceiveTimeout

import xitrum.ActorAction
import xitrum.annotation.GET

@GET("url/to/HelloActor")
class HelloActor extends ActorAction {
  def execute() {
    log.info("Request received: " + request)

    // Communicate with another actor
    anotherActorRef ! "aMsg"

    // Wait for the above actor to reply within 5s
    context.setReceiveTimeout(5.seconds)
    context.become {
      case aReply =>
        respondText(aReply)

      case ReceiveTimeout =>
        respondText("Timeout")
    }
  }

  override def postStop() {
    log.info("Connection closed or response sent")
    super.postStop()
  }
}

Just annotate your actors and they will be accessible from web!

WebSocket example

import xitrum.{
  WebSocketAction,
  WebSocketText, WebSocketBinary,
  WebSocketPing, WebSocketPong
}
import xitrum.annotation.WEBSOCKET

@WEBSOCKET("url/to/EchoWebSocketActor")
class EchoWebSocketActor extends WebSocketAction {
  def execute() {
    log.info("WebSocket onopen")

    context.become {
      case WebSocketText(text) =>
        respondWebSocketText(text)

      case WebSocketBinary(bytes) =>
        respondWebSocketBinary(bytes)

      case WebSocketPing =>
        // Xitrum automatically sends pong for you,
        // you don't have to send pong yourself

      case WebSocketPong =>
        // Client has received your ping
    }
  }

  override def postStop() {
    log.info("WebSocket onclose")
    super.postStop()
  }
}

SockJS example

import xitrum.{SockJsAction, SockJsText}
import xitrum.annotation.SOCKJS

@SOCKJS("url/to/EchoSockJsActor")
class EchoSockJsActor extends SockJsAction {
  def execute() {
    log.info("SockJS onopen")

    context.become {
      case SockJsText(text) =>
        respondSockJsText(text)
    }
  }

  override def postStop() {
    log.info("SockJS onclose")
    super.postStop()
  }
}

Presentations

Create a new empty Xitrum project from skeleton

See xitrum-new project.

Download xitrum-new.zip, unzip, then run:

sbt/sbt run

Now you have a new empty project running at http://localhost:8000/ and https://localhost:4430/

To generate Eclipse or IntelliJ project:

sbt/sbt eclipse
sbt/sbt gen-idea

News

CHANGELOG