Cometd публикует входные данные Map вместо ожидания вывода с сервера
Я работаю над приложением Spring-MVC, которое использует Cometd для общения. Единственная проблема, с которой я сталкиваюсь, заключается в том, что когда я отправляю сообщение со стороны клиента, клиент добавляет это сообщение непосредственно к серверу говорит, вместо того, чтобы ждать, пока я вызову в бэкэнде механизм публикации, а затем добавляю этот материал. Я попробовал это на 2 разных компьютерах, связанных, тот же результат. Из-за этого я не могу получить доступ к переменным, которые я устанавливаю в бэкэнде.
Пожалуйста, дайте мне знать, что я могу сделать. Большое спасибо.
Журнал отладки:
DEBUG: org.cometd.server.BayeuxServerImpl.31913ea0 - < {data={name=check123}, channel=/chat/1360}
wassup
DEBUG: org.cometd.server.BayeuxServerImpl.411c4c13 - Added channel /chat/1360
DEBUG: org.cometd.server.BayeuxServerImpl.411c4c13 - < {data={accountid=1360, firstname=AKS, name=check123, channelname=/chat/1360, timestamp=2015-04-27 10:58:08.539}, channel=/chat/1360}
DEBUG: org.cometd.server.BayeuxServerImpl.31913ea0 - << {channel=/chat/1360, id=10, successful=true}
DEBUG: org.cometd.server.BayeuxServerImpl.31913ea0 - < {channel=/chat/1360, id=10, successful=true}
В приведенном выше журнале отладки первая строка приходит от клиента, а оператор 'wassup' печатается в начале моего метода @Listener. Затем я добавляю некоторые данные и публикую их, но не могу получить доступ к переменным, упомянутым в третьей строке. Есть идеи.
Вот код Java:
@Named
@Singleton
@Service("chat")
public class ChatServiceImpl{
@Inject
private BayeuxServer bayeux;
@Inject
private PersonService personService;
@Inject
private ChatMessagesService chatService;
@Inject
private ConversationService conversationService;
@Inject
private RepliesService repliesService;
@Session
private ServerSession serverSession;
@PostConstruct
public void init(){
System.out.println("Echo Service Initialized");
}
@PreDestroy
public void cleanUp() throws Exception {
System.out.println("Spring Container is destroyed");
}
@Listener(value = "/person/*")
public void privateChat(ServerSession remote, ServerMessage.Mutable message){
System.out.println("wassup");
Person sender = this.personService.getCurrentlyAuthenticatedUser();
String senderName = sender.getFirstName();
Map<String,Object> input = message.getDataAsMap();
String data = (String) input.get("name");
String temp = message.getChannel();
String temp1 = temp;
temp = temp.replace("/person/","");
final int conversationId = Integer.valueOf(temp);
Map<String,Object> output = new HashMap<>();
output.put("text",data);
output.put("sender",senderName);
output.put("channelname",temp);
output.put("timestamp",new Timestamp(System.currentTimeMillis()));
bayeux.createChannelIfAbsent(message.getChannel(), channel -> channel.setPersistent(true));
ServerChannel serverChannel = bayeux.getChannel(message.getChannel());
serverChannel.publish(remote,output);
Thread thread = new Thread(() ->{
Replies replies = new Replies();
replies.setReplyingPersonName(senderName);
replies.setReplyText(data);
this.repliesService.addReply(replies,conversationId, sender);
});
thread.start();
}
@Listener("/chat/*")
public void processChat(ServerSession remote, ServerMessage.Mutable message){
System.out.println("wassup");
String firstName = this.personService.returnLoggedInUsersName();
Timestamp timestamp = new Timestamp(System.currentTimeMillis());
Map<String, Object> input = message.getDataAsMap();
String data = (String)input.get("name");
String temp = message.getChannel();
String temp1 = temp;
temp = temp.replace("/chat/","");
final Long groupAccountIdentifier = Long.valueOf(temp);
Map<String, Object> output = new HashMap<>();
output.put("name",data);
output.put("channelname",message.getChannel());
output.put("firstname",firstName);
output.put("timestamp",timestamp);
output.put("accountid",groupAccountIdentifier);
bayeux.createChannelIfAbsent(message.getChannel(), channel -> channel.setPersistent(true));
ServerChannel serverChannel = bayeux.getChannel(message.getChannel());
serverChannel.publish(serverSession,output);
Thread thread = new Thread(() ->{
ChatMessages chatMessages = new ChatMessages();
chatMessages.setFirstName(firstName);
chatMessages.setChatText(data);
chatMessages.setChannelName(message.getChannel());
chatMessages.setTimeStamp(new Timestamp((System.currentTimeMillis())));
this.chatService.addChatMessage(chatMessages,groupAccountIdentifier);
});
thread.start();
}
}
Javascript код:
(function($)
{
var cometd = $.cometd;
$(document).ready(function()
{
function _connectionEstablished()
{
$('#body').append('<div>CometD Connection Established</div>');
}
function _connectionBroken()
{
$('#body').append('<div>CometD Connection Broken</div>');
}
function _connectionClosed()
{
$('#body').append('<div>CometD Connection Closed</div>');
}
// Function that manages the connection status with the Bayeux server
var _connected = false;
function _metaConnect(message)
{
if (cometd.isDisconnected())
{
_connected = false;
_connectionClosed();
return;
}
var wasConnected = _connected;
_connected = message.successful === true;
if (!wasConnected && _connected)
{
_connectionEstablished();
}
else if (wasConnected && !_connected)
{
_connectionBroken();
}
}
// Function invoked when first contacting the server and
// when the server has lost the state of this client
function _metaHandshake(handshake)
{
if (handshake.successful === true)
{
cometd.batch(function()
{
cometd.subscribe('/chat/1360', function(message)
{
$('#hello1').append('<div>Server Says: ' + message.data.name + ' ' + ' ' +message.data.firstname+'</div>');
});
});
cometd.publish('/chat/1360');
}
}
// Disconnect when the page unloads
$(window).unload(function()
{
cometd.disconnect(true);
});
var cometURL = location.protocol + "//" + location.host + config.contextPath + "/cometd";
cometd.configure({
url: cometURL,
logLevel: 'debug'
});
cometd.addListener('/meta/handshake', _metaHandshake);
cometd.addListener('/meta/connect', _metaConnect);
cometd.handshake();
});
})(jQuery);
Если у кого-то есть идеи, пожалуйста, дайте мне знать, что я могу сделать. Если вам нужна дополнительная информация, пожалуйста, не стесняйтесь спрашивать. Большое спасибо.:-)
ОБНОВИТЬ
Во второй раз, как предлагал Сбордер, я внес некоторые изменения, но добился частичного успеха. Также я забыл добавить свой index.jsp, который отправляет текстовое сообщение.
Во-первых, ChatServiceImpl:
@Session
private ServerSession serverSession;
@Listener("/service/chat/{accountid}")
public void processChat(ServerSession remote, ServerMessage.Mutable message,@Param("accountid")String accountid) {
System.out.println("wassup and account id is "+accountid);
String firstName = this.personService.returnLoggedInUsersName();
Timestamp timestamp = new Timestamp(System.currentTimeMillis());
Map<String, Object> input = message.getDataAsMap();
String text = (String) input.get("name");
String temp = message.getChannel();
Map<String, Object> data = new HashMap<String,Object>();
data.put("name", text);
data.put("channelname", message.getChannel());
data.put("firstname", firstName);
data.put("timestamp", timestamp);
ServerChannel serverChannel = bayeux.createChannelIfAbsent("/chat/1306").getReference();
serverChannel.setPersistent(true);
System.out.println("Channel name is "+serverChannel.getChannelId());
serverChannel.publish(remote, data);
}
Application.js:
function _metaHandshake(handshake)
{
if (handshake.successful === true)
{
cometd.batch(function()
{
cometd.subscribe('/chat/1306', function(message){
$('.hello1').append('<div>Server Says: ' +message.data.name + ' ' + ' ' +message.data.firstname+'</div>');
});
});
}
}
index.jsp:
<div id="body">
<input id="enterText" type="text" />Enter text
<input id="sendMessage" type="button"/>
</div>
<div class="hello1">
</div>
<div class="hello123">
</div>
<script type="text/javascript">
var config = {
contextPath: '${pageContext.request.contextPath}'
};
var cometd = $.cometd;
$(document).on("click", "#sendMessage", function(){
var text = $("#enterText").val();
cometd.publish('/service/chat/1306', { name: text});
});
Итак, если я использую serverChannel.publish на канале /service, то во внешнем интерфейсе текст не добавляется на сервер. Если я использую remote.deliver вместо публикации, правильный текст добавляется, но только к клиенту, который находится в текущем браузере, а не к другому клиенту, который находится в другом браузере. Как я могу использовать serverChannel.publish для отправки данных всем подписчикам, правильные данные я имею в виду.
1 ответ
Ваш клиентский код JavaScript публикуется неверно, просто вызывая:
cometd.publish('/chat/1360');
В нем отсутствуют данные, которые вы хотите отправить, и вы должны по крайней мере использовать пустой объект, как в:
cometd.publish('/chat/1360', {});
Обратите внимание, что, поскольку ваш клиент JavaScript (отправитель) также подписывается на канал /chat/1360
любое сообщение, которое отправитель публикует на этом канале, вернется обратно самому отправителю. Это стандартное поведение CometD.
Кроме того, на стороне сервера вы также публикуете на этом канале ServerChannel.publish(...)
Таким образом, вы отправляете подписчикам этого канала еще одно сообщение.
Вам не нужно звонить:
bayeux.createChannelIfAbsent(message.getChannel(), channel -> channel.setPersistent(true));
потому что на тот момент канал уже существует; ты можешь просто позвонить bayeux.getChannel(message.getChannel())
,
Что вы делаете, чтобы отправить сообщение на сервер (messageA
), то вы хотите обработать messageA
полей на сервере и создать новое, измененное сообщение (messageB
) для трансляции всем подписчикам, включая первоначального отправителя.
В этом случае это гораздо лучше, что вы отправляете messageA
на сервисном канале, поэтому он не транслируется всем подписчикам. MessageA
не предназначен для трансляции, это просто средство сообщить серверу, что вы хотите сделать, и сервисные каналы существуют именно для этой цели.
Получите ваши сообщения правильно в первую очередь, и вы увидите, что все остальное будет хорошо работать.
Вы можете использовать удаленные вызовы вместо служебных каналов, их проще использовать в данном конкретном случае, когда вы хотите выполнить некоторую обработку отправляемых вами сообщений на стороне сервера.
Наконец, посмотрите на параметры канала, вместо того, чтобы выполнять синтаксический анализ самостоятельно, используя нотацию слушателя:
@Listener("/chat/{accountId}")
public void processChat(ServerSession remote, ServerMessage.Mutable message, @Param("accountId") String account)
{
...
}