DontPush - Vaadin on WebSockets

Hi Vaadin fanatics,

I have been bit amazed how big “buzz” Artur’s
IcePush Add-on
has created among Vaadin users. Big enough to give him an iPad. Congrats! I’m bit jealous about the iPad, but I’m not convinced that it is much better (in terms of server performance and end user experience) than a simple polling solution via ProgressIndicator or Henrik’s Refresher. Same goes for pretty much all today’s main stream push implementations on the web. It sure is a nice hack for some chat apps, but it is nowhere near to be optimal long term solution for Vaadin. There are couple of issues with it that I see apparent.

The push channel is used just to indicate that there are changes on the server for the client. Another XHR is made to actually fetch them. Also for sending changes from client to server, the push channel (which is already open) isn’t used, but the std xhr method. So there is still lots of overhead from http headers and cookies, one precious http connection is used by the browser and in some cases the latency can be equal or even longer than with the infamous polling method.

Perhaps even larger pitfall is the method called push(). Its existence to be more precise. The thing best thing about Vaadin is, that you should be able to forget the client-server platform where your application is run. This sure ain’t for it. Now you know I named my todays work this way :slight_smile:

The success of Artur’s add-on inspired me to do a prototype with tomorrows technology today. HTML5 standard has a protocol called WebSocket, which is a perfect match for Vaadin. If you haven’t heard about the WebSocket communication method, google about them. WebSockets are actually here today: in browsers they work on practically all but IE’s and several Java web servers has built a support for them.

I started up with Jetty 7, gwt-websockets and Vaadin 6.5 branch. I had to forget the gwt-websockets GWT module and replace it with own solution. It didn’t play that well in hosted mode and I was about to give up the whole idea. There is now way that I could code without debugger at this age. Hooking a new communication channel to Vaadin wasn’t that easy too, but luckily I know some guys who work with Vaadin core each and every day :slight_smile:

Soon after a three hour fishing trip a managed to set my clear my head and the prototype to such a shape that all the UIDL communication is happening via WebSockets. Buy buy XHR! I prepared
a package to directory
for early adopters. I suggest you download it, try it and report you finding on this thread. Contributions are more than welcome. E.g. flash fallback for IE would be awesome.

Note, that the code is not even close ready for production. The code has born today and I can tell you that I have been doing more experimenting than real coding and testing. The solution is only tested on mac and webkit, but I guess it works on FF4 and latest Chrome too. Still there are some know bugs too and lots of TODO’s in the code. E.g. it only works with a one window per application and I haven’t thought at all how windows “forgotten open” should be handled. The easiest way to test this is to download the jetty distribution and launch the jetty starter (plain java app: org.vaadin.dontpush.server.DontPushServer) included in the add-on jar file. There is a very simple test app in the jar file too. Or just grab the sources via SVN.

For plain GWT user the add-on jar contains helper classes for WebSockets. The module name for all you “heretics” is: org.vaadin.dontpush.vwebsocket.VWebSocket

cheers,
matti

Hi,

A flash fallback library that could be used to widen the support for IE:

http://github.com/gimite/web-socket-js/

cheers,
matti

This is really promising. We’ve held off a bit on polling and push, but WebSockets seems like it will be nice should it get native support on the major browsers in a reasonable amount of time.

Will WebSockets allow you to know if a user has not done anything in a fixed amount of time to allow for normal session expiration? Seems like full duplex will do it since the server can send data updates as it has them, but it won’t receive anything back from the browser unless an action is requested, showing the user is “alive.”

For applications that require secure login, it’s important to know that a user has left without logging off so it can be forced to prevent unauthorized used. Session timeout is all way we have today, but will WebSockets allow this to be detected faster because the browser will close its’ connection when it’s done, like if the user closes the browser or the window/tab your web app is running in? The WebSockets themselves must have some sort of timeout feature, too, to handle the case where the user has simply left – I guess the server session ending could just close the socket and the browser should know right away. It would seem a waste to be sending updates to a browser where the user is no longer even there, and it’s worse if the browser is sending requests to the server on its own and the user is no longer involved.

