a java.util.concurrent.locks.ReentrantLock() is used to implement the lock for the comet implementation. This was taken and slightly modified from the ServerJS comet example.

Whenever a subscription is fired on the server, the event queue (and thus the associated client) is saved in a global variable (remember JS is single threaded) so that when the server does a publish we know where to send the event.

Upon "/event/bind" the client creates stub event subscriptions which forward the actual event to the server using /event/forward

The client connects to /event/listen. Once it returns the client publishes the returned event and starts listening again immeditately.

Please excuse the messed up indentation, I was using a new editor (not bespin :).

I'm personally not convinced that this architecture should be used because the beauty of REST goes away. On the other hand, I feel that the artificial border between client and server does not make sense for some applications and thus it is great if it goes away. Opinions?

on the client. Because the server listens for that event, the event defined above will now fire. In the code snippet above the server immediately fires "test:receive". If now the client is subscriped to that event, this subscription will fire.

Events are transferred to the server via simple HTTP requests. Also the client maintains a comet connection to the server which is used to transfer events which are published on the server to the client.

Based on my twitter stream the implementation of this protoype took under 2 hours. Considering it was my first ever ServerJS application, I can only applaud the people behind ServerJS to the awesomeness of their work. While the current state is still somewhat experimental, it is amazing how much was achieved in so little time.

PS: It is only bespin.subscribe above because I did: var bespin = require("./pubsub").pubsub;

Sunday, May 17, 2009

Here is a video of my talk on postmodern web application at next conference:

...and the slides to follow along:

The target audience of the presentation was marketing guys with a tech affinity :) I'm going to enhance this with some more in depth tech content and a good part about Joose, of course, for my talk at SWDC2009 next Monday (By the way, there are ticket for 150 Euros for people attending from outside of sweden).

Monday, May 11, 2009

While experimenting with web workers in bespin I made a small change that makes working with them a lot nicer. In bespin we make heavy use of custom events to loosely bind things together in the application. So you see a lot of

bespin.publish("something:happened", { ... })

and

bespin.subscribe("something:happened", function () { ... })

The change I made is that you can now do the same thing in workers and it will Do The Right Thing (tm). Meaning you can subscribe to events that might be triggered by the UI or anywhere else from within the worker and also publish events that might be observed by handlers which live in the "main page". Overall this makes working with workers much more seamless and first class from a bespin perspective because it means that as long as one is not doing any direct UI work (as opposed to sending events to UI components) one can do everything from the worker without building custom interfaces.

For me working on bespin is really an experiment on how to design an event driven client side web applications (or postmodern web application). One of the things that felt kinda awkward up until now was how to know the right point in time to initialize a particular component. You might want to wait until the settings have been loaded (asynchronously via Ajax) and another component has been initialized. All these events are, of course, signaled by custom events but the order might be totally random and they might have already happened when we start looking for them. The solution I came up with (whether it is a good one remains to be seen) is to have a function that checks a list of events against all events that have fired already and then waits for the rest of the events to fire and finally calls a callback when this is done: