Tales from the jar side: Archives in Gradle (featuring Groovy vs Kotlin), AI Experiments, and More Tweets / Toots / Skeets / Whatever they are on Threads
What do you call a flock of baby sheep rolling down a hill? A lambslide (rimshot)
Welcome, fellow jarheads, to Tales from the jar side, the Kousen IT newsletter, for the week of July 9 - 16, 2023. This week I taught a private Groovy Programming for Java Developers course in the Indian time zone (and I’m still tired), a full-day NFJS virtual workshop called Deep Dive Into Spring, a half-day NFJS virtual workshop on Gradle, and an O’Reilly Learning Platform course on Spring and Spring Boot. A very busy week.
Regular readers of (and listeners to, and now video viewers of) this newsletter are affectionately known as jarheads, and are far more intelligent, sophisticated, and attractive than the average newsletter reader (or listener, or viewer). If you wish to become a jarhead, please subscribe using this button:
As a reminder, when this message is truncated in email, click on the title to open it in a browser tab formatted properly for both the web and mobile.
Zip and Unzip in Gradle
As many of you know, I used to teach the Introduction to the Gradle Build Tool course for Gradle, Inc online every other month. They’ve recently taken that training in-house and restructured it, but I learned an awful lot about Gradle from teaching that beginner course over and over.
One topic that used to be part of the course but became deemphasized over time was how to do basic file manipulation tasks using Gradle. There’s an entire section of the Gradle User Guide called Working With Files, which talks about copying files, creating directories, and more.
One topic I always found interesting and rather counterintuitive is that while there is a built-in task called Zip
for making zip archives, there’s no task called Unzip
. It turns out the way you unzip an existing archive is by using a Copy
task, where the source to copy is the zip file wrapped inside the method called zipTree
.
Here’s an example of creating a zip:
Here, zip is the name of the task, Zip
is the type, from
is a method that takes a directory as an argument, and into
takes a directory as well. This task copies all the files from the src/main/java
and src/main/resources
folders into the zip file. The into
method is a bit misleading. Since the destination is already specified (it’s the zip file itself), the purpose of into
is to create a director inside the zip, called dist, and copy the README file into it.
That’s all using the Groovy DSL, and is slightly suboptimal because it calls out the task explicitly rather than saying tasks.register('zip', Zip)
. As written, the task is configured eagerly, whereas the register approach would be lazy, meaning the task is only configured if it’s called. Personally, I don’t think the difference is significant, because calling the from and into methods really don’t do much, but the Gradle people get very worked up about such things, so I should probably change it.
The corresponding unzip task looks like this:
As mentioned, you use a Copy
task to expand an archive, along with the zipTree
method. This particular example depends on creating a zip first, and then expands it into the build directory in a subdirectory called expanded
.
All well and good. These days, however, Gradle now defaults to using the Kotlin DSL rather than the Groovy DSL, so I feel obligated to show the same tasks in that language. Here’s the zip task:
This time I did go with the register method, because in Kotlin we have what they call reified types (the <Zip> part), meaning Kotlin preserves the data type during compilation, unlike Groovy (or Java, for that matter). Otherwise things look pretty much the same, other than Kotlin using double quotes for strings and requiring the parentheses.
The unzip task looks like:
That’s way more of a mouthful, especially the chain of method calls that accesses the generated zip file. Personally, I prefer the Groovy version, but it may be time to acknowledge that I’ve lost that battle and move on.
I’m trying, at least. Every once in a while, somebody will write a blog post or make a video about how to convert Gradle build files written in the Groovy DSL into the Kotlin DSL. That’s fine, but they invariably give a list of reasons why they’re doing so, and I really wish they wouldn’t because they almost always get the Groovy part wrong.
For the record:
No, despite what you think, Groovy is not slower than Kotlin. In fact, one of the reasons it’s taken the Kotlin DSL in Gradle so long to catch on is that it was considerably slower than the Groovy one.
No, Groovy is not dynamically typed. It’s optionally typed, meaning you can specify a type if you want and Groovy will follow it, or use the keyword def if you don’t know they type or don’t care about it. Either way, that’s not a big reason to abandon Groovy for Kotlin, because you can always turn that capability off in Groovy if you don’t like it.
While it’s true that Kotlin has null safety built into the language at compile time (in fact, that’s one of its best features), Groovy’s safe navigation operator
?.
is pretty effective at working with nulls in most circumstances.Yes, the IDE support is (somewhat) better for Kotlin than for Groovy, but that’s hardly Groovy’s fault. If any company had invested the money into IDE development for Groovy that JetBrains and Gradle have spent on Kotlin over the last decade, the Groovy support would be excellent. Even so, the gap between them isn’t that big.
Again, I am forced to admit I’ve lost this battle. This week I taught a Groovy course for the first time in years, and all of its advantages came flooding back. I still don’t know why it didn’t succeed beyond a few percent of the marketplace, and I still miss it. It just galls me to see developers who have no idea what the language can do echo criticisms about it that simply aren’t true.
This whole discussion (minus most of my rant about Groovy over Kotlin) is in my latest video…
If you’re wondering why I don’t make all my Groovy vs Kotlin points in that video or in other places, this image I saw posted on Mastodon explains it:
Still, I had to say something… You’ll see if you watch it.
The real problem with my video is that I’ve learned a lot recently about keyword research on YouTube, and let’s just say that it’s a bit sad that I keep making videos nobody is searching for. We’ll see how this one does, assuming anybody watches it at all. I mostly made it because I thought the ideas were interesting, and maybe they’ll help somebody somewhere.
AI Experiments
This coming week I’ll be in Denver for ÜberConf, the NFJS “destination” conference that runs from Tuesday to Friday. (Despite the name, this conference has nothing to do with the ride-sharing app.)
I’m giving a full-day workshop, as well as six talks. The biggest new one is called Practical AI Tools for Java Developers. I spent a fair amount of time this week working on that talk.
I’ve been using GitHub Copilot for months now, so that’s part of the talk. I’ve also had a subscription to the paid version of ChatGPT, so that’s included. I recently used Google’s Bard on a project (with mixed results), so that’s in there, too. Only recently, though, did I get a chance to try out Claude, the AI tool from a company called Anthropic. Claude is supposedly designed with ethical considerations in mind, though I have no way to prove that. I don’t tend to push that envelope, so I’m not sure when it would push back. The best part is that it’s still free, even if it’s restricted to users in the US and the UK (which I assume they’ll expand as soon as possible).
One of Claude’s best features is that you can upload files to it, of decent size, and it can analyze and interpret them. You can add a couple of pdfs, for example, and it will summarize their contents. It’s pretty impressive, to be honest, and I’ll be playing with it more as time goes on.
Another part of my talk is that OpenAI (the company behind ChatGPT) maintains an API for accessing its GPT models. There are ports to various languages, but I just wrote a Java program that used the provided REST links to do the job.
I did a couple of “Hello, World” type examples, which worked (and probably cost me a tenth of a cent or so to run). Before my talk, I’ll no doubt commit everything to a GitHub repository and include a link in next week’s newsletter.
If there’s time, I’ll show off the MacWhisper tool I’ve mentioned here before. That tool is based on another product from OpenAI, called Whisper, which transcribes audio files into text. It can also do translations, though I haven’t tried that. I use MacWhisper to generate subtitles for all my videos.
I also hope to show some of the AI features built into Canva these days, like the Magic Eraser that can remove parts of pictures and the Background Remover that makes the entire background transparent. They also have a program called Beats Sync, which adjust added music so that video transitions line up with musical changes. Maybe I can show the AI-generated voice overs in Descript. Those few examples are cool, but they get pretty far from the stated goal of showing how AI is helping Java developers. For that I will include the GitHub Copilot X system, which aims to add more analysis tools to the toolkit.
The latest beta of IntelliJ IDEA also includes it’s new feature called AI Assistant. I mentioned last week how I tended to argue with it, but it’s actually pretty useful.
I’ll let you know how the presentation goes. This is a very fast moving field, so I guess it’s good I’ll be updating my talk right up until I give it.
Tweets / Toots / Skeets / More
Last week I mentioned that I joined the Threads app from Instagram. I’ve hardly used it at all, though. It’s filled with algorithmic suggestions from celebrities and influencers, which are two groups of people I really don’t care about at all. In fact, I don’t see many posts from people I’m trying to follow. It seems they’re trying to be like TikTok, which is another app I don’t have. I doubt I’ll use it much until they add some of the features I want, like a reverse chronological feed and the ability to just see posts from the people I follow. I don’t trust Zuck to provide anything that doesn’t serve him directly, though, so I may have a long wait.
As for Bluesky, it turns out I’m not using it very much, either. It too doesn’t have the reverse chronological option, so I have to scroll way down to find where I last left. It’s also pretty bland, though I got the impression they had some serious moderation drama over there last week. I was too busy, and too uninterested, to track it down.
Based on a suggestion by a jarhead (Hi Meg!), I did join the Post news app. That feels like it was designed for journalists and publications. I’m not sure how much I’ll use it, but it’s okay, I guess. If nothing else, I’ll post my newsletter there. And I followed Meg, of course. :)
As for the rest, I liked this cartoon:
My app of choice these days is big mammoth — er, Mastodon. That’s the only one where I spent any real time.
Oh, and speaking of Threads:
That pretty much matches my experience. I saw a separate news article that suggested that Twitter usage was off by about 10% as well. Who knows what the future will bring?
Song Cue
I’d love to know what this picture was actually about, but maybe it’s best if I don’t. I must also admit it took me hours to get that song out of my head.
Living in a Glass Onion
The response is from Rian Johnson, who made the Benoit Blanc movies Knives Out and Glass Onion. If Elon is really so clueless as to emulate the idiot billionaire in Glass Onion (rhetorical question — he most definitely is), yeah, I’d laugh too.
(I didn’t want to check to see if that rumor is true, but I had to do something. It turns out, yup, he’s a complete idiot. Here’s an article in Architectural Digest, one in Jalopnik about using Tesla funds to do it, and the big one in the Wall Street Journal.)
Trivia Time!
Of course, there’s permanent, and there’s permanent. But still.
Human Resources
Seems only fair.
Interview Technique
Nerd Joke, But I Laughed
As the saying goes, IYKYK (if you know, you know). My only concurrency joke is really a time traveler one:
The bartender says, “We don’t serve time travelers here.”
A time traveler walks into a bar.
AI Goals
The cartoonist (Zach Weinersmith) claims, to his own amazement, he made that years ago.
Finally, Twitter
Here’s the cake:
Have a great week everybody!
The video version of this newsletter will be on the Tales from the jar side YouTube channel tomorrow.
Last week:
Introduction to Groovy, private class on India time
Deep Dive Into Spring, an NFJS Virtual Workshop
Gradle Tips and Tricks, ditto
Getting Started with Spring, on the O’Reilly Learning Platform
This week:
ÜberConf.
I also never understood the Groovy hate, for mostly the reasons you list there Ken.
I won't be able to get the Lion Sleeps Tonight out of my mind.