Upcoming Events, and “The Streak”

I’m really not a workaholic. I prefer days off as much as anybody. The problem is that there are all these things I want to do, so I volunteer to do them, and suddenly I’m overbooked so much I don’t have time for a break.

I think part of it comes down to an acronym that’s making the rounds these days. It’s called FOMO, and stands for Fear Of Missing Out. I suffer from it as much as anybody, I guess. I’ll need to work on that.

At any rate, I’m beginning a particularly busy part of my calendar, and I thought I’d mention it here in case I have the opportunity to meet any of you along the way.

On Tuesday, May 26, I’m giving my Groovy Vampires talk at the Austin Java Users Group. I really have a lot of fun with that talk. I plan to update it a bit, especially because a recording of the version I gave at last year’s SpringOne 2GX conference is currently available on InfoQ.

To give you a clue what it’s about, one day I was wandering in a Barnes and Noble and noticed that there was only one book shelf labeled “Computer”:

ComputerBooks

while there were three (yes, three) labeled “Teen Paranormal Romance”:

TeenParanormalRomance

Instead of lamenting the decline of western civilization, I decided that what this meant was that I needed to add some Groovy vampires to my book. The talk is based on that, and involves accessing RESTful web services, parsing JSON data, using a MongoDB database, creating a RESTful service using ratpack and Grails, and more.

The next day, May 27, I’ll be speaking at the Austin Groovy and Grails Users Group, this time on Testing Grails. While the bulk of the talk was created using Grails 2.3 and works under 2.4, I do plan to say a few words about Grails 3.0 as well. The testing mechanisms haven’t changed much in going from 2.3 to 2.4 to 3.0, though now they’ve added Geb as an included dependency, so you can make functional tests easily.

If you’re in the Austin, TX area this week, please drop by and say hi.

Also this week, starting tomorrow I’ll be hanging out at JavaRanch, because my Groovy Fundamentals video course will be featured in the Groovy forum this week. I’ve always been a fan of the ranch. I first joined way back in the late 90’s, when I was getting Java certified for the first time.

Speaking of the Groovy Fundamentals video (did I really need to link to that again? Yes. Yes I did), that’s the first of three Groovy video courses I recorded for O’Reilly recently. It covers the basics, from POGOs to collections to closures, in almost exactly four hours.

The second video course in the series is called “Practical Groovy”, and covers topics like integrating Java and Groovy, runtime metaprogramming, using AST transformations, the Groovy SQL class, and more. That one ought to go live within a week.

The third video in the series is called “Mastering Groovy”. It covers Spock testing (though I use Spock tests in the earlier videos), working with Spring, JPA, and NoSQL databases, functional programming, traits, and RESTful web services, among other topics. That one will go live when I finally finish reviewing all the video segments. It’s rather dismaying to discover that reviewing six hours of video takes at least six hours.

Though I must admit I’m tired of watching and listening to myself, I’m very proud of these videos and hope they’ll be helpful. I used to joke about selling the movie rights to Making Java Groovy, and speculate about who would I would recommend to play me.

(Best suggestion: Vincent D’Onofrio from his Men In Black days; most definitely not his Kingpin days.)

In essence, these video courses are that movie. They capture pretty much everything I’ve learned about Groovy over the years, condensed to an easily digestible form. If you’ve ever seen me give Groovy talks at No Fluff, Just Stuff conferences, you’ve seen a lot of what I’ve included, though with fewer jokes.

That brings me to next weekend, which is the Dallas NFJS event. I’ll be giving a Spock talk, and my “Managing Your Manager” talk, and a series on Android development. Again, if you’re in the neighborhood, please drop by and say hi.

Incidentally, some time this week (tentatively Wednesday, 5/27), Peter Ledbrook, Baruch Sadogursky, and I are planning to do another Groovy Podcast. I love doing those, so assuming that happens I’ll definitely tweet about it.

From Dallas I’m off to San Diego, where I’ll be teaching a (private) Groovy and Grails class. Teaching technical training classes is What I Do, practically my raison d’être, so feel free to contact me for details.

After the Grails class I’m heading to Sebastopol, CA, home of O’Reilly, to get back into the recording studio again. This time I’m working on a couple of Android videos, and if I manage to finish those I’ll also try to record something on Gradle for Android. That will all be the same week that culminates in the Gradle Summit in Santa Clara, where I’m doing an updated talk on the Gradle plugin for Android. I’m really looking forward to that conference, though I may miss the first day if we’re still recording.

(Yes, I’m making progress on the Gradle for Android book. Yes, it would be a lot easier if the Android plugin for Gradle, Android Studio, and even Android itself stopped changing so much so frequently, causing me to have to constantly rewrite chapters. Yes, the video course will be related, and will help me write the book. Yes, I’ll probably scowl if you ask me for an actual release date, but don’t let that stop you.)