Look forward to this maturing along with the browser support…

I have an application that is basically 24 users collectively running a live, real-time, mission-critical event. Its all push – they all play with the very same data. I just removed all support for polling by using ICEpush. I’m really eager to change my app.push() calls into no-ops !

One question : I presume that background-induced changes still need a synchronized(app){} wrapper ?

Another (but commercial) one would be
Kaazing
. It implements WebSocket API in most browsers and is heavily tested. It would be great to be able to enable plugging in any kinds of (WebSockets emulation) implementations.

Hi,

I haven’t really looked into session expiration etc yet. I just tried to make the basic concept work. WebSocket’s have their own timeout too, but I don’t really know (haven’t read the spec that well) how websockets usage relates to standard servlet session handling. E.g. does it touch the session timeout on each message or not?

In the prototype I hacked yesterday, the client side just reopens the socket once closed by the timeout (which is quite small by default in the jetty). But it is clearly not the optimal solution for most applications as the session will never die if browser window is left open.

cheers,
matti

Hi,

I couldn’t resist working a bit more on this. The VWebSocket GWT module now supports virtually all browsers via web-socket-js. Fallbacks are disabled and everything should work on IE’s too. I have tested it only with Win7 + IE8. The downside is that one must run the server as root as the flash socket server port is in the privileged area.

BTW. GWT experts! Does anyone know how one could restrict JS file for specific permutations only? Now the fallback scripts are loaded for webkit based browsers too. It really sucks to make good browsers suffer from MS’s lack of interest to web as application platform.

cheers,
matti

Hi,

I thought I already responded to you, but I guess the answer went straight to bit heaven the the liferay forum. But the answer is yes. It is annoying, but I don’t really know a better solution. Otherwise we should make pretty much all methods in various components synchronized.

cheers,
matti

Sounds good!
Will it work with Portlet 2.0?

Hi,

I can’t promise without checking, but if you are running your portal on Jetty it might be possible with some tweaks. But with just a pure portlet war file - I don’t think so. For portlet 1.0 style support this solution might be easier to integrate (as UIDL request are not going through the portal at all).

cheers,
matti

And how shall this work ?

I am using “public class VaadinServlet extends DontPushServlet” in the Jetty and wrote some code using

table = new com.vaadin.ui.Table

table.addItem(…)

I would expect that the table is now automatically updated, but its not.

So how does it work ? Are there any step-by-step examples ?

Cheers, Rob.

Hi,

I’m sorry I haven’t set up step by step instructions. With maven this might actually be just a few commands, but haven’t tried it.

Have you followed these overall instructions:

  • grab the latest Jetty 7.2
  • use the org.vaadin.dontpush.DontPushServlet instead of default Vaadin servlet
  • rebuild the widgetset with this add-on jar

Otherwise it should work just like Vaadin in general. One thing that was missing from the directory instructions is that you need to use 6.5 nightly build to make things work.

cheers,
matti

Being using Dojo + CometD on Grails i am looking forward to use Vaadin in the next project.
The only show-stopper is the absence of server-side push.
IMHO WebSockets is just a right way to go. Keep up the great work. It is highly appreciated,

Hi,

I have tried to follow the instructions but I am not really sure what you exactly mean with “grab the latest Jetty 7.2”. I have exported my whole Vaadin application as *.war and have deployed it to a Jetty 7.2 stand-alone server. But then I always get the following Exception:

Exception in thread “Thread-29” java.lang.NullPointerException
at org.vaadin.dontpush.SocketCommunicationManager$1.run(SocketCommunicationManager.java:82)

Thanks in advance

Tobias

Hi :).

Does DontPush work only on Jetty web server?

I am trying to run this add-on on Glassfish and I’m getting:

