The Reason The Internet Was Invented, or, Cat Pictures FTW

I’ll report about the SpringOne2GX conference soon, but I’m fighting a cold at the moment and the medication has put me in a rather bleary state. Thus, the following bit of random Groovy whimsy…

In this post, I’ll use Groovy to access a publicly available RESTful web service, parse the downloaded data, and build a GUI to hold the resulting images. The code will demonstrate the Groovy JDK, maps, the collect method, I/O processing, and the builder pattern, all to achieve its ultimate goal: looking at cat pictures.

A Flickring Light In The Darkness

There are many so-called RESTful web services available to the general public. Despite the name, however, most only support GET requests. This isn’t terribly surprising, since POST, PUT, and DELETE would require some kind of transaction, and security, and all sorts of protection against the sort of damage reminiscent of YouTube comments[1].

Examples of that sort of services include Open Weather Map (http://openweathermap.org/api), Currency Exchange Rates (http://openexchangerates.org), the Bing[2] Maps REST services (http://msdn.microsoft.com/en-us/library/ff701713.aspx), the Google Maps Geocoder (https://developers.google.com/maps/documentation/geocoding/) and the source for this article, Flickr (https://secure.flickr.com/services/developer). Each supports HTTP GET requests only.

If a RESTful web service only supports GET requests, does that make it a GETful service? If so, and it’s also stateless, does that make it a FORGETful web service? Thank you, thank you. Try the veal, and please remember to tip your wait staff.

Believe it or not, Flickr used to be the definitive site for image sharing, and some people still use it. Access requires a key, which means you need to register with Yahoo!, another web site that used to matter long, long ago when the web was shiny and new.

Why use it here? It’s available, it’s free, and, most important of all, it’s got cat pictures.

Feeling Groovy

Groovy is one of the new family of languages that compiles to bytecodes for the Java Virtual Machine. It’s simpler than Java, yet much more powerful, and has an easy learning curve for existing Java developers. It’s cool in its own right, and also forms the basis of interesting projects like Grails and Gradle.

Hey, I even wrote a Java/Groovy integration book about it.

Now on to the Groovy. Let’s assume you register and receive your special key. Save it in a file called flickr_key.txt, so you can access it this way:

[sourcecode language=”groovy”]
String key = new File(‘flickr_key.txt’).text
[/sourcecode]

Accessing a property (like text here) in Groovy is the same as invoking the corresponding getter or setter method. Here, the Groovy JDK adds the getText method to File, which returns the contents of the file.

The base URL for the web service is:

[sourcecode language=”groovy”]
String endPoint = ‘https://api.flickr.com/services/rest?’
[/sourcecode]

I included the “?” because I want to append the generated query string to the end point to get the complete URL.

The Flickr API uses a query string with a lot of parameters. Here I add them to a Groovy map.

[sourcecode language=”groovy”]
def params = [method: ‘flickr.photos.search’, api_key: key,
format: ‘json’, tags: ‘cat’, nojsoncallback: 1,
media: ‘photos’, per_page: 6]
[/sourcecode]

I’m calling the flickr.photos.search method with the api_key. I want JSON data back, but not as a JSON callback, and I want photo data using the cat tag. It’s not terribly complicated, but there are a lot of parameters.

The cool part is that a Groovy map like this can be converted to a query string using a very common idiom. The collect method applied to a map generates a list by applying a closure to each element of the original list. Therefore I can generate the query string thusly:

[sourcecode language=”groovy”]
def qs = params.collect { k,v -> "$k=$v" }.join(‘&’)
[/sourcecode]

The two-argument closure takes each key/value pair and returns a string where the key equals the value. Then the join method applied to the list creates a string whose entries are separated by ampersands.

That means the whole URL is defined by "$endPoint$qs". I can then use the toURL method from the Groovy JDK to convert the string to a URL[3], and the text parameter invokes getText, returning the total response.

I can now use the cool JsonOutput.prettyPrint(txt) method to format the output and write it to a file.

[sourcecode language=”groovy”]
File f = new File(‘cats.json’)
if (f) f.delete()
f << jsonTxt
println JsonOutput.prettyPrint(jsonTxt)
[/sourcecode]

Here’s a sample from that output:

[sourcecode language=”javascript”]
{
"photos": {
"page": 1,
"pages": 882777,
"perpage": 6,
"total": "5296661",
"photo": [
{
"id": "15077663928",
"owner": "125421155@N06",
"secret": "dc605f2671",
"server": "3837",
"farm": 4,
"title": "Mornings with bb kitty",
"ispublic": 1,
"isfriend": 0,
"isfamily": 0
},
{ … },
{ … },
{ … },
{ … },
{ … }
]
},
"stat": "ok"
}
[/sourcecode]

From JSON to Cat Pictures

Each photo block has the components necessary to assemble the URL to retrieve it, which is way more complicated than it needs to be but is still doable. Here’s the code for that part.

[sourcecode language=”groovy”]
def json = new JsonSlurper().parseText(jsonTxt)
def urls = json.photos.photo.collect { p ->
"http://farm${p.farm}.staticflickr.com/${p.server}/${p.id}_${p.secret}.jpg"
}
[/sourcecode]

The JsonSlurper has a parseText method that converts the received JSON string into a Groovy map. Then walking the map by calling json.photos.photo gets all the photo objects, and the collect block converts each of them into a URL.

All that remains is to access all the photo URLs and populate a simple GUI with them. One simple way to do that is to use Groovy’s SwingBuilder class.

[sourcecode language=”groovy”]
new SwingBuilder().edt {
frame(title:’Cat pictures’, visible: true, pack: true,
defaultCloseOperation: WindowConstants.EXIT_ON_CLOSE,
layout:new GridLayout(0, 2)) {
urls[0..5].each { String url ->
label(icon:new ImageIcon(url.toURL()))
}
}
}
[/sourcecode]

The SwingBuilder has an edt method, which builds the UI on the event dispatch thread. The frame “method” instantiates a JFrame with the given title, makes it visible, and packs it as small as possible. The GUI uses a GridLayout to make two columns of equally-spaced elements, each of which is a JLabel that contains an ImageIcon with the individual photo URLs.

The result is a display of the most recent six pictures tagged cat in Flickr, which can result in almost anything[4].

Here’s a sample view:

Cat-pictures

Don’t ask me about the monkey. I have no idea what that’s about either.

So what have we learned?

  1. Groovy maps can be converted to query strings using a closure and the join method
  2. The Groovy JDK adds methods to Java library classes that you wished were there all along
  3. Groovy builders can make Swing programming almost, but not quite, pretty cool
  4. I can haz kitteh pics

The entire script from this article is part of a GitHub repository called IntroGroovy. Drill down to the src/main/groovy/flickr directory. You’ll need to add your own Flickr key, but after that, go for it. Just don’t be surprised, apparently, if you get monkeys or tractors mixed in with your cat pictures.

I suppose now I should go and reimplement the whole script in LOLCODE.


1. Okay, that’s a little harsh. Nothing could be as awful as YouTube comments. Or perhaps the correct response to that is, “I didn’t know YouTube supported comments.” If that’s your answer, I SO wish I was you.
2. Come on, stop laughing. I get it: “If you don’t remember what Bing is, just Google it”. Ha ha.
3. What did you expect toURL to convert the string into, a tomato? That would be pretty cool, actually. Now I wish I had that method. Of course, Groovy is an open source project…​
4. Usually it’s cats, but once I got a bunch of tractors, which confused me until I realized they were manufactured by Caterpillar.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.