When the Gradle Summit ends, I finally get to go home again, at least for a few hours, before I’m headed to South Carolina for another training class. I might have another one after that, too, but I haven’t decided.

Eventually I’m going to need a break, so it’s a good thing I scheduled one. Next year (!) my wife and I decided to go on the JoCo Cruise in the Caribbean, which is a sweet nerd cruise featuring Jonathan Coulton, Wil Wheaton, Paul and Storm, and many others. That really ought to be fun.

Finally, I need to say something about “The Streak”. Like many people in the I.T. field, I was a career changer. I came from engineering. More accurately, I should say that I was a research scientist, specializing in the field of turbomachinery aeroacoustics. What that really meant was I did lots and lots of math and wrote lots and lots of Fortran (the nightmares have ended, but it took a while). Ultimately I joined an AI group, went back to school at night, got my MS in CS and decided to leave my job.

My new job as a technical trainer started May 31, 2000. That day I helped teach a training course in Object Oriented Concepts (remember when did stuff like that?). I spent five years teaching classes (including roughly one Intro Java course a month back then) before I went out on my own in March of 2005.

We’re coming up on May 31, 2015, and in all that time, I have never missed a day of training. Not one. I call that The Streak, and since it looks like I’m going to make it to that date I figured it was okay to announce it here.

That journey, and the life changes that accompanied and preceded it, deserve their own blog post. I didn’t want the date to pass, though, without mentioning it. I’m rather inordinately proud of The Streak. Some of it is certainly luck, and it can’t last forever, but it means a lot to me. Right now my job and my career are everything I ever dreamed they could be, and I think The Streak is a side-effect. At the very least, it always gets me up in the morning. 🙂

Concurrent Kitties Using GPars

On today’s Groovy Podcast, I mentioned that I was teaching a Groovy training class this week at Research Now in Plano, TX. That’s not how I said it, though. I said that I was broadcasting live in front of a studio audience and that they were the most amazingly awesome group I’ve ever encountered.

(Yeah, okay, sometimes I shamelessly pander for good evals. I’ll let you know if it worked after the class ends. Unless it doesn’t, in which case I probably won’t.)

During the podcast, I told my inestimable co-host, Peter Ledbrook, that we got a chance to use GPars in class. The app we used it on was all about the primary goal of the internet, which is to display cat pictures.

Peter then shamed me into writing a blog post about it, which you’re reading now.

I’ve actually written about this app before, for another client. My post there was originally entitled, “The Reason The Internet Was Invented, Or Cat Pictures FTW”, but the host changed it to the far more mundane Calling RESTful Services in Groovy.

The basic idea is that Flickr (remember them? Me neither) has a RESTful API that lets you search for photos. The “flickr.photos.search” request doesn’t require authentication, but does require a whole set of query parameters, including an API key.

Funny story: in order to get a Flickr API key, you actually have to register at Yahoo! Remember them, too? Yeah, neither did I.

At any rate, I registered and got my key, so I can now do the searches. Here’s the start of my Groovy script to do it:

import groovy.json.*

String key = new File('flickr_key.txt').text
String endPoint = 'https://api.flickr.com/services/rest?'
def params = [method        : 'flickr.photos.search',
              api_key       : key,
              format        : 'json',
              tags          : 'kitty',
              nojsoncallback: 1,
              media         : 'photos',
              per_page      : 6]

// Build URL and download JSON data
String qs = params.collect { it }.join('&')
String jsonTxt = "$endPoint$qs".toURL().text

The query string is constructed from the map of params by running a collect on each element (which returns key=value for each Map.Entry) and then joining the resulting list with an ampersand. Notice the tags key was assigned to the word “kitty”.

The next part of my script writes out the results and appends them to a file.

// write formatted JSON data to file
File f = new File('cats.json')
if (f) f.delete()
f << JsonOutput.prettyPrint(jsonTxt)
println JsonOutput.prettyPrint(jsonTxt)

Here’s a sample formatted JSON response:

{
    "photos": {
        "page": 1,
        "pages": 127979,
        "perpage": 6,
        "total": "767873",
        "photo": [
            {
                "id": "17418175405",
                "owner": "31469819@N02",
                "secret": "9055856685",
                "server": "5453",
                "farm": 6,
                "title": "A Ghostly Cat",
                "ispublic": 1,
                "isfriend": 0,
                "isfamily": 0
            },
            {
                "id": "16795470464",
                "owner": "95966544@N07",
                "secret": "cc4af0d44f",
                "server": "8799",
                "farm": 9,
                "title": "Looking for a home",
                "ispublic": 1,
                "isfriend": 0,
                "isfamily": 0
            },
            {
                "id": "17228164988",
                "owner": "92936362@N06",
                "secret": "d42c68bbf3",
                "server": "8734",
                "farm": 9,
                "title": "peaches the cat",
                "ispublic": 1,
                "isfriend": 0,
                "isfamily": 0
            },
            {
                "id": "17208304157",
                "owner": "102705402@N02",
                "secret": "582fff8f44",
                "server": "8688",
                "farm": 9,
                "title": "This is the sweetest cat in the world!",
                "ispublic": 1,
                "isfriend": 0,
                "isfamily": 0
            },
            {
                "id": "17228717179",
                "owner": "37561081@N07",
                "secret": "eb8d0119fe",
                "server": "7722",
                "farm": 8,
                "title": "\u65e9\u5b89",
                "ispublic": 1,
                "isfriend": 0,
                "isfamily": 0
            },
            {
                "id": "17388635206",
                "owner": "127041099@N08",
                "secret": "6310c6012a",
                "server": "7745",
                "farm": 8,
                "title": "Tsim Tung Brother Cream (\u5c16\u6771\u5fcc\u5ec9\u54e5)",
                "ispublic": 1,
                "isfriend": 0,
                "isfamily": 0
            }
        ]
    },
    "stat": "ok"
}

