Ajax Proxy
S-Controls
| Note: S-controls have been superseded by Visualforce pages. For more information, please visit S-Control_Deprecation |
Contents |
Applies to
- Developer Edition (Free for DFC Members)
- Enterprise Edition
- Unlimited Edition
Application overview
This article describes how to build a mash-up on the Force.com Platform using data from a third party web service. In particular, this web service simply takes in two country names and returns the exchange rate for those two countries. The service is free and is hosted by XMethods. As such this particular web service does not guarantee any level of service and may be removed without notice.
The key mechanism for getting data from this web service is SOAP based RPC. These protocols use standard XML-based formats, which presents a problem for applications looking to combine data from a third party API and data from another domain, such as Salesforce. Client browsers have a cross domain scripting restriction, which prevents the browser from communicating with any domain other than the domain that serves the browser page. This restriction would normally prevent a Salesforce page from communication with a third party API through JavaScript on the client.
To avoid this problem, Force.com SOA includes a feature called the AJAX proxy. This proxy allows client-side S-Controls to use JavaScript to communicate with third-party websites through the Salesforce.com infrastructure. Since the request from the S-Control intially goes to the Salesforce domain proxy, there is no violation of the cross domain restriction. The next section describes the specifics of using the AJAX proxy.
Using the Salesforce AJAX proxy
The application described in this article uses the Salesforce AJAX proxy to communicate with an XMethods API using SOAP. An S-Control sends web requests to the XMethods API via the AJAX proxy.
There is a new function in the Salesforce AJAX library that performs this proxy call. The new function name is remoteFunction() and the signature for the function is sforce.connection.remoteFunction( {request object} );
This function, when called from your S-Control, would submit a request to the proxy through a URL such as the following -
https://na1.salesforce.com/services/proxy
The request object is a simple data structure that you construct which contains all the members needed for the proxy to construct an HTTP request on behalf of your client scontrol, such as URL, mimeType, requestHeaders, etc. This type of request is allowed by client browsers as it abides by the same domain security rule that browsers enforce when communicating with servers. You will see an example of this object in the code sample below.
Once the proxy receives your request, it constructs an outgoing request to the final destination specified , and waits for the response. The timeout for the request is set to 10 seconds, so normal web requests will work well with the AJAX Proxy SOA feature.
Once the response is received, the proxy repackages the response and delivers it back to the S-Control. The remainder of this article will illustrate this process in more detail.
The really cool part of this function is that the response is already parsed into an XML node tree by the AJAX library, so that when you receive a valid response you can simply traverse it as you would any XML DOM document.
In this demonstration code, all the calls from the Salesforce AJAX proxy are being made synchronously. In most production applications, you would make these calls asynchronously to provide a more interactive user experience.
Configuring the Salesforce.com AJAX proxy
The Salesforce.com AJAX proxy must be enabled for an organization. Once the feature is enabled, the next step is to set up the domains you wish to allow the proxy to communicate with. This is done through the standard set up and configuration area of the Salesforce environment.
For this application, you would add the XMethods website as one of the allowed domains.
Creating the Application
The application is intentionally meant to be simple and have few moving parts as the purpose is to illustrate the use of the Ajax Remote Proxy. It consists of two <select> tags that contain the same list of countries to choose from. It also contains a button to invoke the web service and a text input to countain the results. Below is the body of the S-Control.
<body onload="loadCountries()">
Country 1 <select id="country1"></select>
Country 2 <select id="country2"></select>
<input type="button" value="Get Rate" onclick="javascript: getRate();" />
<br><br>Results<br>
<input type="text" id="result" />
</body>
In the html code above we are loading the options for the select list in the onload event of the body and calling the getRate() function when the user clicks a button. Pretty straight forward.
I'm including the loadCountries code for completeness, but will leave it to the reader to understand what it does.
<script src="/soap/ajax/11.0/connection.js"></script>
<script type="text/javascript">
function getRate() {
var s1 = document.getElementById("country1");
var s2 = document.getElementById("country2");
var c1 = s1.options[s1.selectedIndex].value;
var c2 = s2.options[s2.selectedIndex].value;
var envelope =
'<soap:Envelope xmlns:mrns0="urn:xmethods-CurrencyExchange" ' +
'xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" ' +
'xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" ' +
'xmlns:xs="http://www.w3.org/2001/XMLSchema" ' +
'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">' +
'<soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">' +
'<mrns0:getRate>' +
'<country1 xsi:type="xs:string">' + c1 + '</country1>' +
'<country2 xsi:type="xs:string">' + c2 + '</country2>' +
'</mrns0:getRate>' +
'</soap:Body>' +
'</soap:Envelope>';
sforce.connection.remoteFunction({
url : "http://services.xmethods.net/soap",
requestHeaders: {
"Content-Type": "text/xml",
"SOAPAction": "\"\""
},
mimeType: "text/xml",
requestData: envelope,
method: "POST",
onSuccess : function(response) {
document.getElementById("result").value = response.textContent;
},
onFailure : function(response) {
document.getElementById("result").value = "Failed " + response;
}
});
}
var countries = ["afghanistan", "albania", "algeria", "andorra", "andorra",
"angola", "argentina", "aruba", "australia", "austria", "bahrain",
"bangladesh", "barbados", "belgium", "belize", "bermuda", "bhutan",
"bolivian","botswana", "brazil", "england", "united kingdom", "uk",
"great britain","brunei", "burundi", "cambodia", "canada", "chile",
"china", "denmark", "netherlands", "estonia", "france", "germany",
"hong kong", "india", "ireland", "israel", "japan", "korea", "mexico",
"new Zealand", "norway", "poland", "romania", "russia", "singapore",
"sweden", "switzerland", "taiwan", "united states", "us", "usa"];
function loadCountries() {
var select1 = document.getElementById("country1");
var select2 = document.getElementById("country2");
for (var i = 0;i<countries.length;i++) {
var opt = document.createElement("option");
var opt2 = document.createElement("option");
opt.value = opt2.value = countries[i];
opt.text = opt2.text = countries[i];
select1.appendChild(opt);
select2.appendChild(opt2);
}
}
</script>
Let's take a walk through the getRate function to understand how to use the remote proxy. The first two lines are simply collecting the arguments needed for the web service. As a reminder, the web services takes two country names and then return the exchange rate between the two countries.
The next section of the code is building the SOAP message for this particular web service. It is helpful when creating remote proxy code to have samples of the the SOAP messages for the web service that you want to exercise. You can certainly analyze the web services WSDL as well to determine the format and content of the SOAP message as well.
As you can see, the soap message is simply a string representation of the SOAP XML. We are substituting the two country values about 3/4 of the way down this string constructor so that the values are passed dynamically to the web service.
Once the message has been built we are ready to send it to the web service. This is done using the remoteFunction method of the AJAX connection object. We need to construct the request to pass to the remoteFunction, and in this case, we are defining it in the remoteFunction call itself.
The first item that is set is the url. This url must be to a domain that you have added to your Remote Sites in setup as mentioned earlier in this article. The url is the full url to the service endpoint as defined in the services WSDL.
Next, we create some requestHeaders. These are http headers and may or may not be different for your web service. The AJAX Remote Proxy works for other requests as well, such as RSS feeds, http GET, and so on. Each of these different types of requests may have different requirements for the requestHeaders.
The mimeType attribute is very important as this will determine the format that the Ajax toolkit will return your results in. Understanding the results returned from your web service will help determine what mime type to set. In this case, we want to have the object as an XML tree, not simple text.
The requestData attribute is used for the "payload" of the request. This is the soap message that we created above.
Every request needs to specify the method being used for the web service in question. SOAP/RPC will almost always require the POST method, while other request types might require a GET method. Again, understanding your web service and how it operates is key to getting this attribute correct.
For most services you will want to define two callback functions, one for a successful request and one to handle a failed request. These callbacks are where you will "handle" the data returned from your service. In the case of this application, the web service response is quite simple and the "meat" of the response can be obtained by access the textContent attribute of the XML tree. Other service might require more complex parsing of the response. In this application we are simply going to set the value of our html text input field to the exchange rate value returned.
And that's it! The Ajax Remote Proxy provides access to data and services that otherwise would not be reachable due to browser security restrictions. Successful use of the proxy requires a clear understanding of the requests and the responses to what ever web service you will use.

