CallServer FormAPI – Teamsite

What is CallServer in FormAPI – Teamsite?

FormAPI is client-side technology. The user scripts that the template designer writes are loaded into the browser and executed by its JavaScript engine. There are many times, however, when code in the user script needs to access resources on a remote server.

Most commonly, the user script needs to run a database query and use the results to set the value of an item. The canonical example is the address entry form that automatically populates the city and state fields after the user has entered the ZIP code. There is no way the user script can include the entire city/state/ZIP database in the code; that information is best obtained from a server.

In Interwoven Teamsite, CallServer is method to make an HTTP request with a set of attributes-value pairs. The request may take the form of either an HTTP POST or an HTTP GET call. The target server (which can be any process that can handle an HTTP request and make a response, such as a servlet or CGI) reads the request and returns JavaScript code embedded in an HTML page. This page is loaded into a hidden frame, distinct from the frame that contains the user script and FormAPI. FormsPublisher provides a special parent.getScriptFrame() function to this hidden frame that returns the user script frame. In this way, the code returned by the server coexists with the user script and has full access to its methods and data.

The callServer() method is asynchronous. A new thread is started with the HTTP request and completes only when it finishes executing the code returned by the server. The user script code that made the request continues executing immediately after the call to callServer(). For this reason, callServer() is usually the last line of code in an event handler; the logic “picks up” in the hidden frame after the post is complete.

Here is an example illustrating a typical city/state/ZIP code form:

IWEventRegistry.addItemHandler("/zip", "onItemChange", fillCityState);

 

The fillCityState() handler is a function that queries a remote server for city and state:

function fillCityState(zipItem) {
	if (zipItem.isValid()) {
		var parameters = new Object();
		parameters.zip = zipItem.getValue();
		// Make an HTTP GET to the server.
		callServer("http://myserver/getCityState", parameters, true);
	}
}

 

The result from a call to the server (which will be given the request like http://myserver/
getCityState?zip=94086) returns code similar to this:

<html>
	<head>
		<script language="javascript">
			// Get handle to the FormAPI/userscript frame.
			api = parent.getScriptFrame();
			// Set the city and state.
			api.IWDatacapture.getItem("/city").setValue("Sunnyvale");
			api.IWDatacapture.getItem("/state").setValue("CA");
		</script>
	</head>
	<body>
	</body>
</html>

 

One of the hazards of making a remote server request is that it may take too long to return. Worse, it may not return at all. To guard against this problem, a user script can use the JavaScript setTimeOut() function to handle a request that does not return within a specified amount of time. Before it calls the server, setTimeOut() is instructed to execute an error handler function. The code that returns from the server cancels the pending error handler call (if it is running, the request succeeded). If the server does not return in time, the error handler is executed.

Adjust the user script fillCityState() function to set up the time out:

...
// Error handler called in 1 minute. Save ID in global variable
// for hidden frame to cancel if it succeeds.
timeout = setTimeOut("callServerFailed", 60000);

// Make an HTTP GET to the server.
callServer("http://myserver/getCityState", parameters, true);
...

 

Create a callServerFailed() function to handle the error case:

function callServerFailed() {
	alert("ZIP code lookup failed. Be sure to enter city and state.");
}

Finally, modify the JavaScript returned from the server to cancel the time out:

...
// Get handle to the FormAPI/userscript frame.
api = parent.getScriptFrame();

// Cancel the pending time out.
clearTimeout(api.timeout);
...

This does not handle the case where the server is not down, but simply slow. In this case, after one minute the user is prompted that the ZIP code lookup failed, but several moments later may suddenly see the city and state fields automatically change. To guard against this possibility, modify the callServerFailed() function to cancel the server call:

function callServerFailed() {
	alert("ZIP code lookup failed. Be sure to enter city and state.");
	// Abort the request by sending a blank page to the hidden frame.
	IWDatacapture.callServer("blank.html", new Object(), true);
}

This request cancels the previous request by making a new one to an empty file. This illustrates an important point about the callServer() method: only one call can be active at a time. Subsequent calls to callServer() will cancel any previous calls.

Important Note:

  1. Use only one CallServer method in Form init for setting initial values in form. To set on init Handler see below code: IWEventRegistry.addFormHandler(“onFormInit”, init);
  2. If on any event you want to set data to more than one element, do not use two call server. Use only one CallServer Method to set all the dropdown.
  3. Above shown is the first way to set the data to elements. Another way to set elements is to set data in array variable and print it on the page in script tag. See below code in perl.
    my $str = "Data1[0] = 'ABC'; Data1[1] = 'XYZ'; Data2[0] = '123'; Data2[1] = 'Test';"; 
    #you can call any subroutine here and return a string like this which sets more values
    
    my $data = qq{
    Content-type: text/html; charset=utf-8
    <script language="javascript">
    	var Data1 = new Array();
    	var Data2 = new Array();
    	var Data3 = new Array();
    	$str
    	var api = parent.getScriptFrame();
    	api.callBackFunction(Data1, Data1, Data1);
    </script>
    <html>
    
    </html>
    };
    
    print $data;

Please comment here if you have any queries or suggestion. I will be posting on generalization of CallServer Method for all the template.