Undertow Websocket Bean Injection CDI Issue

781 views Asked by At

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}

2

There are 2 answers

3
Patrick Suter On BEST ANSWER

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();
    }
}
1
John Ament On

Undertow is only a servlet container. Weld (or OWB) provide CDI support. I'm not sure how you're instantiating Undertow, but you need to leverage Weld (or some other CDI implementation).

Here's one example how to do it. Leverage a CDI Extension to find the endpoints, and once you have them you can register them in Undertow

Feel free to leverage Hammock for this.