2

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}

thekevshow
  • 774
  • 14
  • 36
  • The last part of your question is confusing. Are you instantiating your `RetrieveAccessor`? You also mention undertow.. are you using weld servlet? wildfly? – John Ament Oct 08 '16 at 11:46
  • I'm just using undertow, and the last part of my question just explains that a normal class initialization of that bean object works, what would be consequences of doing that. – thekevshow Oct 08 '16 at 17:52

2 Answers2

3

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();
    }
}
Patrick Suter
  • 275
  • 3
  • 12
  • I will try this later today or tomorrow and mark this correct if it works, I had seen this but hadn't really attempted it, I think you explained it well though. – thekevshow Nov 11 '16 at 15:55
  • Sorry for not getting around to this sooner, so I had tried something similar before but I must have did it wrong. This is the correct answer, thank you so much. – thekevshow Nov 16 '16 at 03:09
  • Nice solution! (+1) – cassiomolin Jun 16 '17 at 08:09
1

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.

John Ament
  • 11,595
  • 1
  • 36
  • 45
  • I am using undertow as a standalone web service/ mircro service. I originally didn't understand what you were asking, but yeah I was using Weld to provide my CDI support, this should be helpful, I been a little busy, if I am able to implement what you have shown me as solving my problem, I will mark this as the correct/accepted answer. Thank you. (PS: your framework is cool) – thekevshow Oct 14 '16 at 03:21