Enterprise Integration Zone is brought to you in partnership with:

Jeune has a fascination for building and solving things. His interests include Algorithms, Development Practices and Software Design. When not immersed in his passions, he spends time experimenting in the kitchen. Jose is a DZone MVB and is not an employee of DZone and has posted 10 posts at DZone. You can read more from them at their website. View Full User Profile

5 Improvements To Be Considered If You’re Writing Your Next Custom Web Service Client

03.20.2013
| 1390 views |
  • submit to reddit
Of course the first thing most people would tell you is to look for existing solutions. But even then, there are those times when you need to write your own. Here are just of my reflections on it.

1. Don’t over do encapsulation. Consider the following class:
class SocialMediaAppCaller extends AbstractAppCaller {
      private $uri = 'http://someurl.com';
   public function getSocialMediaAccounts($params) {
      return $this->remoteDispatch('someParam2', 'someParam2', $params);
   }
   public function addSocialMediaAccount($params) {
      return $this->remoteDispatch('someParam3', 'someParam3', $params);
   }
   public function deleteSocialMediaAccount($params) {
      return $this->remoteDispatch('someParam3', 'someParam3', $params);
   }
   public function getPost($params) {
      return $this->remoteDispatch('someParam4', 'someParam4', $params);
   }
}
Here’s another one…
class MagazineAppCaller extends AbstractAppCaller {
   private $uri = 'http://someurl2.com/';
 
   public function addArticle($params) {
      return $this->remoteDispatch('someParam2', 'someParam2', $params);
   }
   public function addSocialMediaAccount($params) {
      return $this->remoteDispatch('someParam3', 'someParam3', $params);
   }
   public function deleteSocialMediaAccount($params) {
      return $this->remoteDispatch('someParam3', 'someParam3', $params);
   }
   public function getPost($params) {
      return $this->remoteDispatch('someParam4', 'someParam4', $params);
   }
}
The first time I saw this, I thought I smelled something fishy. But I thought I’d let it slide and give it the benefit of the doubt. For all I know, it was in anticipation of encapsulating some business logic as in a service. One year later and everything still looks the same.

There was nothing to be encapsulated after all and it begs the question why can’t I just do this?
$response = remoteDispatch('param1', 'param2', $params);

2. Use RESTful methods as a generic interface. All api method calls can be summed up in them one way or another. Applying this to our examples above, the getComments, getSocialMediaAccounts are, as I look at it, can be covered by the GET method. Need make a change on the resource? There’s POST for that. How about if you want to remove something? DELETE.

3. Check if the response is a success or not and take appropriate action if it isn’t. One thing that really got on my nerves after calling the clients above was that it encapsulated the wrong thing and didn’t encapsulate the things I felt that needed to be encapsulated. I think error checking is one of them. Every time I had to make a call, I had to do the following:
if ($response->success === false) {
  // do something or throw an exception
}

Now ain’t that a trip? A bad trip I mean. I think I know what I smelled before. Code Duplication.

4. Work with some assumptions. Now this task is much easier if you were just dealing with one api say, Twitter. If you’re expecting json responses for example (and don’t ever see yourself reading xml responses — now that’s already one assumption), the keys of the error messages will be the standardized, the keys of the resources you are looking for are well defined in the api documentation. But what if you wanted your client to cater to a wide multitude of web services as possible? Different clients will have different keys for different things like the error/success message or the data. My suggestion is to specify these keys in an options data structure (array in PHP, dictionaries in Python, Maps in Java). So for example in one web service you are calling, the error message is in the key “error_message” or in the Twitter API, the key is “error”, they can be specified like so:
$response = $client->get(
   'https://twitter.com/#!/search/%40twitterapi',
    array(
      'error_key' => 'error',
      'data_key'  => 'data'
    )
); 

Appropriate action can be taken if there is the response from twitter has the ‘error’ key in it. Else, return the contents of the ‘data’ key. If the caller does not specify the data and error keys, we can safely assume that whole response from the api is the one desired.

5. Just for convenience and to pretty things a bit, have a way to save the uri of the resource. This can be set initially on creation of the client object…
$client = new RestClient('http://api.myfictionalmagazine.domain/');
$response = $client->get('articles',
   array(
      'error_key' => 'errormsg',
      'data_key' => 'data'
      'category' => 'cars'
   )
);

…or changed during runtime with a mutator/getter.

$client->setUri('http://maps.googleapis.com/maps/api/');
$response = $client->get('directions/json' ,
  array(
     'origin' => 'Boston,MA',
     'destination' => 'Concord,MA',
     'waypoints' => 'Charlestown,MA|Lexington,MA',
     'sensor' => false
  )
);
I got that one example from the Google Maps Api documentation. I think I am going to use that one above as a test case or something.

Published at DZone with permission of Jose Asuncion, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)