Search code examples
javadependency-injectioncdiundertowjsr356

Undertow Websocket Bean Injection CDI Issue


I don't understand why CDI use of injection doesn't work with websockets, using undertow.

Below is the code I have for a simple websocket endpoint.

@ServerEndpoint("/")
public class TestWebSocketEndpoint {

    @Inject
    private RetrieveAccessor retrieveAccessor;

    private final Logger logger = Logger.getLogger(this.getClass().getName());

    @OnOpen
    public void onConnectionOpen(Session session) {
        logger.info("Connection opened ... " + session.getId());
    }

    @OnMessage
    public String onMessage(String message) {

        if (!message.isEmpty()) {
            return message;
        }

        System.out.println("RETRIEVE BEAN -> " + retrieveAccessor);
        if (retrieveAccessor != null) {
            return "BEAN NOT NULL";
        }
        return ":(";
    }

    @OnClose
    public void onConnectionClose(Session session) {
        logger.info("Connection close .... " + session.getId());
    }

}

Of course the issue is that the injected property is null. I have no problems of course using the rest side of things for this deployment and injection of the stateless bean described below. Is there a work around for this, what are the problems I could run into if I just init properties I need that are beans? Because that definitely works.

RetrieveAccessor retrieveAccessor = new.... {code}


Solution

  • An easy way to get injection working on your @ServerEndpoint annotated classes is to set a custom configurator that handles the creation of your endpoint instance by overriding the getEndpointInstance(Class endpointClass) method to instantiate with CDI.

    https://tyrus.java.net/documentation/1.13/user-guide.html#d0e464

    Annotated endpoint:

    @ServerEndpoint(value = "/", configurator = CDIEndpointConfigurator.class)
    public class TestWebSocketEndpoint {
       ...
    }
    

    Custom configurator:

    public class CDIEndpointConfigurator extends ServerEndpointConfig.Configurator {
    
        @Override
        public <T> T getEndpointInstance(Class<T> endpointClass) throws InstantiationException {
            return CDI.current().select(endpointClass).get();
        }
    }