I am working on a Spring-MVC application which uses Cometd for chatting. The only problem I am facing is when I send a message from client-side, the client is appending that message directly to server-says, instead of waiting for me to call in the backend the publish mechanism and then appending that stuff. I tried it on 2 different computers connected, same result. Because of this, I am not able to access variables which I am setting in the backend.
Kindly let me know what I can do. Thanks a lot.
Debug Log :
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}
In the above debug log, the first line comes from the client, and the statement 'wassup' is printed in the start of my @Listener method. Next, I add some data and publish it, but I cannot access any variables mentioned from the third line. Any ideas.
Here is Java code :
@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 code :
(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);
If anyone has any ideas, kindly let me know what I can do. If there is anymore information necessary, please feel free to ask. Thanks a lot. :-)
UPDATE
As per Sborder suggested second time, I made some changes, but I have met with partial success. Also I forgot to add my index.jsp, which is sending the actual text message.
Firstly, 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});
});
So, if I use serverChannel.publish on a /service channel, then In the front-end, no text is appended to server. If I use remote.deliver instead of publish, the correct text is appended, but only to the client who is on the current browser, not to other client who is in another browser. How can I use serverChannel.publish to send data to all subscribers, the correct data I mean.