(I gotta start thinking of better themes for some of my ramblings! The I’ve already used the “Pipe Dream” thing but nothing else seems to fit sometimes.)
Let me ask you a question. Yes, you, the one with the shifty eyes moving from left to right ingesting mounds of text as you operate your scroll wheel. (“But my mouse doesn’t have a scroll wheel!”, Tough tanoogies! Go buy a mouse with a scroll wheel.) Have you ever seen a stack trace that looks like this:
Caused by: java.io.IOException: Pipe broken at java.io.PipedInputStream.read(PipedInputStream.java:255) at java.io.PipedInputStream.read(PipedInputStream.java:305) at java.io.InputStream.read(InputStream.java:89) at com.gbg.util.io.StreamReader.transferStream(StreamReader.java:50) at com.gbg.util.io.StreamReaderTest$1.run(StreamReaderTest.java:63) ... 1 more
Do you know what that means? I do! And I’m not telling you! It’s my dirty little secret and I’m not letting go of it. While I’ll continue my “I know something you don’t know, nah, nah, nah, nah, nah” rant internally I’ll tell a short story about what I’ve seen in my Java stream handling experience. Java Streams are tricky things just like JDBC connections, Exceptions, and pretty much every other heart attack Java gives you to make life easier, so follow closely.
Once upon a time… (don’t you love when a story starts once upon a time? I hate when people start rattling off the details leaving nothing to the imagination. That’s why I’m starting my story like one of my daughters Cinderella adventures.) there lived a humble Java developer. He needed to connect his RMI programming logic to an RMI server across the network. (Actually the RMI server was on the same machine as his RMI client but his mean old coworkers told him that they would be separating the two brothers in production.) He knew very little about Java RMI and he knew very little about Java streams. It was a deadly combination of ignorance, you might say. Anyway, this Java dude started tapping away on his keyboard in a mad attempt to keep RMI client connected with classes and resources that belonged to his soon to be estranged brother, RMI server. His best attempt was a method that used a loop to examine bytes in an InputStream and write their individual values to bytes on an OutputStream. (You’re probably thinking, “what does any of this have to do with Cinderella!” I’ll get to that part soon, I promise.) He was proud of his loop. He told his co-worker about the loop. The loop became famous as it solidified as the major backbone to the entire project he was working on.
Over the years the loop changed little. There was hardly a need to touch anything. It was finished code. However Mr. Java Dude and his fellow employees noticed a minor hiccup from said loop which caused messages like what I posted above to show in the server logs. First hours, then days, and eventually months were spent by Java guy and coworkers as they occasionly examined the loop and tried to find the flaw. The loop was flawless. It was the one piece of code that couldn’t be broken. Such a small snippet of logic, it was nearly the equivalent of a simple assignement, “x = y”. The development team puzzled for years to come until today, yours truly hath found thine answer! (Excuse the old English, I’ve been doing some heavy Bible reading lately.)
Gather around little children (and all of you shifty-eye text reviewers), Let me show you some magic! You see with magic the trick happens behind the areas that are veiwable. (The rabbit comes from under the colth covered table not from within the hat! Sorry to spoil the magic for you.) In my case the loop was flawless, and the trick was coming from outside of the loop. There is one very important thing you must do with every Stream or Reader or Writer that you create. You must try to close it. (If you know Java then you know what I mean when I say try to close it. If you don’t know Java, pretend that you do until you finish shaking your eyes at your monitor then go pick up a Java book at your local book seller and get with it!) If you don’t then unexpected errors like the “Broken Pipe” thing above can occur and you’ll be stuck wondering why your code is smoking crack.
This is such a fundamental concept in Java that you’re probably wondering why I would waste a page or more of text dramatizing it. That’s because the subtle errors its oversight can cause are truely dramatic. In my case there seemed to be nothing wrong. All of the data was being flushed downstream, nothing was ever missing or incorrectly written from the loop. Then the problem turned up again just days ago in a completely different application that happened to use a clone of the very same loop, tucked into a utility library. Once again, all of the data was correctly written and the error seemed to be a superfluous internal JRE glitch. This time around I was working with savvy components unlike the original loop that had been hard-wired into a complicated servlet that was tucked into a jar loaded ear, deployed on a complex App server environment. This time around, I was able to replicate the problem using unit tests. This time around I was able to find the problem and diagnose it.
So what do I want, a cookie?
A Keebler would be nice, but what is even better is if you all would bow in admiration of my superior Stream error handling prowess. Humble yourself before me while I lash you with the Cat O’ Nine Tails for underestimating my abilities! Actually I want to point out what Java thinks should be ovious but comes at a price to us lesser informed folks. Broken pipes, and write-end closed exceptions originate from foolish minded developers who believe it is the Garbage Collector’s responsibility to close your Readers, Writers, and Streams. That is all. You may now comment.
By the way, I guess I never did tie Cinderella into my little story did I? Well it was her glass slipper that stepped on the pipe causing it to break in the first place. The awkward angle twisted her ankle ever so slightly resulting in her stepping out of her slipper, leaving it on the ballroom staircase. I believe you know the rest of the story from there. Moral: don’t leave your pipes laying around for Cinderella to step on!