I am trying to create a demo of Group Chat using reverse ajax in Spring. I am using Spring 3.2.0.RELEASE version.
I am using DeferredResult to perform reverse ajax in my controller. Following is the snippet of my Controller class.
@Autowired
private AsyncRepository asyncRepository;
Map<Integer, List<DeferredResult<String>>> watchers = new ConcurrentHashMap<Integer, List<DeferredResult<String>>>();
@RequestMapping(value="/asyncRequest/getMessages/{id}", method=RequestMethod.GET)
@ResponseBody
public DeferredResult<String> getMessages(final @PathVariable("id") Integer id){
final DeferredResult<String> deferredResult = new DeferredResult<String>(null, Collections.emptyList());
if(watchers.containsKey(id)) {
watchers.get(id).add(deferredResult);
} else {
watchers.put(id, new ArrayList<DeferredResult<String>>());
watchers.get(id).add(deferredResult);
}
deferredResult.onCompletion(new Runnable() {
@Override
public void run() {
watchers.get(id).remove(deferredResult);
}
});
return deferredResult;
}
@RequestMapping(value="/asyncRequest/setMessages/{id}/{message}", method=RequestMethod.GET)
@ResponseBody
public String setMessage(@PathVariable("id") Integer id, @PathVariable("message") String message) {
asyncRepository.setMessage(id, message);
return "";
}
@Scheduled(fixedRate=1000)
public void processQueues() {
for (Map.Entry<Integer, Queue<AsyncDataBean>> entry : asyncRepository.getAsyncBeans().entrySet()) {
while(entry != null && entry.getValue() != null && !entry.getValue().isEmpty()) {
AsyncDataBean asyncDataBean = entry.getValue().poll();
for (DeferredResult<String> deferredResult : watchers.get(asyncDataBean.getId())) {
deferredResult.setResult(asyncDataBean.getMessage());
}
}
}
}
And below is the Repository class which holds the Map of GroupID and its relevant messageQueue. And it also has the functions for getting and setting the messages for relevant group id.
@Repository
public class AsyncRepository {
private Map<Integer, Queue<AsyncDataBean>> asyncBeans = new ConcurrentHashMap<Integer, Queue<AsyncDataBean>>();
public String getMessages(Integer id) {
StringBuilder stringBuilder = new StringBuilder();
while (asyncBeans.get(id) != null && !asyncBeans.get(id).isEmpty()) {
stringBuilder.append(asyncBeans.get(id).poll().getMessage()).append("~");
}
return stringBuilder.toString();
}
public void setMessage(Integer id, String message) {
if(asyncBeans.containsKey(id)) {
asyncBeans.get(id).add(new AsyncDataBean(id, message));
} else {
Queue<AsyncDataBean> messageQueue = new ConcurrentLinkedQueue<AsyncDataBean>();
messageQueue.add(new AsyncDataBean(id, message));
asyncBeans.put(id, messageQueue);
}
}
public Map<Integer, Queue<AsyncDataBean>> getAsyncBeans() {
return asyncBeans;
}
public void setAsyncBeans(Map<Integer, Queue<AsyncDataBean>> asyncBeans) {
this.asyncBeans = asyncBeans;
}
}
And below is the data bean I am using to store each message with its group id.
public class AsyncDataBean {
private Integer id;
private String message;
public AsyncDataBean() {
}
public AsyncDataBean(int id, String message) {
this.setId(id);
this.setMessage(message);
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
And then comes the jsp page for group chat. which looks like below.
<script type="text/javascript">
var messagesWaiting = false;
function getMessages(){
if(!messagesWaiting){
$.ajax({ url: "${pageContext.servletContext.contextPath}/asyncRequest/getMessages/${id}",
dataType:"text",
success: function(data,textStatus,jqXHR) {
if(textStatus == 'success'){
messagesWaiting = false;
var arr = data.split("~");
for(var i=0; i<arr.length; i++)
{
try
{
if(arr[i] != '') {
$("#txtaMessages").val($("#txtaMessages").val() + "\n\n" + arr[i]);
document.getElementById("txtaMessages").scrollTop = document.getElementById("txtaMessages").scrollHeight;
}
}
catch(e){
alert(e.message);
}
}
}
},
complete: function(j) {
},
error: function(xhr) {
}
});
messagesWaiting = true;
}
}
setInterval(getMessages, 1000);
getMessages();
function sendMessage() {
var xmlhttp1 = new XMLHttpRequest();
xmlhttp1.open("GET", '${pageContext.servletContext.contextPath}/asyncRequest/setMessages/${id}/' + $("#txtMessage").val(), true);
xmlhttp1.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xmlhttp1.send();
$("#txtMessage").val("");
$("#txtMessage").focus();
}
</script>
</head>
<body>
<h1>Hello World!</h1>
<table>
<tr>
<td>Messages :: </td>
<td>
<textarea cols="100" rows="10" id="txtaMessages"></textarea>
</td>
</tr>
<tr>
<td>Send Message :: </td>
<td><input type="text" id="txtMessage"/></td>
</tr>
<tr>
<td><input type="button" value="Send" onclick="sendMessage();"/></td>
</tr>
</table>
</body>
</html>
That is what I have coded till now to get this working. And everything is working finw in FF and Chrome. But in IE it is not working as expected. The request is never gets hold on the server and it always gets executed every second as configured in the javascript code. And it always returns the same result as previous. I have tried to use several other methods to send ajax request for IE but its not working. Can anyone get it working for me?
Since everything works fine in FF and Chrome, I suspect the problem is with javascript code to send the request to get messages.
Please help me.
Thanks in advance.