(or The Reason the Internet Was Invented, or Cat Pictures for the Win)
In this article, 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.
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/). Each supports HTTP GET requests only.
NOTE | 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.
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 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:
String key = new File('flickr_key.txt').text
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:
String endPoint = 'https://api.flickr.com/services/rest?'
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.
def params = [method: 'flickr.photos.search', api_key: key,
format: 'json', tags: 'cat', nojsoncallback: 1,
media: 'photos', per_page: 6]
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. Thecollect
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:
def qs = params.collect { k,v -> "$k=$v" }.join('&')
The two-argument closure takes each key/value pair and returns a string where the key equals the value. Then thejoin
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.
File f = new File('cats.json')
if (f) f.delete()
f << jsonTxt
println JsonOutput.prettyPrint(jsonTxt)
Here's a sample from that output.
{
"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"
}
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.
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"
}
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.
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()))
}
}
}
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 aGridLayout
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:
NOTE | Don't ask me about the monkey. I have no idea what that's about either. |
So what have we learned?
join
methodThe entire script from this article is part of a GitHub repository called IntroGroovy
. 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 re-implement the whole thing in <a href=”http://lolcode.org”>LOLCODE</a>.
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.
Respectfully submitted by Ken Kousen <[email protected]>, who teaches this stuff
Accelebrate offers private Groovy training for groups.
Written by Ken Kousen
Our live, instructor-led lectures are far more effective than pre-recorded classes
If your team is not 100% satisfied with your training, we do what's necessary to make it right
Whether you are at home or in the office, we make learning interactive and engaging
We accept check, ACH/EFT, major credit cards, and most purchase orders
Alabama
Birmingham
Huntsville
Montgomery
Alaska
Anchorage
Arizona
Phoenix
Tucson
Arkansas
Fayetteville
Little Rock
California
Los Angeles
Oakland
Orange County
Sacramento
San Diego
San Francisco
San Jose
Colorado
Boulder
Colorado Springs
Denver
Connecticut
Hartford
DC
Washington
Florida
Fort Lauderdale
Jacksonville
Miami
Orlando
Tampa
Georgia
Atlanta
Augusta
Savannah
Hawaii
Honolulu
Idaho
Boise
Illinois
Chicago
Indiana
Indianapolis
Iowa
Cedar Rapids
Des Moines
Kansas
Wichita
Kentucky
Lexington
Louisville
Louisiana
New Orleans
Maine
Portland
Maryland
Annapolis
Baltimore
Frederick
Hagerstown
Massachusetts
Boston
Cambridge
Springfield
Michigan
Ann Arbor
Detroit
Grand Rapids
Minnesota
Minneapolis
Saint Paul
Mississippi
Jackson
Missouri
Kansas City
St. Louis
Nebraska
Lincoln
Omaha
Nevada
Las Vegas
Reno
New Jersey
Princeton
New Mexico
Albuquerque
New York
Albany
Buffalo
New York City
White Plains
North Carolina
Charlotte
Durham
Raleigh
Ohio
Akron
Canton
Cincinnati
Cleveland
Columbus
Dayton
Oklahoma
Oklahoma City
Tulsa
Oregon
Portland
Pennsylvania
Philadelphia
Pittsburgh
Rhode Island
Providence
South Carolina
Charleston
Columbia
Greenville
Tennessee
Knoxville
Memphis
Nashville
Texas
Austin
Dallas
El Paso
Houston
San Antonio
Utah
Salt Lake City
Virginia
Alexandria
Arlington
Norfolk
Richmond
Washington
Seattle
Tacoma
West Virginia
Charleston
Wisconsin
Madison
Milwaukee
Alberta
Calgary
Edmonton
British Columbia
Vancouver
Manitoba
Winnipeg
Nova Scotia
Halifax
Ontario
Ottawa
Toronto
Quebec
Montreal
Puerto Rico
San Juan