Issuing a REST request and parsing a response

A proper introduction to REST is out of scope for this recipe. Countless materials describing the REST architectural style are available both online and offline. Wikipedia's entry on Representational State Transfer at http://en.wikipedia.org/wiki/Representational_State_Transfer provides a compact description of REST's main concepts, its limits, and the guiding principles to design RESTful applications. A more tongue-in-cheek introduction to REST can be found on Ryan Tomayko's website at http://tomayko.com/writings/rest-to-my-wife.

There are several ways to execute a REST request using Groovy. In this recipe, we are going to show how to execute a GET operation against a RESTful resource using RESTClient from the HTTPBuilder project (http://groovy.codehaus.org/modules/http-builder/doc/index.html). HTTPBuilder is a wrapper for Apache HttpClient, with some Groovy syntactical sugar thrown on top.

Getting ready

For this recipe, we will use the RESTful API exposed by the Bing Map Service (http://www.bing.com/maps/). The API allows performing tasks such as, creating a static map with pushpins, geocoding an address, retrieving imagery metadata, or creating a route.

In order to access the service, an authentication key must be obtained through a simple registration process (see https://www.bingmapsportal.com). The key has to be passed with each REST request.

How to do it...

The following steps will use the Location API, through which we will find latitude and longitude coordinates for a specific location:

  1. The first step is to create a class. The class has a method, which accepts the information to query the map service with:
    @Grab(
      group='org.codehaus.groovy.modules.http-builder',
      module='http-builder',
      version='0.6'
    )
    import static groovyx.net.http.ContentType.JSON
    import static groovyx.net.http.ContentType.XML
    import groovyx.net.http.RESTClient
    
    class LocationFinder {
    
      static final KEY = '...'
      static final URL = 'http://dev.virtualearth.net'
      static final BASE_PATH = '/REST/v1/Locations/'
    
      def printCityCoordinates(countryCode, city) {
    
        def mapClient = new RESTClient(URL)
        def path = "${countryCode}/${city}"
        def response = mapClient.get(
                         path: "${BASE_PATH}${path}",
                         query: [key: KEY]
                       )
    
        assert response.status == 200
        assert response.contentType == JSON.toString()
    
        println response.
                  data.
                  resourceSets.
                  resources.
                  point.
                  coordinates
    
      }
    }
  2. We can use the class in the following way:
    LocationFinder map = new LocationFinder()
    map.printCityCoordinates('fr', 'paris')
    map.printCityCoordinates('uk', 'london')
  3. The code will output the coordinates for Paris and London:
    [[[48.856929779052734, 2.3412001132965088]]]
    [[[51.506320953369141, -0.12714000046253204]]]
    

How it works...

The RESTClient class greatly simplifies dealing with REST resources. It leverages the automatic content type parsing and encoding, which essentially parses the response for us and converts it into the proper type. The get method accepts a Map of arguments, including the actual path to the resource, the request content type, query, and headers. For a full list of arguments, refer to the Javadoc at http://groovy.codehaus.org/modules/http-builder/apidocs/groovyx/net/http/HTTPBuilder.RequestConfigDelegate.html#setPropertiesFromMap(java.util.Map).

In the previous example, the response is automatically parsed and transformed into a nested data structure, which makes dealing with the response values a very simple affair.

By default, all request methods return an HttpResponseDecorator instance, which provides convenient access to the response headers and the parsed response body. The response body is parsed based on the content type. HTTPBuilder's default response handlers function in the same way: the response data is parsed (or buffered in the case of a binary or text response) and returned from the request method. The response either carries no data, or it is expected to be parsable and transformed into some object, which is always accessible through the getData() method.

The actual data returned by the service looks like the following code snippet:

{
  "authenticationResultCode": "ValidCredentials",
  "brandLogoUri": "...",
  "copyright": "...",
  "resourceSets": [
    {
      "estimatedTotal": 1,
      "resources": [
        {
          "name": "Paris, Paris, France",
          "point": {
            "type": "Point",
            "coordinates": [
              48.856929779053,
              2.3412001132965
            ]
          },
          ...
        }
      ]
    }
  ],
  "statusCode": 200,
  "statusDescription": "OK",
  "traceId": "..."
}
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.220.53.93