Tales from the jar side: A Spring bean CommandLineRunner, the COVID booster shot, and a Chess story
Dad joke of the week: What do you get when you cross a chicken with a fox? A fox.
Welcome, jarheads, to Tales from the jar side, the Kousen IT newsletter, for the week of October 10 - 17, 2021. This week I taught a Functional Java course on the O’Reilly Learning Platform and a Spring MVC virtual workshop for the No Fluff, Just Stuff conference tour.
If you wish to become a jarhead by actually subscribing to this (free!) newsletter, please use this button:
A Spring Bean CommandLineRunner
Since this newsletter is supposed to be Java-related (it even has the word jar in its title), let me bring up an interesting technical topic this week. Often when I create a new Spring application from scratch (like in my Spring MVC course this week), I start with the the data access layer. That’s because if I create a domain class or classes, I can use Spring Data JPA to generate the entire DAO (data access object) layer for me just by extending a couple of interfaces.
For example, in my Spring MVC course I often start with a simple class called Product, with defines an id, a name, and a price:
The annotations map this to a database table and validate that each instance has to have a name and a price greater than or equal to zero. With Spring Data, I can then add a ProductRepository as a one-liner:
Seriously, that’s the whole implementation. Spring Data will generate about a dozen methods from that, ranging from save(Product) to findById(Integer) to deleteAllInBatch. Pretty sweet.
Since at this point I’m letting Hibernate generate my database schema for me (in a Spring Boot app, Hibernate defaults to create-drop mode, which means it generates the database on startup and drops it on shutdown), I need some initial data to play with.
That’s where the CommandLineRunner interface in Spring can help. If you make a class that implements CommandLineRunner, its run method will be executed when you start the application. As the relevant section in the Spring Boot documentation says,
This contract is well suited for tasks that should run after the application startup but before it starts accepting traffic.
Therefore, I usually add a Spring Bean called AppInit which implements that interface:
This class is annotated with @Component, both so I can autowire in my ProductService, and so it is detected on a component scan. I’m delegating to a service because ProductService is transactional, and anything that modifies the database should be done inside a transaction.
(As a side note, the @Profile annotation is used to indicate this bean should be loaded unless we’re in test mode, where I have a separate mechanism for creating a test database.)
So far so good. This works as is, but you might notice that the CommandLineRunner interface only has a single abstract method, called run, which takes a vararg list of strings and returns nothing. That means you can implement CommandLineRunner using a lambda expression inside a Spring configuration file.
When Spring Boot generates an application, it creates a class that it annotates with @SpringBootApplication. That annotation in turn includes @SpringConfiguration, which is just @Configuration with a different name. That means you can add methods annotated with @Bean and those methods will be treated as a Java way to add beans to Spring’s application context. Even more, you can autowire other beans into @Bean methods as arguments.
That’s a long way of saying I can replace that entire AppInit class with the following initialize method added to the root ShoppingApplication class, as shown here:
I could even drop the String… part of that lambda and just leave it as args, but I like that this reminds the reader of the input arguments, even though they’re not being used here. I go back and forth on that decision, though, depending on my mood.
Personally, I think that’s pretty cool, and it makes for a nice demo in class. It doesn’t change the behavior at all, but most Spring developers are unaccustomed to seeing a lambda as a return value, so it’s a nice illustration of that, too.
For the record, here’s the initializeDatabase method in my ProductService:
At UberConf, that led to a brief discussion about oblong American footballs as opposed to those weird round balls with spots on them that the rest of the world uses and aren’t allowed to touch for some bizarre reason.
One of the students pointed out that in American football they spend more time talking about playing than actually playing (a perfect example of American culture — brief moments of chaos surrounded by committee meetings and legal debates about the rules), and I honestly have no defense for that.
I had to admit that for me, this is an old wound dating back to college. I remember multiple times trying to round up some guys to play touch football, and after twisting arms to get as many as six guys together, we’d start practicing and then be driven off the field by about 30 international students who wanted to play this weird game involving a round ball with spots on it. That happened all the freakin’ time.
Finally, I should mention that despite being small and making up for it by being slow, I was a half-decent intramural quarterback. When I was growing up, my backyard had a few dozen trees, and I got really good throwing a football and hitting them from a fair distance away. When I played quarterback, my receivers often wondered why all my pass patterns required them to go to a spot and just stand there, and now you know the real reason.
I was going to make a segue to the next section about sports having boosters just as vaccines do, but that gag is too bad even for me.
COVID, this body ain’t big enough for both of us
I got my first COVID vaccine back in March (yay), so when the booster shots became available I wasn’t going to hesitate. The vaccine portal in Connecticut says:
Third doses of COVID-19 vaccines are now available [to] individuals who received either the Pfizer or Moderna vaccine and have moderately to severely compromised immune systems.
I’m a Pfizer guy, but what constitutes “moderately to severely compromised immune systems”? The CDC has a whole list of “underlying medical conditions” ranging from cancer to dementia to mental health disorders. One of the included conditions, however, is overweight and obesity (defined as a body-mass index over 25 kg/m2). If you know anything about Americans, you can probably just round up and say that includes pretty much all of us.
I therefore signed up, filled out the paperwork, got the shot, and waited for the side effects. As I tweeted at the time:
I was able to update that today.
My body: Thank you kindly, sheriff.
Vaccine: Twern’t nuthin, and if any of them thar COVID virii varmints cause you any more troubles, just give us a holler and we’ll run ’em out of town.
My body: My hero! (swoons, or naps, whatever)
People In Space
One of the demos I show frequently in my coding classes is to access the restful web services provided by Open Notify. One of them shows the number of people currently in space. It’s called, naturally enough, Number of People in Space, and can be accessed at the linked URL.
I keep meaning to mention that some time ago, an Irish developer named John O’Reilly saw me use that example once and built a huge, powerful, multi-platform app around it. His code is located at the PeopleInSpace repository on GitHub.
I have say, though, that him giving me credit for inspiring his app is a bit like Michelangelo saying to me, “Hey, I saw you run a paint roller across your ceiling, and that inspired me to paint the Sistine Chapel.
In other words, he’s being very kind, but yeah, no. I mean, I’m happy to have been the first person to show him that link, because it’s free and doesn’t require registration and seems to be always available, but let’s be clear about this. My demo involves about half a dozen lines of code. His uses Android’s Jetpack Compose capability, runs on a watch (both Android and iOS), or on a Mac, or even on the web. It’s got images and maps and everything.
I was going to include some images here, but he’s got a bunch of them in the README at the repository, and they’re about as gorgeous as you’d expect, so just look there.
Oh, what the heck, here’s one from his page (using Jetpack Compose on Android):
What brought this up this week? China launched three astronauts to their Tiangong space station, currently under construction, so the number of people in space is now 10, rather than just the seven aboard the ISS. I presume that one of the lessor-known objectives of their mission was to remind me to mention John’s app in this newsletter, which I’ve been meaning to do for some time anyway, so that’s at least one goal accomplished.
A Chess Story
I’ve been saving this story for a newsletter that had room (barely) and here it is. I have a good friend named Jim Harmon, who taught me a lot about Android development. (Here’s his LinkedIn page.) I originally met him on the No Fluff, Just Stuff tour, where he gave several Android-related talks.
Jim is one of my chess playing friends who I meet periodically on lichess.org for a game or two. He’s much better than I am, but only if he has enough time to think. If I can get him into faster time controls, I’m much more competitive.
Anyway, Jim recently played in a over-the-board (as opposed to online) tournament, and he beat at player rated over 2000 for the first time. It was a beautiful game, but that’s not the funny part. The funny part is that after the game, the tournament director got everybody’s attention before the next round and said, “I’d like to congratulate Jim Harmon…”
(Jim was surprised by this, but never expected the rest of the sentence.)
“… for his daughter Beth’s victory over Borgov in the Russian Invitational.”
I’ve known Jim for years, and of course we both watched the whole Queen’s Gambit series on Netflix, but until that moment it never occurred to me that he had the same last name as the hero. I can just imagine the slow chuckle that rolled across the room as they players got the joke.
BTW, if you want to see World Champion Magnus Carlsen break down that game, see this YouTube video.
As a reminder, you can see all my upcoming training courses on the O’Reilly Learning Platform here and all the upcoming NFJS Virtual Workshops here.
Last week:
Functional Java, on the O’Reilly Learning Platform
Spring MVC, an NFJS Virtual Workshop
This week:
Reactive Spring and Spring Boot, on the O’Reilly Learning Platform
Gradle Concepts and Best Practices, an NFJS Virtual Workshop