Cross-browser compatible, real-time, bi-directional communication between ClojureScript and Clojure using Google Closure BrowserChannel.
clj-browserchannel-demo is an example chat application using a server side implementation for BrowserChannel written in Clojure. The server component is for BrowserChannel version 8.
The example runs in at least:
- Internet Explorer 5.5+ (!!)
- Android browser
When there are long lasting connections between a client and a webserver it is desirable to not have a thread per connection. Therefore this demo runs with with an asynchronous Jetty adapter. This adapter is compatible with Ring.
The adapter is based on ring-jetty-async-adapter by Mark McGranaghan.
An implementation on top of Netty, through Aleph is in development.
Related and alternative frameworks
- Websockets - Websockets solve the same problems as BrowserChannel, however BrowserChannel works on almost all existing clients.
- socket.io - socket.io provides a similar api as BrowserChannel on top of many transport protocols, including websockets. BrowserChannel only has two transport protocols: XHR and forever frames (for IE) in streaming and non-streaming mode.
;; compile cljs lein run -m tasks.build-dev-js ;; compile cljs in advanced mode lein run -m tasks.build-advanced-js lein run -m chat-demo.core
Run on Heroku
Use the Heroku Clojure buildpack.
heroku config:add BUILDPACK_URL=https://github.com/heroku/heroku-buildpack-clojure.git
This project additionally requires two build tasks to compile the ClojureScript during deployment.
heroku labs:enable user_env_compile -a <YOUR_APP_NAME>
Add this config var:
heroku config:add LEIN_BUILD_TASK="run -m tasks.build-dev-js, run -m tasks.build-advanced-js"
Note on disconnections on Heroku
I have found that Heroku does not immediately report when a connection to a client is broken. If the client is able to reconnect this is not a problem, as this is supported by the BrowserChannel API. However when you unplug the internet cable the client cannot reconnect and the server must timeout the session. Ussually this happens when trying to send the next heartbeat to the client. On Heruko this does not report an error, even though there is no connection to the client. So instead of the connection timeing out on a heartbeat (after seconds/a minute) the connection will only timeout after the connection is timed out by the server (4 minutes by default). The Netty implementation has the same problem on Heroku. Deployments on Amazon Web Services do not have this problem.
See default-options in src/net/thegeez/browserchannel.clj And the :response-timeout option in src/net/thegeez/jetty_async_adapter.clj
Debug / Play around
BrowserChannel has a helpful debug window. Uncomment the debug-window and .setChannelDebug lines in cljs/bc/core.cljs to enable the logging window.
- Release backend as library
- Handling acknowledgements by client and callbacks on queued arrays
- Host prefixes
- Heroku disconnection
- Replace session listeners, possibly with lamina
- Explore other event based Java webservers, such as Netty and Webbit
Other BrowserChannel implementations
Many thanks to these authors, their work is the only open-source documentation on the BrowserChannel protocol.
- libevent-browserchannel-server in C++ by Andy Hochhaus - Has the most extensive documentation on the BrowserChannel protocol
- browserchannel in Ruby by David Turnbull
Copyright (c) 2012 Gijs Stuurman and released under an MIT license.