websocketjettyjava-websocketjetty-11

Jetty 11: Set idle timeout for WebSockets programmatically and via configuration file


I have found a way to set the idle timeout for Jetty 11 WebSocket connections programmatically by invoking factory.setIdleTimeout in an implementation of the JettyWebSocketServlet.configure(JettyWebSocketServletFactory factory) method. I wonder…

<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
<Configure id="Server" class="org.eclipse.jetty.server.Server">
  <Call name="addConnector">
    <Arg>
      <New class="org.eclipse.jetty.server.ServerConnector">
        <Arg name="server"><Ref refid="Server"/></Arg>
        <Set name="idleTimeout">90000</Set>
      </New>
    </Arg>
  </Call>
</Configure>

Solution

  • There is no configuration file for idle timeout on websocket.

    On Jetty 12 ...

    If using the jakarta.websocket APIs then the default idle timeout comes from the jakarta.websocket.Session.getMaxIdleTimeout() that comes from the container.

    For ee10 environment on Jetty 12 the org.eclipse.jetty.ee10.websocket.jakarta.common.JakartaWebSocketSession handles the container for jakarta.websocket.Session on ee10.

    The ee10 environment delegates to the jetty-core (with no servlet features) org.eclipse.jetty.websocket.core.CoreSession class which tracks a default idle timeout of 30 seconds.

    The jetty-core org.eclipse.jetty.websocket.core.Configuration has the ability to get/set the idle timeout with the APIs.

    But those are not set by configuration files, inis, or xmls.
    Those are accessible in an embedded scenario though.

    If you use the Jetty WebSocket API, then the org.eclipse.jetty.websocket.api.Configurable is where you would set container specific idle timeout. But accessing that is a bit tricky from a servlet webapp, no big deal if you are embedded though.

    import import org.eclipse.jetty.ee10.websocket.server.config.JettyWebSocketServletContainerInitializer;
    
    ServletContextHandler contextHandler = new ServletContextHandler();
    JettyWebSocketServletContainerInitializer
        .configure(contextHandler, (servletContext, wsContainer) ->
        {
            wsContainer.setIdleTimeout(Duration.ofSeconds(30));
            wsContainer.addMapping("/echo", EchoEndpoint.class);
        });
    

    The object returned on wsContainer parameter is of type org.eclipse.jetty.ee10.websocket.server.JettyWebSocketServerContainer which implements org.eclipse.jetty.websocket.api.Configurable.

    From an ee10 Servlet based webapp (based on either org.eclipse.jetty.ee10.webapp.WebAppContext or org.eclipse.jetty.ee10.servlet.ServletContextHandler), you have 2 options for configuring idle timeout from the point of view of the ServletContext itself.

    First you can manually add the filter org.eclipse.jetty.ee10.websocket.servlet.WebSocketUpgradeFilter and then use the idleTimeout init-parameter.

    That would define the default idle-timeout for all endpoints mapped against the WebSocketUpgradeFilter.

    This is how it works in embedded mode. Use the same init-param in WEB-INF/web.xml

    import org.eclipse.jetty.ee10.websocket.servlet.WebSocketUpgradeFilter;
    
    FilterHolder filterHolder = new FilterHolder(WebSocketUpgradeFilter.class);
    filterHolder.setName(WebSocketUpgradeFilter.class.getName());
    filterHolder.setInitParameter("idleTimeout", idleTimeoutFilter1);
    contextHandler.addFilter(filterHolder, "/*", EnumSet.of(DispatcherType.REQUEST));
    

    Second you can manually add the org.eclipse.jetty.ee10.websocket.server.JettyWebSocketServlet servlet you have, and use the idleTimeout init-parameter.

    That would define the default idle-timeout for only that servlet, no matter how many <url-pattern> entries it was mapped to.

    This is how it works in embedded mode. Use the same init-param in WEB-INF/web.xml

    import org.eclipse.jetty.ee10.websocket.server.JettyWebSocketServlet;
    
    public static class EchoServlet extends JettyWebSocketServlet { 
        /* ... implementation here ... */
    }
    
    ServletHolder wsHolder = new ServletHolder("wsecho", EchoServlet.class);
    wsHolder.setInitParameter("idleTimeout", "30");
    contextHandler.addServlet(wsHolder, "/echo");