简体   繁体   中英

Call HttpServletResponse a second time

I'm trying to set up a servlet that I can use to call webservices asynchronously. For the most part, it is working fine. I have a servlet with a doGet method and a js that calls it. I have a callback method in the js that the servlet correctly calls when it has finished doing its thing.

The complication is that one of the web services I am calling is also asynchronous, and I would like to be able to essentially call the js callback method a second time after the asynchronous ws callback has finished. For example, if you have a status field, when you call the synchronous web service, it immediately updates to "Beginning Synchronous Call" and then when the servlet callback arrives it changes to the callback value, which is the result of the web service.

When you call the asynchronous web service, the update field immediately updates to "Beginning Asynchronous Call", and shortly receives the first callback from the servlet indicating that the web service has been requested, so we update the field to "Processing Web Service" or whatever. The problem is that once the web service finishes and calls back to the servlet, I can't seem to figure out how to send the result to the js callback method.

I'm pretty new at AJAX and servlets, so maybe this is a horrible way to accomplish what I want.

The web services are both being called in the Servlet, mostly using Netbeans auto-generated WS calls. The WS calls themselves work fine, but once I get the result of the asynchronous WS, I am stuck inside of the handleResponse method of the webservice callback and no longer have any reference to the response element for the document I want to update.

I tried to store the original response variable as a static member variable and use it in the handleResponse method like so:

javax.xml.ws.AsyncHandler<WsClients.Op11Response> asyncHandler = new javax.xml.ws.AsyncHandler<WsClients.Op11Response>() {

    public void handleResponse(javax.xml.ws.Response<WsClients.Op11Response> asyncResponse) {
        try {
            storedResponse.setContentType("text/xml");
            String returnString = asyncResponse.get().getReturn();
            storedResponse.getWriter().write("<returnData><content>"
                    + returnString + "</content></returnData>");

        } catch (Exception ex) { 
        }
    }
};

This will not compile with a debugger attached and does not seem to be able to assign a reference anyway.

Is there a better way to do this?

The nature of HTTP is that you cannot send anything back to the client unless client requested this information either by polling or by keeping the connection open.

The operation to start the asynchronous call ends immediately and you need to return from the servlet doGet method (while technically you can stay in the servlet call until your async call finishes I wouldn't recommend that as it ties up the server resources. It is generally a good practice to return from the servlet as soon as you can).

The best course of action would be:

  1. Have internal data structure (eg HashMap with appropriate synchronization) to hold the asynchronous calls that are executing.
  2. When you start a new call, assign it pseudo-random key and return it from the initial call.
  3. Using the above key, have browser-side javascript AJAX calls periodically poll the status of the call and display the results.
  4. Do not forget to clean up finished or stale calls (for example by running a timer thread).

When you comfortable with the polling implementation in step 3 above, you may want to consider Comet, aka long poll to replace client-side polling.

Servlet cannot send response again. HTTP protocol is synchronous, and only client can initiate a request-response exchange.

For async updates you need to perform polling from the client side to the server side, and accumulate messages on the server side (in the sessions) until client picks them up or they expire.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM