How many lines of Java?


You need to open a web connection to some site and post some binary data from a local file. You need to validate that the site returns data that matches byte for byte the contents of another file stored on your hard drive. You need to return pass or fail depending on whether or not the data matched. Sounds simple enough, right? I’m setting my stop watch… you have 10 minutes to scroll to the comment section below and code the logic in Java… Ready? Go!

What does it look like? (Did you hit the submit button when you were done?) Did you get it right on the first go? No, we don’t have a back-end compiler and test engine on this site so you wouldn’t get a green bar when you hit submit. The point here is to find the bug. You got a bug somewhere in that logic! First ask yourself, what’s it doing with the streams? Are you closing them all properly or leaving them to Roc, the garbage collector? Did you side step all of the try/catch ugliness with the big oogly try/catch generic Exception that squelches your NullPointer issues? That’s a big bug, believe it or not, because it hides the real problems for you and sends you on wild goose chases. (Who chases wild geese anywayz? What happens when you catch one? Is there a prize? Do you become a wild goose in turn with other hungry savages chasing your tail wielding fork and knife?)

The other point is why bother? Look at the code. I bet there’s a lot of bloat, unless you’re reaching out to some 3rd party API or framework. If you are then you get an F for cheating cuz you can’t submit binary jar includes in the comment section which means you stuff won’t run anyway. Here’s a breif snip of the very same requirement using Groovy:

def runTest(url, reqMethod, requestBinFile, responseBinFile) {
    def con = url.openConnection()
    con.requestMethod = reqMethod
    con.doOutput = true
    requestBinFile.withInputStream { input ->
        con.outputStream.withStream { output -> output << input }
    }
    assert HttpURLConnection.HTTP_OK == con.responseCode
    responseBinFile.withInputStream { input-> input.eachByte {theByte -> assert theByte == con.inputStream.read().byteValue()} }
    con.inputStream.close()
}
    try { runTest(new URL("http://myremotesite.com"), "POST", new File(resourceDir, "typicalRequest.bin"), new File(resourceDir, "expectedResponse.bin")) }
    catch(AssertionError e) { return "fail: $e"}
    finally { println "Done!" }
    return "pass"

While there is a dangling close on the input stream the entire thing could be written without explicitly calling to close anything. The magic comes from the callback pattern as you’ll see in this walk through.

But that’s not Java!
Look again. We are using standard Java API objects URL and File.
new URL("http://myremotesite.com")
new File(resourceDir, "typicalRequest.bin")

We just didn’t have to import them. Our variables are untyped and we dropped semi colons because it’s unnecessary.
def con = url.openConnection()
All of our get/set methods become accessible using properties syntax. We also have auxiliary helper methods, more on that below.

Decorated Objects
Groovy comes as the Amaretto creamer in your cup of Java. It decorates standard Java objects with additional capabilities. For example, there’s an execute method added to java.lang.String that turns any string into an instant command line. You can do stuff like:
"cmd /c explorer C:\\myscreenshot.png".execute()
to open up an image on your hard drive. They’ve also added goodies like plus(int days) to the java.sql.Date object. All of the stuff you would normally break out into a util component has been tucked neatly inside the Groovy enhanced Java API.

New Style
If you’re still for looping and switch casing your way through development you need to get with the program. There’s a new style of programming and either ya’ with it or yer’ slackin’! My example shows off the power of closures and call backs. Let’s talk about what they are and the things they bring to the table. Typical programming requires iteration which results in the loop. In tasks like the example above you need to acquire some resource iterate and dispose of the resource. Since Java uses checked exceptions in a lot of it’s low level API calls you’re forced to deal with them at every turn. The actual thing you are trying to accomplish gets lost in a flurry of noise code dealing with the state of indexes or counters, loop constructs and exception handling. With the callback pattern (which is also possible in pure Java) the iteration, state management, and exception handling is dealt with by some object that you call. This object calls back the code that invoked it on each step of iteration. (You can use callbacks for more than just iteration.) You write logic that looks like so:
networkThingIterator.iterateNetworkThings(this);
instead of:

Connection con = null;
try{
   con = networkThing.connectToNetwork();
   int count = con.getCountOfThingsToDealWith();
}
catch(NetworkException e) { /*I dunno what to do here, I never do so...*/}
for(int i = 0; i < count; i++){
   try{ networkThing.doNetworkStuffWith(localVariable); }
   catch(NetWorkException e) {/*I dunno what to do here, I never do so...*/}
}
finally {
   if(null!=con) try{con.close();} catch(Exception e) {/*Ooooh... I'm squelching!!!*/}
}

We do this in plain old Java but we have to implement an interface which many would inline turning the above example to:
networkThingIterator.iterateNetworkThings(new NetworkThingHandler() {
public void handleNetworkThing(NetworkFooBar foo) {
//The innards of your for loop goes here!
}
});

Not too bad but there’s a little bit of noise here. The syntax of Anonymous inner classes mandates you write an entire class definition where all you really want to write is the method to handle the iteration.

Enter closures
With closures you write what looks, works, and smells like a method but can be grabbed hold of like an object. It removes the cruft of anonymous inner classes and adds the ability to pass a method or an action, or a thing to do (i.e. verb) to an object that does callbacks. Our above networkThing iteration would look like:
networkThingIterator.eachNetworkThing( {
//handle network thing here
}//End of closure defitnition
);//end of method call

Back to the example
In our initial Groovy snip we see closures being passed to what looks like magic methods added to the OutputStream and File objects. These withStream methods contain callback logic that opens the stream, passes it to the closure, and closes the stream. We also have another piece of magic in the left shift operator [<<] that pipes or reads the contents of an InputStream to an OutputStream. The net result is code that focuses on the real task of connecting to streams without the noise of try to open, catch exception, blibbidy-blobbidy, try to close. Look closer. There’s another call back decorated onto InputStream that performs iteration on eachByte and passes it to the given closure. It’s named eachByte. Self explanatory enough? I’d write more but I’ve become way to verbose on the topic so hit me up with any finer details or points of interest.

4 thoughts on “How many lines of Java?

  1. I really love all the added methods like eachByte. Do you like this though?

    input.eachByte {theByte -> assert theByte == con.inputStream.read().byteValue()}

    I’m not comfortable using exceptions for control flow. Are you? On the other hand I don’t see a way of doing this as you can’t break out of a closure.

  2. I don’t see it as control flow handling. Instead it expresses high level intent. I assert that each byte read from the actual stream is equal to each byte from the expected stream. So looking at the entire statement as an expression you could almost say assertStreamsEqual expectedStream, actualStream. I don’t advocate breaks from closures though there was a lot of discussion o nthe topic about a year or so ago on the mailing lists, I think the idea is insane. Use a closure as a closure and not a turbo-charged for loop or such.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s