Checkout Ring Adapter for Jetty 9

Wed 24 April 2013
  • ANN tags:
  • clojure
  • jetty
  • web
  • websocket published: true comments: true

The Clojure world has been using Jetty 7 for quite a long time because it's supported by the Ring development team. However, Jetty 9 brings us exciting features like WebSocket and SPDY. In order to use websocket in my Clojure web application, I built this adapter last weekend.

[info.sunng/ring-jetty9-adapter "0.1.0"]

The API for Clojure is still consistent with the one for jetty 7.
[cc lang="clojure"]
(use 'ring.adapter.jetty9)
(run-jetty app {})
[/cc]

Options supported in jetty 9 are almost same as jetty 7 except the configurator is dropped. And a new "WebSockets" option is added. Accepting a map of context path and websocket class, it enables websocket protocol in your web application.

[cc lang="clojure"]
(use 'ring.adapter.jetty9)
(run-jetty app {:websockets {"/loc" LocationTracker}})
[/cc]

Due to the lack of WebSocket API standards, I don't spend time on the WebSocket abstraction. Just use Jetty's internal API for websocket. Here is a typical implementation of websocket listener.

;; sample code
(ns xxx.ws.location
  (:gen-class
   :name xxx.LocationTracker
   :init init
   :state state
   :extends org.eclipse.jetty.websocket.api.WebSocketAdapter
   :prefix ws-
   :exposes-methods {onWebSocketConnect superOnWebSocketConnect})
  (:require [clojure.data.json :as json]
            [clojure.tools.logging :as logging]
            [monger.collection :as mc])
  (:import (org.eclipse.jetty.websocket.api WebSocketAdapter)
           (java.util UUID)))

(defn ws-init []
  [[] {:client-id (str (UUID/randomUUID))}])

(defn ws-onWebSocketConnect [this session]
  (.superOnWebSocketConnect this session)
  (logging/warn "new connection: " (get-client-id this))

(defn ws-onWebSocketText [this message]
  (let [msg (json/read-json message)]
    (case (:type msg)
      ...)))

(defn ws-onWebSocketClose [this status reason]
  (logging/debug "close socket"))

Since Jetty will create new instance of adapter for each connection, it requires heavy usage of "gen-class" . Remember to add the namespace to AOT compilation. Detailed Jetty API spec can be found here.
And also find the project is here.