Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java EE7 websocket initialization - implement logic before first @OnOpen

I think this is more a design specific question, than direct coding issue.

I want to implement a websocket service which serves an updated dataset from a foreign http:// resource to the clients. but i want to have the data available before the first client connects, so @OnLoad notation won't do.

In HttpServlet world I would

@Override public void init() throws...

I could not figure out a suitable way for doing so just using JSR-356. I tried with custom ServerEndpointConfig.Configurator but that does not seem to give me access to method similar to init() from HttpServlet.

So my question is:

Letting the websocket Endpoint class extend HttpServlet gives me access to the init() method and I can place my initial logic there. Is that a suitable way for solving my problem, or have i missed something in JSR-356 which does the job elegantly and without importing mostly unused servlet packages?

Thank you very much!

like image 864
raptaML Avatar asked Oct 20 '22 09:10

raptaML


1 Answers

A class annotated with @ServerEndpoint("/myEndPoint") is instantiated each time a new connection is created via @OnOpen. It is not a static class nor a singleton (e.g. not behaves as Spring @Service).

I have a similar problem to yours, I need to make a web socket the observer of a Spring web service (don't ask, I'm with you that is a bad architecture the problem). In order to make it an observer, I have to add it to the observable class, but because of the lack of an initialization for the web socket I don't have a clear spot where to add the observer, adding it in the @OnOpen method would repeatedly add it on each new connection.

The only solution I found is a workaround. Usually a web socket class has a static Set of the peers connected to it, you need something similar for your initialization. Either use a static block or a static flag in the constructor. In my case I solved with:

private static boolean observerFlag = false;
private static Set<Session> peers = Collections.synchronizedSet(new HashSet<Session>());

public MyWebSocket() {
    if (!observerFlag) {
        observable.addObserver(this);
        observerFlag = true;
    }
}

And to remove the observer:

@OnClose
public void onClose(Session peer) {
    peers.remove(peer);
    if (peers.isEmpty()) {
        observable.deleteObserver(this);
        observerFlag = false;
    }
}

I repeat that this is a workaround, I think that there is a more elegant solution.

like image 119
Narmer Avatar answered Oct 23 '22 09:10

Narmer