AtmosphereResource становится нулевым

#java #gwt #atmosphere

#java #gwt #атмосфера

Вопрос:

Я пытаюсь разработать небольшое расширение gwt для приложения gwt для чата Atmosphere. Серверная часть приложения заботится о том, чтобы входящий AtmosphereResource связывал вещателя и приостанавливал его. Вот фрагмент кода о приостановке нового входящего AtmosphereResource:

 private void doGet(AtmosphereResource ar, String userId) {
    if(BroadcasterFactory.getDefault().lookup(userId) != null) {
    ar.setBroadcaster(BroadcasterFactory.getDefault().lookup(userId).addAtmosphereResource(ar));
    } else {
            ar.setBroadcaster(BroadcasterFactory.getDefault().get(userId).addAtmosphereResource(ar));
    }
    ar.suspend();
    ...
}
  

Когда я ищу этот AtmosphereResource, используя его ранее сохраненный uuid, я всегда находил его нулевым:

 ...
AtmosphereResource arTarget = AtmosphereResourceFactory.getDefault().find(uuid);            
if (arTarget != null)   {
    arTarget.getBroadcaster().broadcast(msg,arTarget);
} else {
    log.info("handleRawMessage:no broadcaster " ((RawMessage) msg).toString());
}
...
  

Что не так? Я также замечаю, что AtmosphereResources быстро загружаются, так как у них сразу истекает время ожидания, но тайм-аут установлен на -1. Я что-то пропустил? Это фрагмент моего пом.

 <dependency>
    <groupId>org.atmosphere.extensions</groupId>
    <artifactId>atmosphere-gwt20-client</artifactId>
    <version>2.1.1</version>
</dependency>
<dependency>
    <groupId>org.atmosphere.extensions</groupId>
    <artifactId>atmosphere-gwt20-common</artifactId>
    <version>2.1.1</version>
</dependency>
<dependency>
    <groupId>org.atmosphere.extensions</groupId>
    <artifactId>atmosphere-gwt20-server</artifactId>
    <version>2.1.1</version>
</dependency>
<dependency>
    <groupId>org.atmosphere</groupId>
    <artifactId>atmosphere-runtime</artifactId>
    <version>2.1.1</version>
</dependency>
  

Ответ №1:

Чтобы получить вещателя, у вас должен быть клиент, подключенный к серверу. Вы уверены, что ваш клиент подключается?

ВЕРСИЯ 2.0

