Tales from the jar side: Gradle, Spring, Why I can't let go of Android, and Amusing tweets

Sometimes learning means being wrong, but I wish it didn't happen in public

Welcome to Tales from the jar side, the Kousen IT newsletter, for the week of November 15 - 22, 2020. This week I taught the Introduction to Gradle course for Gradle, Inc., and a Reactive Spring and a Kotlin and Spring course on the O’Reilly Learning Platform.


Even though I’ve taught those courses before, this week I learned something new in at least two of them. More to the point, in the Gradle course I discovered that something I’d been teaching for years was wrong, or at least not right.

Gradle Parallel Tests

That requires a bit of an explanation. I’ll summarize it here, but if you’re interested in the details I created a new blog post entitled Simple Demo of Gradle Parallel Tests that shows everything. The “tl;dr” version is that you can use Gradle to run tests in parallel, but when you do that, only test classes run concurrently, not individual tests in those classes.

(For those who might not remember, tl;dr is short for “too long; didn’t read” in Internet speak.)

We finally got around to updating the Introduction to Gradle materials. They asked me to do it a few years ago, but since I’m not an employee of Gradle I don’t feel comfortable giving the “official” answers for how to do things. Finally they assigned a couple people to do the updates and I was able to supply feedback. This week we debuted the new materials, which was, as expected, something of a mixed bag. I’m glad they were updated, and I learned a couple of new things (though the testing issue mentioned above wasn’t supposed to be one of them), but I think we need at least one more round of revisions.

More personally, though, I hate it when I realize I’ve been teaching something that turns out to be wrong. There’s a huge temptation not to admit it, or to minimize it. There’s also a huge temptation to go into a shame spiral and apologize way too much.

Since this isn’t my first time, I know more or less how to handle it. The question came up and I realized I wasn’t sure, so during class we came up with a demo (which my blog post is based on), and that’s when I discovered I was wrong. I said something along the lines of, “Wow, I hope I’ve built up some credibility by now, because that’s not helping,” made sure everybody understood how it actually does work, and went on.

The students were nice enough about it, fortunately. I decided to post something on Facebook, which I use just for friends and family, which went something like this:

Actual conversation I had with my wife:

