Invoke an Asynchronous Servlet from AJAX

What I'm trying to accomplish is not too complicated, but I have a bit of a problem as I am not very good at AJAX.

When it is implemented, I will have a JSP that has a button that invokes the asynchronous servlet. The servlet will perform the long-term task and provide dynamic feedback to the user by adding rows to the table when the parts of the task are completed.

Before I try to write the final version, I make a proof of concept to understand how this will work. However, I am facing a problem. When I use an AJAX call when I click the button, the function works as expected when the call is made for a regular synchronous servlet. However, as soon as I make the servlet asynchronous, updates are not displayed.

Can anyone give some idea of ​​what is going wrong?

My JSP looks like this:

<html>
    <body>
        <script type="text/javascript" charset="utf-8">
            $(document).ready(function() {
                $('#mybutton').click(function() {
                    $.get('someservlet', function(responseJson) {
                        $.each(responseJson, function(index, item) {
                            $('<ul>').appendTo('#somediv');
                            $('<li>').text(item.row1).appendTo('#somediv');
                            $('<li>').text(item.row2).appendTo('#somediv');
                            $('<li>').text(item.row3).appendTo('#somediv');
                            $('<li>').text(item.row4).appendTo('#somediv');
                        });
                    });
                });
            });
        </script>
        <p><button id="mybutton">Click to add things</button></p>
        <div id="somediv"></div>
    </body>
</html>

My asynchronous servlet doGet()method is as follows:

response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
final AsyncContext asyncContext = request.startAsync();
final PrintWriter writer = response.getWriter();
asyncContext.setTimeout(10000);
asyncContext.start(new Runnable() {

@Override
public void run() {
    for (int i = 0; i < 10; i++) {
        List<Row> rows = new ArrayList<Row>();
        rows.add(new Row(i, i + 1, i + 2, i + 3));
        String json = new Gson().toJson(rows);
        writer.write(json);
        writer.flush();
        log.info("Wrote to JSON: " + i);
        try {
            Thread.sleep(1000);
        } catch (InterruptedException ex) {
        }
    }
    asyncContext.complete();
    }
});

Any thoughts? It seems that my AJAX call, which occurs when I click the button, only accepts the response from the main servlet thread. Perhaps I need to call a JavaScript function from asynchronous calls write()? I'm just not sure how to do this, or if this will be the correct execution method.

+3
source share
2 answers

OK!

, . , , . , . - , push .

?

JSP :

<html>
    <head>
        <script src="jquery-1.7.1.min.js" type="text/javascript" ></script>
        <script>
            $(document).ready(function() {
                var prevDataLength;
                var nextLine = 0;
                var pollTimer;
                $('#abutton').click(function() {
                    $(function(){
                        var x = new $.ajaxSettings.xhr();
                        x.open("POST", "someservlet");
                        handleResponseCallback = function(){
                            handleResponse(x);
                        };
                        x.onreadystatechange = handleResponseCallback;
                        pollTimer = setInterval(handleResponseCallback, 100);
                        x.send(null);
                    });
                });

                function handleResponse(http) {
                    if (http.readyState != 4 && http.readyState != 3)
                        return;
                    if (http.readyState == 3 && http.status != 200)
                        return;
                    if (http.readyState == 4 && http.status != 200) {
                        clearInterval(pollTimer);
                    }

                    while (prevDataLength != http.responseText.length) {
                        if (http.readyState == 4  && prevDataLength == http.responseText.length)
                            break;
                        prevDataLength = http.responseText.length;
                        var response = http.responseText.substring(nextLine);
                        var lines = response.split('\n');
                        nextLine = nextLine + response.lastIndexOf(']') + 1;
                        if (response[response.length-1] != ']')
                            lines.pop();
                        for (var i = 0; i < lines.length; i++) {
                            var line = $.parseJSON(lines[i]);
                            addToTable(line);
                        }
                    }

                    if (http.readyState == 4 && prevDataLength == http.responseText.length)
                        clearInterval(pollTimer);
                }

                function addToTable(JSONitem) {
                    $.each(JSONitem, function(index, item) {
                        $('<tr>').appendTo('#sometablebody')
                        .append($('<td>').text(item.name))
                        .append($('<td>').text(item.message))
                        .append($('<td>').text(item.number))
                        .append($('<td>').append($('<a>').attr('href', item.link).text('link')));
                    });

                }
            });
        </script>
        <title>Async Test</title>
    </head>
    <body>
        <p><button id="abutton">Click to add things</button></p>
        <div id="somediv">
            <table border="1">
                <thead>
                    <tr>
                        <td>Name</td>
                        <td>Message</td>
                        <td>Number</td>
                        <td>Link</td>
                    </tr>
                </thead>
                <tbody id="sometablebody"></tbody>
            </table>
        </div>
    </body>
</html>

doGet() :

request.setAttribute("org.apache.catalina.ASYNC_SUPPORTED", true);

        final AsyncContext asyncContext = request.startAsync();
        final PrintWriter writer = response.getWriter();
        asyncContext.setTimeout(60000);
        asyncContext.start(new Runnable() {

            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    try {
                        List<Row> list = new ArrayList<Row>();
                        list.add(new Row("First", "This is the first", String.valueOf(i), "link" + i));
                        list.add(new Row("Second", "This is the second", String.valueOf(i), "link" + i));
                        list.add(new Row("Third", "This is the third", String.valueOf(i), "link" + i));
                        String json = new Gson().toJson(list);

                        asyncContext.getResponse().setContentType("application/json");
                        asyncContext.getResponse().setCharacterEncoding("UTF-8");
                        try {
                            asyncContext.getResponse().getWriter().write(json);
                            asyncContext.getResponse().getWriter().flush();
                        } catch (IOException ex) {
                            System.out.println("fail");
                        }

                        Thread.sleep(250);
                    } catch (InterruptedException ex) {
                        break;
                    }
                }
                asyncContext.complete();
            }
        });

, , , Row:

public class Row {

    private String name;
    private String message;
    private String number;
    private String link;

    public Row(String name, String message, String number, String link) {
        setName(name);
        setMessage(message);
        setNumber(number);
        setLink(link);
    }

    public String getLink() {
        return link;
    }

    public void setLink(String link) {
        this.link = link;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }
}
0

All Articles