#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. Вы указали мне правильный путь. Спасибо.