Twitter, Facebook, Yahoo!, Google, and countless others provide REST APIs for their services. REST is designed for lightweight clients, those running inside Web browsers or other scripting environments. Rather than generating static language bindings from a metadata description, as found with WSDL in the Web services world, the REST approach is dynamic. Its emphasis is on a concise syntax for URLs that represent resources and the use of HTTP methods to describe actions on those resources.
REST services usually return data in XML or JSON format, with the format specified by the caller of the service. JSON stands for JavaScript Object Notation, a standard format for representing JavaScript objects as strings. Like XML, it’s widely used for communication between programs.
To invoke REST-style services, Apex can make HTTP requests from the Force.com platform to external servers on the Internet, as well as parse their JSON and XML responses. The core Apex classes that allow you to work with HTTP are described here:
HttpRequest—This class contains the parameters for making an HTTP request. It includes methods for working with the request body, HTTP headers, the HTTP method type, client certificates, HTTP compression, and timeouts.
HttpResponse—When an HTTP request is sent, an instance of the HttpResponse
class is returned. Methods are available for getting the raw response body, HTTP status code, and HTTP headers.
Http—This class is used to perform the HTTP operation. It contains a single method called send
to initiate the operation, which accepts an instance of HttpRequest
and returns an HttpResponse
.
In addition to these three classes, here are two other useful classes for working with HTTP in Apex:
1. EncodingUtil—This class contains methods for URL and Base64 encoding and decoding.
2. Crypto—Use the Crypto
class to compute cryptographic hashes and signatures commonly required to authenticate to HTTP services. It includes the methods generateDigest
to generate a one-way hash digest for a message, generateMac
to generate a message authentication code given a private key, and sign
to produce a digital signature for a message using a private key.
To get started with HTTP in Apex, try writing a method to invoke a RESTful service. The service used in the following example is provided by Yahoo!. It’s a geocoding service, returning latitude and longitude given a street, city, and state. The service is documented at http://developer.yahoo.com/boss/geo. Listing 10.1 is a sample of the result of invoking the service.
cbfunc({
"query": {
"count": 1,
"created": "2013-07-21T05:03:20Z",
"lang": "en-US",
"results": {
"place": {
"centroid": {
"latitude": "37.547031",
"longitude": "-122.314827"
}
}
}
}
});
In the code sample in Listing 10.2, the geocoding service is called and its response parsed using the JSON API provided by Force.com.
public class Listing10_2 {
private static String APP_ID = 'B1tiUc7k';
public static Result geocode(String location) {
HttpRequest req = new HttpRequest();
String query = 'select centroid from geo.places where text="'
+ location + '"';
String url = 'http://query.yahooapis.com/v1/public/yql?appid='
+ APP_ID + '&q=' + EncodingUtil.urlEncode(query, 'UTF-8')
+ '&format=json';
req.setEndpoint(url);
req.setMethod('GET'),
Http http = new Http();
HTTPResponse res = http.send(req);
JSONParser parser = JSON.createParser(res.getBody());
while (parser.nextToken() != null) {
if ((parser.getCurrentToken() == JSONToken.FIELD_NAME) &&
(parser.getText() == 'centroid')) {
parser.nextToken();
return (Result)parser.readValueAs(Result.class);
}
}
return null;
}
public class Result {
public String latitude;
public String longitude;
public String asString() {
return latitude + ', ' + longitude;
}
}
}
Tip
The Listing10_2
class will not work without a Remote Site Setting authorizing Force.com to call out to the Yahoo! service. To add this setting, go to the Administration Setup area and click Security Controls, Remote Site Settings. Click the New Remote Site button and enter a name to remember the site (no spaces allowed) and the root of the URL (http://query.yahooapis.com).
To test the code, open the Execute Anonymous view in the Force.com IDE and execute the statements given in Listing 10.3. The result (contained in the debug log) should be a single line containing the latitude and longitude of the input address.
Listing10_2.Result r = Listing10_2.geocode
('1 market st san francisco ca'),
System.debug(r.toString());
18.118.7.102