JSR-356 websocket — не удается получить код возврата после остановки контейнера

#java #websocket #jetty #jsr356

#java #websocket #причал #jsr356

Вопрос:

Я создал клиент-серверное приложение, используя javax websockets.Хотя в JSR 356 нет методов для остановки контейнера websocket, мне удалось остановить контейнер после приведения к jetty Lifecyle.После остановки контейнера я написал

system.exit(1);

Но возвращаемый код всегда равен нулю из клиентской программы.

код: @ClientEndpoint

     public boolean close()
        {
            try
              {
                  if(this.container != null amp;amp; 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;
            }
        }
  

код: вызов метода close из другого класса

 public closeConnection(){

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

}
  

Приветствуется любая помощь 🙂

Ответ №1:

Вы пытаетесь вызвать closeConnection или close из потока, который принадлежит контейнеру или пулу потоков / исполнителю контейнера?

Кроме того, как только контейнер будет остановлен, все сеансы тоже будут остановлены.

Изменение @ClientEndpoint close() должно быть …

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

И сделайте closeConnection() просто…

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

Рабочий пример этого можно найти на
https://github.com/joakime/javaxwebsocket-client-returncode

В котором есть код…

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();
    }
}
  

Комментарии:

1. Спасибо @Joakim Erdfelt, но это не сработало. Поток не принадлежит потоку контейнера, я думаю, потому что, учитывая, что у меня есть моя реализация @ clientendpoint в классе A и из класса B (программа содержит основной метод), я создаю объект класса A и, в конечном итоге, я создаю контейнер в конструкторе класса A .

2. Это работает. поверьте мне. 🙂 Я обновил ответ и даже ссылался на пример проекта, который это делает.

3. Это было освещено @Joakim Erdfelt. Но здесь ` новый поток(() -> { LifeCycle.stop (App.MAIN_INSTANCE.client); System.exit(returnCode); }).start();` единственное отличие заключается в остановке контейнера в новом потоке. Какая-либо причина, стоящая за этим?

4. Причина в том, что, как указано в ответе, вы не можете остановить жизненный цикл из потока, который управляется этим жизненным циклом. Это просто гарантирует, что остановка контейнера произойдет в другом потоке. Поскольку в примере приложения показано, что оно останавливается во время получения onMessage, я знаю, что это всегда находится в потоке, управляемом жизненным циклом этого контейнера.

5. Большое спасибо!! @Joakim Erdfelt