Calling Web Services and Custom Java Controls From A Page Flow

The following topic explains how call a web service or a Custom Java Control (JCS file) from a Page Flow.

In most cases, you communicate with a web service or Custom Java Control resource, you send a request to the resource, and then listen for a callback containing the response. But one limitation of Page Flows is that that they cannot hear callbacks from web-based resources. For this reason, Page Flows can only communicate with web-based resources that either have synchronous methods (methods where the request and the returned result are accomplished within the same method) or that have polling interfaces (an interface that allows the page flow to send the request through one method, and then collect the result through another method). Each of these communication techniques are described below.

Synchronous Communication

Suppose you have a web service that communicates synchronously with its clients, such as the HelloWorld.jws web service. Synchronous communication means that an individual method of the web service both takes requests and returns the results of those request, without using another callback method to return the results. The following web service communicates synchronously, because one and the same method Hello() both takes a request and returns the result, the String "Hello World!", to the client.

public class HelloWorld implements com.bea.jws.WebService
{ 
    /**
     * @common:operation
     */
    public String Hello()
    {
        return "Hello, World!";
    }	
}

To call a web service's methods from a page flow, first declare the web service's control file within the page flow file.

public class MyPageFlow extends PageFlowController
{

    /**
     *  @common:control
     */
    private HelloWorldControl myControl;
	
	.
	.
	.
 
 
}

Now you can call the methods on the web service through the object myControl.

    /**
     * Action encapsulating the control method : HelloWorld
     * 
     * @jpf:action
     * @jpf:forward name="success" path="result.jsp"
     */
    public Forward HelloWorld()
    {
        String result = myControl.HelloWorld();

        return new Forward( "success" );
    }

However, it is generally bad design to base page flow/web resource communication on synchronous methods. This is because clients (the page flow) are blocked while they wait for the synchronous methods on the web resource to execute. If the resource takes a substantial amount of time to complete its work, the client will be blocked the same amount of time waiting for the resource to complete. For this reason, it is generally best to use a polling interface to control page flow / web resource communication whenever possible.

Polling Interfaces

In most cases a web service communicates with its clients through the use of asynchronous callbacks. This means that a client makes a request of a web service and then receives the result at a later time in the form of a callback message. Using this technique, the client does not have to halt its own processes while it waits for the callback message: it can go on to do other tasks, such as processing data, making other requests, etc.

But not all clients are capable of hearing callback messages from web services: Page Flows are one such client. As a workaround for this limitation, a Page Flow can communicate with a web service through the use of a polling interface. A polling interface allows a web resource to communicate with those clients that are unable to hear callbacks from the resource.

Polling interfaces work by provided one method where clients make requests of the web service, and another method where clients collect the result. Note that this technique does not rely on callbacks: the resource never invokes a callback handler on the client. Instead each method call in the polling process is client initiated.

Suppose there is a web service that presents a polling interface with three different methods: requestData(), isDataReady(), and getData(). Clients call requestData() to make a request of the web service, they call isDataReady() to see if the result is ready to be collected, and they call getData() to collect the completed result. To utilize this polling interface from a page flow, you first must declare the web service control file on the page flow file.

public class MyPageFlow extends PageFlowController
{

    /**
     *  @common:control
     */
    private MyWebServiceControl myControl;
	
	.
	.
	.
 
 
}

The following shows a typical routine for calling the methods of a polling interface from a Page Flow. In a typical routine, the polling is allowed to go on for a set amount of time, not indefinitely. (In the example below, the polling lasts 20 seconds. After that time, the user is forwarded to the error page.) How long you should poll the web service depends on the specifics of the target web service, your client application, and the web environment.

    /**
     * @jpf:action
     * @jpf:forward name="success" path="response.jsp"
     * @jpf:forward name="failure" path="error.jsp"
     */
    protected Forward pollForData()
        throws java.lang.InterruptedException
    {
        /**
         * Request data from the web service.
         */
        myControl.requestData();
        
        /**
         * Poll the isDataReady method 20 times, once a second,
         * to check if the result is ready.
         */
        for(int i=0; i<20; i++)
        {
            /*
             * If the data is ready, get the data,
             * store it in _data, and forward the user to 
             * response.jsp.
             */
            if(myControl.isDataReady() == true)
            {
                _data = myControl.getData();
                return new Forward("success");
            }
            else
            {
                /*
                 * If the data is not ready, wait one second before
                 * polling again.
                 */
                Thread.sleep(1000,0);
            }
        }
    
        /*
         * The data was not delivered in the time allowed (20 seconds).
         * Forward the user to the error page.
         */
        _message = "The web service did not respond it the time allowed.";
        
        return new Forward("failure");
	}

Related Topics

Calling a Synchronous Web Service Sample

Calling an Asynchronous Web Service Sample

Tutorial: Page Flow: Step 2: Processing Data with Page Flows