Monday, May 12, 2014

Consuming Appnexus API using Java

Introduction to Appnexus 

Appnexus is the leading demand-side and supply-side platform which specializes in RTB. For more information on Appnexus kindly refer to this Wikipedia entry

About Me 

I am working for a media company which specialises in performance trading and most of the campaigns are run through Appnexus apart from other leading AdExchanges. As part of the software platform, we consume Appnexus services using the API provided by Appnexus. In this series of posts I'll show you the technology used and the architecture required to consume Appnexus API. 

Audience 

These posts are targeted at software engineers developing applications which consume Appnexus services using their API or similar third party services. I also assume a fair understanding of Java and related web technologies. 

Restful Web services 

Appnexus exposes all of its services as restful Web services. REST stands for Representational State Transfer, which in short could be put forward as the method of consuming third-party services using HTTP protocol. For more information on REST, please refer to the following Wikipedia entry. 

Consuming Restful Services 

There are a couple of options available for consuming restful services. Namely,
Since using Apache HTTP client is of the most straightforward methods of consuming restful Web services, most of the developers would tend to choose it. On the other hand, a couple of developers might also choose Spring rest template-based implementation in order to consume the services. I would suggest using Square's Retrofit for that purpose. The following paragraphs contain code examples for consuming an example service using each of the above methods, which will help me highlight the differences between each of these methods and also to put forward the fact that Retrofit is better in this specific case. 

Using Apache HTTP Client:

HttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet("http://www.github.com");
HttpResponse response = client.execute(request);

// Get the response
BufferedReader rd = new BufferedReader
  (new InputStreamReader(response.getEntity().getContent()));
    
String line = "";
while ((line = rd.readLine()) != null) {
  textView.append(line); 
} 

Using Spring Rest-template

  HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_JSON);
    headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));

    RestTemplate template = new RestTemplate();

    HttpEntity<String> requestEntity = new HttpEntity<String>(
        RestDataFixture.standardOrderJSON(),headers);

    ResponseEntity<Order> entity = template.postForEntity(
        "http://localhost:8080/aggregators/orders",
        requestEntity, Order.class);

    String path = entity.getHeaders().getLocation().getPath();

    assertEquals(HttpStatus.CREATED, entity.getStatusCode());
    assertTrue(path.startsWith("/aggregators/orders/"));
    Order order = entity.getBody();

Using Retrofit:

public interface GitHubService {
  @GET("/users/{user}/repos")
  List<Repo> listRepos(@Path("user") String user);
}

RestAdapter restAdapter = new RestAdapter.Builder()
    .setEndpoint("https://api.github.com")
    .build();

GitHubService service = restAdapter.create(GitHubService.class);
List<Repo> repos = service.listRepos("octocat");

There is a fundamental difference between each of these three methods. 

1. With Apache HTTP client, the response is received as a string, following which we have two manually deserialize it. Explaining serialization and deserialization is out of the scope of this post, kindly refer to the following Wikipedia entry for more information

2. When Spring Rest-client is used, we get a response object, and which encapsulates the required entity, which we could fetch by invoking a method on the response. Though this method is simple, it is not elegant. If you pay attention to the construction of the client, you could notice that it doesn't really represent what is being consumed.

template.postForEntity("http://localhost:8080/aggregators/orders", requestEntity, Order.class);

The specific line that has been enclosed above does not represent the business in hand, while it is more technical. 

3. Finally, if you take a look at the way the retrofit client has been constructed, the purpose of it is clear. Using the following line

restAdapter.create(GitHubService.class);

an implementation of GitHubService.class is created at run-time, following which we could use GitHubService just like any other services that are defined locally. Once such a client has been declared and instantiated the rest of the application we don't worry about the fact that the services are remote. 

Conclusion 

This is not a post to compare different technologies, because each of these technologies mentioned above have their own place in the technical world. I am suggesting that considering the use case in hand, Retrofit would be a better fit. Since we have seen that we are going to use Retrofit for consuming Appnexus API, the following post I will show you how exactly it could be done. 

Kindly post a comment if you either like it or if you feel the content is inappropriate in some way.

No comments :

Post a Comment