Для реализации сервера в версии 2.0 я сделал: (Идентификатор клиента может быть получен из запроса)

 public class AtmosphereHandler extends AbstractReflectorAtmosphereHandler {

private static Logger logger = Logger.getLogger(AtmosphereHandler.class);;

@Override
public void onRequest(final AtmosphereResource ar) throws IOException {
    logger.info("Connecting to comet with: "
              ar.getRequest().getRequestURI());
    Broadcaster broadcaster = BroadcasterFactory.getDefault().lookup(
            YOUR_CLIENT_ID, true);
    if (broadcaster.getAtmosphereResources().size() > 0) {
        logger.debug("Broadcaster recovered with name: "
                  broadcaster.getID());
    } else {
        logger.debug("Broadcaster created with name: "
                  broadcaster.getID());
    }
    ar.setBroadcaster(broadcaster);

    ar.setSerializer(new Serializer() {
        Charset charset = Charset.forName(ar.getResponse()
                .getCharacterEncoding());

        @Override
        public void write(OutputStream os, Object o) throws IOException {
            try {
                logger.info("Writing object to JSON outputstream with charset: "
                          charset.displayName());
                String payload = serializer.serialize(o);
                os.write(payload.getBytes(charset));
                os.flush();
            } catch (SerializationException ex) {
                throw new IOException("Failed to serialize object to JSON",
                        ex);
            }
        }
    });

    ar.suspend();

}

private ServerSerializer serializer = new JacksonSerializerProvider()
        .getServerSerializer();
  

В клиентской части у вас должно быть что-то похожее на это:

      AutoBeanClientSerializer json_serializer = new AutoBeanClientSerializer();
    json_serializer.registerBeanFactory(beanFactory, ActivityMessage.class);
    AtmosphereRequestConfig jsonRequestConfig = AtmosphereRequestConfig.create(json_serializer);
    jsonRequestConfig.setUrl(GWT.getHostPageBaseURL()   HANDLER_URL_PART);
    jsonRequestConfig.setContentType("application/json; charset=UTF-8");
    jsonRequestConfig.setTransport(AtmosphereRequestConfig.Transport.WEBSOCKET);
    jsonRequestConfig.setFallbackTransport(AtmosphereRequestConfig.Transport.STREAMING);
    jsonRequestConfig.setOpenHandler(new AtmosphereOpenHandler() {
        @Override
        public void onOpen(AtmosphereResponse response) {
            GWT.log("JSON Connection opened");
        }
    });
    jsonRequestConfig.setCloseHandler(new AtmosphereCloseHandler() {
        @Override
        public void onClose(AtmosphereResponse response) {
            GWT.log("JSON Connection closed");
        }
    });
    jsonRequestConfig.setMessageHandler(new AtmosphereMessageHandler() {
        @Override
        public void onMessage(AtmosphereResponse response) {

        }
    });


    Atmosphere atmosphere = Atmosphere.create();
    final AtmosphereRequest jsonRequest = atmosphere.subscribe(jsonRequestConfig);
  

ВЕРСИЯ 1.1.0RC4

Я расширяю AtmosphereGwtHandler для реализации сервера следующим образом:

 private static Logger logger;
@Override
public void init(ServletConfig servletConfig) throws ServletException {
    super.init(servletConfig);
    logger = Logger.getLogger(AtmosphereHandler.class);
}

@Override
public int doComet(GwtAtmosphereResource resource) throws ServletException, IOException {
    logger.info("Connecting to comet with: "  resource.getRequest().getRequestURI());
    Broadcaster broadcaster = BroadcasterFactory.getDefault().lookup(YOUR_CONNECTION_ID, true);
    if(broadcaster.getAtmosphereResources().size()>0){
        logger.debug("Broadcaster recovered with name: "   broadcaster.getID());
    }
    else{
        logger.debug("Broadcaster created with name: "   broadcaster.getID());
    }
    resource.getAtmosphereResource().setBroadcaster(broadcaster);
    return NO_TIMEOUT;
}

@Override
public void cometTerminated(GwtAtmosphereResource cometResponse, boolean serverInitiated) {
    logger.info("Disconnecting from comet. Broadcaster : "   cometResponse.getBroadcaster().getID());
    super.cometTerminated(cometResponse, serverInitiated);
}

@Override
public void doPost(HttpServletRequest postRequest, HttpServletResponse postResponse,
        List<?> messages, GwtAtmosphereResource cometResource) {
    broadcast(messages, cometResource);
}
  

Вы должны инициализировать его с помощью atmosphere.xml файл в папке META-INF в вашем целевом каталоге.

Я надеюсь, что это поможет!

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

1. Привет! Спасибо за ответ. Почему вы внедрили расширение AtmosphereGWTHandler для серверной части? Я реализую свою серверную часть, используя AbstractReflectorAtmosphereHandler. Вы указали это расширение в свой atmosphere.xml как обработчик атмосферы?

2. Да, я использовал старую версию, я понял после этого, почему я отредактировал свой ответ, чтобы указать версию atmosphere, которую я использовал. Теперь я пытаюсь с 2.0. Я скажу вам сейчас, работает ли это также 😉

3. Я тестировал с atmosphere 2.0, и я мог без проблем найти вещателя. Вы уверены, что у вас подключен клиент? Я опубликую свой код.

4. Если сериализатор выполнен неправильно, вы не получите вызов onMessage. Будьте осторожны с этим, потому что я сошел с ума, выяснив, почему он не получал сообщение!

5. Проблема была более тривиальной, чем кажется. Просто я забыл приостановить каждый входящий AtmosphereResource. Вы указали мне правильный путь. Спасибо.