REST, the OSGi and ECF way

REST, the OSGi and ECF way

A few months ago I introduced you to REST. Since then my Google Summer of Code project, REST abstraction for ECF, has been accepted and a lot of work has been done. Scott Lewis and I wanted to make the use of any REST services as simple as possible and whats simpler for a bundle developer than an OSGi service?

First I want to give  you a little code snippet to see how we access a REST based web services:

IConnectContext context = 
     ConnectContextFactory.createUsernamePasswordConnectContext("user", "password");
container.setConnectContextForAuthentication(context);
remoteService = container.getRemoteService(RestService.class.getName());
try {
     remoteService.callSync(new RestRemoteCall("getUserTimeline"));
     TwitterService service = (TwitterService) remoteService.getProxy();
     IUserTimeline timeline = service.getTimeline();
     IUserStatus[] userStatuses = timeline.getUserStatuses();
     // do something with the userStatuses
} catch (ECFException e) {
// handle exception
}

What have we done? We use an ECF container to get an IRemoteService object which we use to call an IRemoteCall with the method getUserTimeline. After this we access the service’s proxy object which is an instance of TwitterService.

As you surely imagine this snippet has something to do with twitter 😉

Twitter provides its services over a REST based API. The messages you post to twitter are stored in a timeline because every message has its unique timestamp. To access your own timeline you can use the URL: https://twitter.com/statuses/user_timeline.json. But this URL is not defined in the above code snippet. So where do we define this kind of resource? Therefore we can use our own ECF container. So let us define a TwitterContainer which extends RestContainer.

public class TwitterContainer extends RestContainer {
  public TwitterContainer(ID restId) {
  super(restId);
  Map twitterMethods = new HashMap();
    try {
      twitterMethods.put("getUserTimeline", 
        new GetRestCall(new URI("/statuses/user_timeline.json"),
        "ecf.rest.resource.json.org", 
        new Object[]{"count=2"}, null, 10000));
      registerRestService(new String[] { ITwitter.class.getName() }, 
        new TwitterService(), twitterMethods, null);
    } catch (URISyntaxException e) {
       // handle exception
    } catch (ECFException e) {
        // handle exception
    }
  }
}

As you see, we register a REST service with the timeline URL and a String called „getUserTimeline“. This String acts as a key for a specific REST service and will be associated with an IRemoteCall instance. These values are stored in a Map and registered in the container with an instance of TwitterService. TwitterService is a simple POJO which just needs to implement one interface called IRestResponseProcessor. This is needed because the parsed response has to be passed to an service object. With the parsed response, the service object can almost do everything. For example, bringing up an object model for Twitter’s timeline. If we look back to the first snippet, we see that the service is accessed via the key registered in this container. So we can register as many services we want and simply access them with a container instance at any point.

To put it all in a nutshell, we have to register our REST service as a POJO in an ECF container and just call it. This sounds almost like ordinary OSGi Services doesn’t it?

I have pre implemented two scenarios (twitter and google search) which you can check out at the project page.

I would love to hear your feedback so feel free to post comments or post on the ecf-dev mailing list.