Reverse ajax using DeferredResult from Spring 3.2.0.RELEASE. Doesn't work in IE

I am trying to create a group chat demo 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. Below is a 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 contains the GroupID map and the corresponding MessageQueue. And it also has functions to get and set messages for the corresponding 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 bean data I use 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;
    }
}

      

Then the jsp page for the group chat will appear. 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>

      

This is what I have coded so far to get this to work. And everything works in FF and Chrome. But in IE, it doesn't work as expected. The request is never delayed on the server and it is always fired every time it is configured in the javascript code. And it always returns the same result as the previous one. I tried a few other methods to send ajax request for IE, but it doesn't work. Can anyone make it work for me?

Since everything works fine in FF and Chrome, I suspect the issue is with the javascript code for sending the receive message request.

Please help me.

Thanks in advance.

+1


source to share


1 answer


This is very frustrating.

For this to work properly in IE, I need to set an attribute cache:false

in the ajax request that I create with jquery for getMessages. Otherwise, IE will not hold the request in a pending state and will always return back with the old response.



This is a very big problem with IE. I hope no one else will run into the problem or find this answer as early as possible.

:)

+1


source







All Articles