Server push on Jetty 9.2

Hi everybody,

I’m trying to implement server push using Vaadin 7.2.4 on my embedded Jetty server (9.2.1.v20140609). However, I keep getting exceptions during startup. These are the steps I have already executed:

  1. Instructed Maven to load the Vaadin server push stuff:




    com.vaadin
    vaadin-push
    ${vaadin.version}



  2. Applied a server push annotation to my Vaadin UI:


    @Push(PushMode.AUTOMATIC)
    public class MyUI extends UI

  3. Enabled server push on my embedded Jetty server:


    ServletHolder servletHolder = new ServletHolder(servlet);
    servletHolder.setInitParameter(“pushmode”, “automatic”);
    servletHolder.setAsyncSupported(true);
    webAppContext.addServlet(servletHolder, “/*”);

  4. In Jetty 9.1 the WebSocketPolicy.setMaxMessageSize method has been removed, which is called by Atmosphere. To avoid the NoSuchMethodException I also added following temporary workaround (see
    ticket
    ):


    servletHolder.setInitParameter(“org.atmosphere.cpr.asyncSupport”, “org.atmosphere.container.JSR356AsyncSupport”);

  5. In the previous step we told Atmosphere to use Jetty’s to use it’s JSR356 standard Java websocket API, instead of it’s native websocket API (see
    blog
    ). Therefore I added following
    dependencies
    for Maven:



    org.eclipse.jetty.websocket
    javax-websocket-server-impl
    ${jetty.version}


    javax.websocket
    javax.websocket-api
    1.0


  6. At this point I get following exception
    com.vaadin.server.ServiceException: Atmosphere init failed



    at com.vaadin.server.communication.PushRequestHandler.(PushRequestHandler.java:
    at com.vaadin.server.VaadinServletService.createRequestHandlers(VaadinServletService.
    at com.vaadin.server.VaadinService.init(VaadinService.java:180)
    at com.vaadin.server.VaadinServlet.createServletService(VaadinServlet.java:190)
    at com.vaadin.server.VaadinServlet.[u]
    [color=#0000FF]

    init

    /color
    at org.eclipse.jetty.servlet.ServletHolder.initServlet(ServletHolder.java:595)
    at org.eclipse.jetty.servlet.ServletHolder.initialize(ServletHolder.java:385)
    at org.eclipse.jetty.servlet.ServletHandler.initialize(ServletHandler.java:862)
    at org.eclipse.jetty.servlet.ServletContextHandler.startContext(ServletContextHandler
    at org.eclipse.jetty.webapp.WebAppContext.startWebapp(WebAppContext.java:1341)
    at org.eclipse.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1334)
    at org.eclipse.jetty.server.handler.ContextHandler.doStart(ContextHandler.java:744)
    at org.eclipse.jetty.webapp.WebAppContext.doStart(WebAppContext.java:497)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68
    at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:
    at org.eclipse.jetty.server.Server.start(Server.java:357)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.jav
    at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:60)
    at org.eclipse.jetty.server.Server.doStart(Server.java:324)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68when starting up my embedded Jetty:





    Caused by: java.lang.IllegalStateException:

    ServerContainer is null


    at org.atmosphere.container.JSR356AsyncSupport.(JSR356AsyncSupport.java:43)

The only information I can find about this exception, is a similar
problem
with Tomcat: "
The attribute is always null when calling ServletContext during the Servlet.init() operation"
. It looks like this is the case in my call stack above. Does anybody know what I’m doing wrong, or how I could workaround this problem?

Thanks a lot!!
Bart Butenaers

Hi Bart,

It seems that according to the spec, the implementation should set the ServerContainer attribute when initializing the servlet context, so it
should
be available at servlet init time. It seems Jetty does so
here
, but I can’t readily tell why it’s nevertheless not found by Atmosphere. Should probably debug by putting a breakpoint in the Jetty code to see when it’s executed if at all.

Hello Johannes,

Thanks for your very usefull reply! Indeed, it seems that the WebSocketServerContainerInitializer is never configured. From another
blog
it became obvious that I had to configure it explicitly (i.e. creating a websocket container) before starting the embedded Jetty server:



ServletHolder servletHolder = …;
ServletContextHandler context = new ServletContextHandler();
context.setContextPath( “/” );
context.addServlet( servletHolder, “/*” );
server.setHandler( context );


ServerContainer container =



WebSocketServerContainerInitializer.configureContext( context );


server.start();
server.join();

Now the exception is gone and I get following in my log: "
Atmosphere Framework 2.1.2.vaadin2 started
".

However, the startup method of that initializer class is never called. In the same blog they mention "
Because we haven’t added any endpoints yet, the container basically sits here and does nothing
". Do you have any idea which endpoint I have to add to the container for Vaadin, to get the server push up and running?

Thanks again!
Bart Butenaers

In case anybody would be using the same steps as I described above: the server push seems to be working correctly this way, even

without

specifying an endpoint! The PushRequestHandler sends all the requests to the PushHandler. So the problem described above is solved for me …