Me: I realized in class something I'd been teaching for years was actually wrong.
Her (trying to be diplomatic despite not making a significant mistake in the 30+ years I've known her): That can happen to the best of us.
Me (trying to save face, at least somewhat): Yes, now I know that.

We both started laughing at that point, so that's as far as it went.

End of story, other than the follow-up blog post, which I figured was worth it for no other reason than to make it easier for me to remember the right answer.

I really don’t like making mistakes like that, but I have to grudgingly admit it will probably happen again some time. Grr.

Spring Surprise

That was bad enough, but then I wound up with a weird situation in the Spring Framework. I should probably write a blog post about this, too, but I didn’t have time this week. I’ll mention it here, partly for those who might care and partly to remind myself to document this somewhere more permanent soon.

When I talk about using Spring to save and restore persistent data, I often talk about the JdbcTemplate class. That class is useful if you already have the SQL code worked out and you just want to pass it to the database while letting Spring manage the transactions for you.

My regular demo uses a class called Officer and a corresponding table called OFFICERS, and in it I store five captains, by the names of Kirk, Picard, Sisko, Janeway, and Archer. (Yes, I need to update that to include Pike, Georgiou, Saru, and maybe even Freeman. I’ll get to that eventually.) When I try to demonstrate how to find an officer by their ID, what I want to write is something like:

That’s Kotlin code, but the principle works the same way in Java. That is, I want to call the queryForObject method, which would execute the SQL argument with the specified ID and transform the resulting row into an Officer using the officerMapper property I created elsewhere in the class. The documentation for queryForObject says it returns a single mapped object, or null if the row mapper (the officerMapper here) returns null, so I wrap the whole thing in an Optional.ofNullable, figuring that ought to be enough.

It is enough if the ID exists in the database, but if not, this throws an exception. In my regular Spring courses I avoid that exception by adding an initial call to an existsById method, to see if the row is there in the first place, but that means an extra SQL call to the database. The resulting code there looks awkward, or at least not as elegant.

This came up in my Kotlin for Spring class, which is why the above example is in Kotlin, and I promised the students I would figure out why it wasn’t sufficient. What I found was that the queryForObject method throws an exception (to be specific, an IncorrectResultSizeDataAccessException, and yes, Spring loves its overly long class names) if the number of rows in the result set is anything other than one. That’s bad, because if the ID doesn’t correspond to an actual row, this fails with an exception. I’d been assuming it returned a null in that case, but that’s not correct. That means one way to fix the problem would be to write:

That works, and avoids the extra SQL call, but at the cost of making exception handling part of the normal execution path. I’m not sure if I’m wild about that, either. I think in the future I’ll add this as a discussion point and talk to the students about it, rather than saying which way is “right”.

Speaking of trying to do things the “right” way:

Shouldn’t Data Run On Android?

I’m going to talk about Android, which always makes me wonder:

There’s an old story about the Joe Montana, Hall of Fame quarterback of the San Francisco 49ers back in the 1980s, when he was coached by Hall of Fame head coach Bill Walsh. The story goes that at the end of one year, Walsh analyzed every pass Montana had thrown that year and realized that the majority of his interceptions had come on a single play.

The way I expected that story to continue, I thought Walsh would say how they worked and worked on that play in training camp the next year so it eventually became a strength instead of a weakness. That’s not what happened, however. Instead, Walsh removed the play from the playbook. He figured fixing it wasn’t worth the effort.

That brings me to my adventures with Android development over the past few years. I’ve been teaching Android coding for over ten years now, and it’s rarely a pleasant experience. I used to do whole-day workshops on the No Fluff, Just Stuff tour where we built an app from scratch. I even recorded a few videos for O’Reilly, called Basic Android and Practical Android. Though I didn’t have any significant Android apps in production, I felt I was comfortable with it.

Then, back in 2017, the Android team at Google decided to recognize Kotlin as a development language for Android. I wasn’t thrilled about that, since I had been hoping Groovy might have a future there, but so be it. That became my primary reason for learning Kotlin. By 2019, Kotlin was promoted by Google to the primary language for Android development, going so far as to claim “Kotlin first” for any new or updated Android libraries.

I took the time and effort to learn Kotlin, which eventually resulted in my Kotlin Cookbook, which has some Android examples, though not a lot. Android kept changing, though. First they moved to what they called Android Architecture Components, and then they rebranded all those as Android Jetpack. That became the future of Android development.

There are a few major problems, however:

  1. I’ve only had a handful of really bad training classes in my career, but at least two of them were Android classes.

  2. My biggest strength as an instructor, or even as a technical professional, is my ability to reduce complex subjects down to relatively simple, straightforward explanations. In fact, the more I make that into my regular day job, the more successful I am.

  3. Despite being a mature technology, every change made to Android has increased the complexity of Android development, to the point that there are no simple Android applications any more.

This week I took another run at trying to understand how to do Android development the preferred way. I found a video course on LinkedIn Learning called Building an Android App with Jetpack Libraries. The course involved constructing an app for taking notes. You could create them, save them, edit them, and show them in a list. That’s all.

The video course is 2 1/2 hours long. By halfway through I despaired at ever being able to reduce the development process down to something simple enough to do, much less teach. It’s full of things like, “sure, we could do this simple approach, but that has some risks and disadvantages, so instead we’ll replace those two lines of code with thirty more spread over half a dozen files, because that’s better.”

It is better, in some sense. The resulting apps are more robust and powerful. I used to say the cost was that it was no longer simple to do simple things. Now I’m of the opinion that it’s no longer even possible to do simple things.

So what do I do? One option would be to do what Bill Walsh did, and drop Android from my list of technologies. The problem is, by becoming proficient in Kotlin, I’m starting to get real business opportunities to do it and they generally involve Android development.

My attempt this week was to fix that problem by figuring out the process again, and I feel it was a dismal failure. I should give it up.

I’m almost there, but I can’t quite let it go. I keep wondering if I try again, and take it a bit slower and more carefully, I’ll get it. Part of me, however, knows that’s a pipe dream.

Oh hey, I get to teach my Basic Android course on Safari again this week, to a group of students who probably don’t know Kotlin and have no idea about the Jetpack components. That ought to be fun. I’ll be honest about everything with them, but it all makes me so uncomfortable.

More as this situation continues to develop.

A Brief Moment Of Beauty

Here’s a great video from the Covid Cello Project:

There are 278 cellists playing in that video, across 29 countries. The gaps between them are eventually filled in by memorials shared by the players, though not necessarily COVID related. Still, it’s very powerful.

A Few Miscellaneous Tweets

Let me conclude this week with a few tweets.

I phrased that awkwardly, but it really bothered me in The Queen’s Gambit that Mr. Shaibel never got his $10. It’s in character for Beth to never get around to it, but I still found it disappointing. Of course, she did, too.

Don’t let that keep you from watching the series, though. :)

If you’re wondering why I’m a bit late this week:

That resulted in the blog post I mentioned at the top of this newsletter, among other things. And sure enough, the Patriots lost yet again in a game that was exactly the sort Tom Brady used to win. Oh well. Twenty years is a heck of a run, but it’s clearly over now.

(If you didn’t get the reference, see the Wikipedia page on Yak Shaving.)

Also there was this little gem:

which is based on this tweet if you can’t see the picture:

Finally, this was too true:

I think I’ll stop there. I want some brownie points for showing great restraint and not including anything political again. We’ll see how long that lasts, too.

Last week:

  • Introduction to Gradle, for Gradle, Inc.

  • Reactive Spring on the O’Reilly Learning Platform

  • Kotlin and Spring, ditto

This week:

  • Basic Android, on the O’Reilly Learning Platform

  • What’s New In Java, ditto

  • Thanksgiving! That means I promise, promise, promise to get a complete draft of my Managing Your Manager book done. I mean it. For sure. What could go wrong?