This is a short guide on how to use an embedded Undertow webserver coupled with Guice for IoC, to expose a WebSocket endpoint. You can check out a sample project’s source code on github.

A custom ClassIntrospector is used to construct a ServerEndpoint instance that expects a dependency to be injected through it’s @Inject annotated constructor.

A Basic WebSocket Deployment

Exposing a WebSocket endpoint with JSR 356 became as easy as:

class WebSocketEndpoint {
  public void connect(Session session) throws IOException { /*...*/ }

  public void message(String message, Session session) { /*...*/ }

  public void close(CloseReason closeReason, Session session) { /*...*/ }

The following class exposes the endpoint using an embedded Undertow server.

public class WebSocketService {
  public static void main(String [] args) {
    final WebSocketDeploymentInfo webSocketDeploymentInfo = new WebSocketDeploymentInfo()

    DeploymentInfo websocketDeployment = deployment()
        .addServletContextAttribute(WebSocketDeploymentInfo.ATTRIBUTE_NAME, webSocketDeploymentInfo)

    DeploymentManager manager = Servlets.defaultContainer()


    try {
      Undertow server = Undertow.builder()
          .addHttpListener(8080, "localhost")
          .setHandler(path().addPrefixPath("/ws", manager.start()))

    } catch (ServletException e) {

Injecting Dependencies

The WebSocketEndpoint class requires a SessionHolder instance that keeps track of all connected users. The SessionHolder’s construction and injection should be handled by Guice.

class WebSocketEndpoint {

  private final SessionHolder sessionHolder;

  public WebSocketEndpoint(SessionHolder sessionHolder) {
    this.sessionHolder = sessionHolder;
  /* ... */

Since a class marked with the ServerEndpoint annotation is expected to have a 0-ary constructor, the WebSocket deployment will fail at runtime throwing a javax.websocket.DeploymentException. A custom ClassIntrospector can be used to provide an Instance Factory which is aware of Guice and can properly handle object construction.

// This is a nested class inside the WebSocketService
// It has access to the `injector` field of it's parent class.
private class GuiceClassIntrospector implements ClassIntrospecter {
    public <T> InstanceFactory<T> createInstanceFactory(Class<T> clazz) throws NoSuchMethodException {
      return new ImmediateInstanceFactory<>(injector.getInstance(clazz));

The GuiceClassIntrospector has to be registered with a DeploymentInfo instance before deployment.

  websocketDeployment = websocketDeployment.setClassIntrospecter(
    new GuiceClassIntrospector());

After registration of the custom ClassIntrospector, all registered endpoint classes will be instantiated through a Guice Injector.