Search code examples
javawebsocketjettyjsr356

JSR-356 websocket - cannot get return code after stopping container


I have built a client server application using javax websockets.Though JSR 356 doesn't have methods to stop websocket container, i managed to stop the container after casting to jetty Lifecyle.Once stopping the container i have wrote

system.exit(1);

But the return is code always zero from the client program.

code: @ClientEndpoint

    public boolean close()
        {
            try
              {
                  if(this.container != null && this.container instanceof LifeCycle) { 
                      logger.trace("stoping container...");
                      ((LifeCycle) this.container).stop();
                  }

                  this.session.close();
        
                return true;
            }
            catch (Exception e)
            {
                logger.trace("Exception occured while closing the connection",e);
                return false;
            }
        }

code : Invoking close method from another class

public closeConnection(){

     this.wc.close();
     System.exit(1);

}

Any help is appreciated :-)


Solution

  • Are you attempting to call closeConnection or close from a thread that belongs to the container or the container's ThreadPool / Executor?

    Also, once the container is stopped, all of the sessions will be stopped too.

    Change @ClientEndpoint close() to be ...

    public void close()
    {
        try
        {
            this.session.close();
        }
        catch (Exception e)
        {
            logger.trace("Exception occured while closing the connection",e);
        }
    }
    

    And make closeConnection() simply ...

    public closeConnection()
    {
        LifeCycle.stop(this.wc.getContainer());
        System.exit(1);
    }
    

    A working example of this can be found at
    https://github.com/joakime/javaxwebsocket-client-returncode

    Which has the code ...

    App.java

    package org.eclipse.jetty.demo;
    
    import java.io.IOException;
    import java.net.URI;
    import java.net.URISyntaxException;
    import javax.websocket.ClientEndpointConfig;
    import javax.websocket.ContainerProvider;
    import javax.websocket.DeploymentException;
    import javax.websocket.WebSocketContainer;
    
    import org.eclipse.jetty.util.component.LifeCycle;
    
    public class App
    {
        private static final App MAIN_INSTANCE = new App();
    
        private WebSocketContainer client;
    
        public static void main(String[] args) throws IOException, DeploymentException, URISyntaxException
        {
            App.MAIN_INSTANCE.connect();
        }
    
        public static void stop(int returnCode)
        {
            // Trigger stop from thread that does not belong to Container.
            new Thread(() ->
            {
                LifeCycle.stop(App.MAIN_INSTANCE.client);
                System.exit(returnCode);
            }).start();
        }
    
        private WebSocketContainer getClientContainer()
        {
            if (client == null)
                client = ContainerProvider.getWebSocketContainer();
            return client;
        }
    
        public void connect() throws IOException, DeploymentException, URISyntaxException
        {
            URI echoUri = URI.create("wss://echo.websocket.org");
    
            ClientEndpointConfig clientEndpointConfig = ClientEndpointConfig.Builder.create()
                .configurator(new OriginServerConfigurator(echoUri))
                .build();
    
            EchoEndpoint echoEndpoint = new EchoEndpoint();
            getClientContainer().connectToServer(echoEndpoint, clientEndpointConfig, echoUri);
            System.out.printf("Connected to : %s%n", echoUri);
        }
    }
    

    EchoEndpoint.java

    package org.eclipse.jetty.demo;
    
    import javax.websocket.CloseReason;
    import javax.websocket.Endpoint;
    import javax.websocket.EndpointConfig;
    import javax.websocket.MessageHandler;
    import javax.websocket.Session;
    
    /**
     * Basic Echo Client Endpoint
     */
    public class EchoEndpoint extends Endpoint implements MessageHandler.Whole<String>
    {
        private Session session;
    
        @Override
        public void onClose(Session session, CloseReason closeReason)
        {
            System.out.printf("Connection closed: Session.id=%s - %s%n", session.getId(), closeReason);
            this.session = null;
        }
    
        @Override
        public void onOpen(Session session, EndpointConfig config)
        {
            System.out.printf("Got open: Session.id=%s%n", session.getId());
            this.session = session;
            this.session.addMessageHandler(this);
            try
            {
                session.getBasicRemote().sendText("Hello");
                session.getBasicRemote().sendText("How are things?");
                session.getBasicRemote().sendText("Thanks for the conversation.");
            }
            catch (Throwable t)
            {
                t.printStackTrace();
            }
        }
    
        @Override
        public void onMessage(String msg)
        {
            System.out.printf("Got msg: \"%s\"%n", msg);
            if (msg.contains("Thanks"))
            {
                App.stop(1);
            }
        }
    
        @Override
        public void onError(Session session, Throwable cause)
        {
            cause.printStackTrace();
        }
    }