Thursday, April 25, 2013

Building a simple java client for forecast.io

I like to be outdoors when life allows so weather is always an interest for me. So i was very pleases to see forecast.io becoming available with global coverage after being jealous of the US only "DarkSkys" app. It was also nice to see that there is a nice REST api for the service which I could play with.

Unfortunately there was only a textual description of service, nothing I could consume with the Java client tools I have been working with. But I though it would be an interesting experiment to try to document an existing service from scratch.

The first thing I did was to get an example of the data that the service would respond with and run it through a JSON->JSON Schema tool. I used JSONSchema.net which gave me a rough v3 JSON Schema; but it wasn't able to take into account elements that are reused. A little bit of hand editing later I ended up with three JSON Schema files, one for the forecast itself and one for a list of weather details and and one for each particular data point.

From there is was pretty simple to read the developer documentation and write up a simple WADL to describe the two resources provided by the service. Luckily Jason LaPort from the DarkSkys was on hand to fix a few mistake and generally verify my description.

Once I had this all in place I of course found a couple of bugs in my own code, so it was time to update and fix wadl.java.net and release a 1.1.5 version with a revised depdency on the jsonschema2pojo project. This is why a little bit of adhoc expert testing pay dividends.

So taking the WADL from github it is possible to generate a nice clean Java API using the wadl.java.net generator. I won't reproduce the steps to generate the client here, but this is the end result and the kind of code you can get out of it.

// Create a Jersey client and setup for POJO JSON mapping

    ClientConfig cc = new DefaultClientConfig();
    cc.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, true);
    Client c = Client.create(cc);


    // Get current weather for location and check for any alerts 
    
    Forecast f = ApiForecastIo_Forecast
        .apikey(c, "xxxxxxx")                  // Get own key from developer.forecast.io
        .latitudeLongitude(51.32d, -1.244d)    // Some location near where I live
           .getAsForecast(
              null,                            // Not JSONP
              Units.SI,                        // Return values in SI units
              "hourly,minutely,daily,flags");  // Just return current weather and any alerts
    
    // Output a summary

    System.out.println(
        f.getCurrently().getSummary() + " " +
        f.getCurrently().getTemperature() + " C");

    // Output any alerts
  
    List<Alert> alerts = f.getAlerts();
    for (Alert altert : alerts) {
        System.out.println(
            altert.getTitle() + " " + altert.getUri());
    }

The nice thing here was just how pleasantly easy describing a service that already exists was, yes I could have written it by hand in Java; but then when I wanted to move to Jersey 2.x I would have to re-write by hand rather that just regenerating from the metadata to a new technology target. (Also did the same for a BBC REST Schedule API, that is in the same git project)

No comments: