Because callbacks are, by definition, separated from the original request to which the callback is a response, they appear as unsolicited messages to the client's host. Many hosts refuse unsolicited network traffic, either because they directly reject such traffic or because they are protected by firewalls or other network security apparatus. Clients that run in such environments are therefore not capable of receiving callbacks.
Another requirement for handling callbacks is that the client is persistent by being conversational. If the client is a web application, that is, a JSP page, or a non-conversational web service, it cannot handle callbacks.
In order to allow clients that can't accept callbacks to use your web services, you can supply a polling interface as an alternative. In a polling interface, you provide one or more methods that a client can call periodically to determine whether the result of a previous request is ready. Although the web service or Java control will still be asynchronous in design, the interactions with a client are handled with synchronous (unbuffered) methods.
A typical design of a polling interface will have these three methods:
Notice that a client using a polling interface needs to periodically check the status of the request, because the web service or Java control cannot notify the client when its request has been processed. Also notice that the three methods will not be buffered. The check_status and get_results methods do not return void and cannot be buffered, while the start_request method cannot be buffered because you need to ensure that this method has been handled before the check_status is handled. (Remember that the relative handling order of buffered and unbuffered methods is uncertain. For more information, see Using Buffering to Create Asynchronous Methods and Callbacks.)
There are several other ways to implement a polling interface. The following example taken from the source code of the Conversation.jws Sample web service shows one such variation:
public class Conversation { /** * @common:operation * @jws:conversation phase="start" */ public void startRequest() { ... } /** * @common:operation * @jws:conversation phase="continue" */ public String getRequestStatus() { ... } /** * @common:operation * @jws:conversation phase="finish" */ public void terminateRequest() { } }
A client uses the startRequest method to initiate a request from a conversational web service. The client then calls getRequestStatus periodically to check on the result. As before, the client is free to perform other processing between calls to getRequestStatus. The getRequestStatus method returns an indication that the request is pending until the request is complete. The next time the client calls getRequestStatus after the request is complete, the result is returned to the client. The client then calls terminateRequest to finish the conversation.
Web Services Development Cycle
Getting Started: Using Asynchrony to Enable Long-Running Operations