Andrew
Andrew

Reputation: 716

How to pass a web socket handler instance instead of class

I'm working with embedded Jetty websockets and what I see in the examples is passing the Class of the handler to the container instead of an instance. I would to know if it's possible to pass an instance instead of a class and how that works.

ServerContainer wscontainer = webSocketServerContainerInitializer.configureContext(context);

// Add WebSocket endpoint to javax.websocket layer
wscontainer.addEndpoint(EventSocket.class);

I would like to be able to do

wscontainer.addEndpoint(new EventSocket());

of course this method is not supported.

I see that on the client side you can provide an instance of a handler

Session session = container.connectToServer(new ClientSocket(), uri);

I'm curious why the api was designed to accept a class instead of an instance, which is unlike how servlets work.

Update:

The following solution works:

        // contains ServerEndpoint annotation and onMessage, onOpen etc
        final EventSocket eventSocket = new EventSocket();

        ServerEndpointConfig config = ServerEndpointConfig.Builder.create(eventSocket.getClass(), eventSocket.getClass().getAnnotation(ServerEndpoint.class).value())
                        .configurator(new Configurator() {
                            @Override
                            public <T> T getEndpointInstance(Class<T> endpointClass) throws InstantiationException {
                                return (T) eventSocket;
                            }                                 
                        })
                        .build();
        wscontainer.addEndpoint(config);

Upvotes: 1

Views: 1254

Answers (1)

Joakim Erdfelt
Joakim Erdfelt

Reputation: 49515

In servlets, you have 1 instance for all requests to the same servlet.

In a websocket server, you have long lived connections, and the normal technique is to have a new websocket endpoint instance per connection. In websocket clients, you don't have to worry about this. You are just 1 instance to start with. If you want multiple connections, you have multiple instances of that websocket endpoint that you created yourself.

ServerContainer is a javax.websocket.server.ServerContainer (aka JSR-356).

It has 2 addEndpoint() mechanisms:

  • addEndpoint(Class<?> endpointClass) assumes that the class either extends from Endpoint or is annotated with @ServerEndpoint (yes, you can have server that doesn't initialize via annotation scanning, but still uses annotations and this addEndpoint mechanism to programatically add endpoints). It assumes that the server will instantiate a new Endpoint on each incoming websocket upgrade request.

  • addEndpoint(ServerEndpointConfig serverConfig) takes a ServerEndpointConfig that declares how you want your endpoint to bound. It too assumes that the server will instantiate a new Endpoint on each incoming websocket upgrade request. However, there is way out using this technique. Define your own Configurator object that overrides the getEndpointInstance(Class<?> endpointClass) method, returning the same object over and over again. Just note that the instance you return must be of the class type that was passed into that method (otherwise its an error).

If you choose to use the jetty native websocket implementation, then you can also use the WebSocketCreator to handle the creation of websocket instances, even singletons.

Upvotes: 2

Related Questions