type Exception report

message

descriptionThe server encountered an internal error () that prevented it from fulfilling this request.

exception

javax.servlet.ServletException: PWC1392: Error instantiating servlet class org.vaadin.dontpush.DontPushServlet
root cause

java.lang.NoClassDefFoundError: org/eclipse/jetty/websocket/WebSocket
root cause

java.lang.ClassNotFoundException: org.eclipse.jetty.websocket.WebSocket

On the console I can see:

WARNING: StandardWrapperValve[eDziennik]
: PWC1406: Servlet.service() for servlet eDziennik threw exception
java.lang.NullPointerException
        at org.eclipse.jetty.websocket.WebSocketFactory.upgrade(WebSocketFactory.java:106)
        at org.vaadin.dontpush.DontPushServlet.service(DontPushServlet.java:88)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:847)
        at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1523)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:279)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:188)
        at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:641)
        at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:97)
        at com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:85)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:185)
        at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:325)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:226)
        at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:165)
        at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:791)
        at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:693)
        at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:954)
        at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:170)
        at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:135)
        at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:102)
        at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:88)
        at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:76)
        at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:53)
        at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:57)
        at com.sun.grizzly.ContextTask.run(ContextTask.java:69)
        at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:330)
        at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:309)
        at java.lang.Thread.run(Thread.java:662)

In my maven’s pom.xml I have:

<dependency>
    <groupId>org.eclipse.jetty</groupId>
    <artifactId>jetty-websocket</artifactId>
    <version>7.3.1.v20110307</version>
</dependency>

<dependency>
    <groupId>org.vaadin.addons</groupId>
    <artifactId>dontpush</artifactId>
    <version>0.2.0</version>
</dependency>

My web.xml:

<servlet-class>org.vaadin.dontpush.DontPushServlet</servlet-class>

I also did widgetset recompilation ().

Please help, I would love to use Vaadin on websockets !! :slight_smile: :slight_smile: [Now I have to use Refresher.]

Hi,

Currently, yes. I think recent Glassfish and Tomcat also have some sort of websocket support, but I haven’t found time to follow this area lately. If there is not yet a cross server solution for WebSocket, we’d need versions of the DontPushServlet for Glassfish and Tomcat too. The client side GWT stuff should stay intact.

If you ready to take the challenge to implement one, don’t hesitate to ask for help.

cheers,
matti

Oh, I’m affraid that I am not so good developer to do that. I don’t know even where to start and what to do :(.

What I understand websockets will be the best solution (compating to Refresher and ICE-push)…

Can you give us a few tips what one can do to implement DontPushServlet for other than Jetty severs (Glassfish, Tomcat, …)??

Thanks:),
Arthur.

Hi,

I’d do it as follows:

  • check out the raw websocket examples by server developers
  • Look at the DontPushServlet (the current jetty specific one) and see what kind of changes were done there.
  • merge two first parts into DontPushGlassfishServlet


Bobby
is an enthusiastic Vaadin user who works with the Glassfish server. He might be interested or at least skilled enough to help you. Serve the bait right for him and he might do your job -_-

Maybe I should create a google code project for this?

cheers,
matti

That would be great… please do.

Also, instead of a Jetty-specific server-side, consider supporting something more general like
jWebSocket
.

Hi,

I’m sorry I haven’t been active on this area lately. It has been busy times baking out the Vaadin 6.6 release and other related releases.

Today I finally got this forward. I used testing maven archetypes as an excuse to make this happen. And in fact I really fixed some archetype problems. Now the dontpush project is built with maven, bit cleaned up and hosted on google code. Also jetty support now is done against 7.4 series.


http://code.google.com/p/dontpush/

I didn’t do anything towards Glassfish support, but did some refactorings which should help the task. Using Athmosphere project as a wrapper would be one thing that somebody could investigate.

Please, start bothering me with your patches!

cheers,
matti