Note that nowhere in the various photo elements do you find a URL for the actual image. It turns out that to assemble the image you have to plug various pieces of the photo elements into a string, which is something Groovy is good at. First, however, I have to parse this and grab the photo elements:

// parse JSON data and build URL for pictures
def json = new JsonSlurper().parseText(jsonTxt)
def photos = json.photos.photo

The photos variable is now a list of maps for each photo, which I can transform into URLs using a collect:

def images = photos.collect { p ->
    String url =
        "http://farm${p.farm}.staticflickr.com/${p.server}/${p.id}_${p.secret}.jpg"
    url.toURL().bytes
}

The Groovy string uses the farm, server, id, and secret elements of the response in each photo and builds a complete URL for the JPG image. Then I convert that to an actual URL and call getBytes() to return byte arrays.

I can then use a SwingBuilder to assemble a trivial GUI showing all the images:

// build UI using Swing
new SwingBuilder().edt {
    frame(title: 'Cat pictures', visible: true, pack: true,
            defaultCloseOperation: WC.EXIT_ON_CLOSE,
            layout: new GridLayout(0, 2, 2, 2)) {
        images.each {
            label(icon: new ImageIcon(it))
        }
    }
}

That requires some additional imports:

import groovy.swing.SwingBuilder

import java.awt.GridLayout
import javax.swing.ImageIcon
import javax.swing.WindowConstants as WC  // Ooh, aliased imports

Here’s where we improved the system using GPars. The download of the images can be done in a multithreaded fashion by adding a GParsPool:

import static groovyx.gpars.GParsPool.*

// ...

def images = []
withPool {
    images = photos.collectParallel { p ->
        String url =
                "http://farm${p.farm}.staticflickr.com/${p.server}/${p.id}_${p.secret}.jpg"
        url.toURL().bytes
    }
}

// ...

That uses the default pool size, which is the number of processors you have plus one. The images are now downloaded concurrently as part of transforming the photo elements into byte arrays using collectParallel.

Here’s the whole script together:

import static groovyx.gpars.GParsPool.*

import groovy.json.*
import groovy.swing.SwingBuilder

import java.awt.GridLayout
import javax.swing.ImageIcon
import javax.swing.WindowConstants as WC

String key = new File('flickr_key.txt').text
String endPoint = 'https://api.flickr.com/services/rest?'
def params = [method        : 'flickr.photos.search',
              api_key       : key,
              format        : 'json',
              tags          : 'kitty',
              nojsoncallback: 1,
              media         : 'photos',
              per_page      : 6]

// Build URL and download JSON data
String qs = params.collect { it }.join('&')
String jsonTxt = "$endPoint$qs".toURL().text

// write formatted JSON data to file
File f = new File('cats.json')
if (f) f.delete()
f << JsonOutput.prettyPrint(jsonTxt)
println JsonOutput.prettyPrint(jsonTxt)

// parse JSON data and build URL for pictures
def json = new JsonSlurper().parseText(jsonTxt)
def photos = json.photos.photo

def images = []
withPool {
    images = photos.collectParallel { p ->
        String url =
                "http://farm${p.farm}.staticflickr.com/${p.server}/${p.id}_${p.secret}.jpg"
        url.toURL().bytes
    }
}

// build UI using Swing
new SwingBuilder().edt {
    frame(title: 'Cat pictures', visible: true, pack: true,
            defaultCloseOperation: WC.EXIT_ON_CLOSE,
            layout: new GridLayout(0, 2, 2, 2)) {
        images.each {
            label(icon: new ImageIcon(it))
        }
    }
}

Here is the result of a sample run:
Cat-pictures

So there you have it, except for the stupid Flickr key, which I decided to let you register for on your own. Hey, I had to go through that pain, so everybody else does, too.

Well, not everybody. As part of my pandering for evals technique, I did give my key to the students in my class, who no doubt will reward me with stellar evals once we’re done. Probably. It could happen. Either way, at least there were cat pictures, and that’s a Good Thing.

%d bloggers like this: