Creating an OS X App Bundle With Gradle

I’ve been tinkering with Kotlin and JavaFX and the result was a Java jar file that spins up a user interface.  OS X will double click open a jar, but I wanted a normal app. I looked around and found App Maker, which did a decent job, but processing the jar manually each build got annoying fast.  Looking at the info out there, and what App Maker did, it seemed like I ought to be able to get gradle to do the same without too much pain. I did.

The Simplest App Possible

So, from documentation, and investigating App Maker’s output, the simplest app is:

AppName.app/
   Contents/
      Info.plist
      MacOs/
         AppName-x.y.z.jar
         launcher
      Resources/
         application.icns

That’s the basics.  So if you’ve a working jar, all you’re lacking it the directory structure, and:

  • Info.plist: An Apple plist file, you can use a simple one unaltered.
  • launcher: A shell script that launches the jar. This can be 98% templated, with only things like the app name, jar name, and java version needing to be set.
  • application.icns: An icon formatted to Apple’s approval.

The Gradle Solution

To generate the app bundle from gradle, I did two things:

  1. Put the three needed files into src/main/app. The Info.plist and the application.icns are the actual final files.  The launcher I modified into a template, using Ant’s templating notation “@VARIABLE_NAME@”.
  2. Then I added one gradle task to build out the directory structure, and copy the files into place, applying the templating.

The Task

Here is the gradle task.  I employed some of gradle’s ant support to perform copies and templating.

With the files and task in place all you need to do is run gradle osxApp and you’ll hopefully find build/app/ProjectName.app – a working OS X app.

Conclusion

I could roll this into a Gradle PlugIn but that’s more work then I want to do for this.  As it stands, if you want to use this approach, just grab my project that uses it, copy the files in src/main/app and add the task to your build.gradle.

 

Advertisements

Kotlin, TornadoFX, Gradle… Thumbs Up!

In one of my many “lets try something new” moments I decided to give Kotlin a more serious look.  I’d previously run through some of the tutorials but hadn’t gone very deep. This time I decided to set a useful target, and achieve it with Kotlin. I’ve a snippets kata project that I often use, and so decided to port that.  At first my intention was to just replace the outside layers with Kotlin, but as I worked more with the language I really got into it, and before I knew it I’d rewritten pretty much everything, keeping only the export/import file format so I wouldn’t loose my data.

My Choices:

  • I’m devoted to Gradle so I wanted to use that. Turned out to be a good choice. The Kotlin plugin is clean, simple and functional.
  • The code I wrote would be all Kotlin 1.2 targeting Java JVM
  • Not really a choice, but figures in, I use IntelliJ as my IDE and it’s very Kotlin aware
  • The UI, well I’d used JavaFX previously, and I found TornadoFX, a Kotlin framework for using JavaFX, so  went with that.
  • I like a visual tool for creating UIs, so used Scene Builder to create FXML files describing the UI

Likes

Pretty much, across the board I was happy with my choices and the development was straight forward.

  • Kotlin is a pleasure. The language is clean and intuitive. It may be able to run in the JVM, and use existing Java, but the language isn’t another Java DSL.  It’s more thorough on topics like, null, immutability, closures, and functional programming.
  • TornadoFX alleviated my main JavaFX gripe.  I liked JavaFX, but it had a painful style impedance with Java. TornadoFX, on the other hand, fit right into the Kotlin world.
  • Scene Builder. It’s stable and workable, better now it’s not Oracle’s product, and Kotlin drinks FXML files flawlessly.

Liked Less

Really didn’t have any complaints, but…

I’m comfortable in the Java ecosystem, and while Kotlin is in that sphere, some Java ecosystem tools won’t play.  Some unit testing tools, and annotation based frameworks seemed confused about Kotlin methods.

Setting Up A Glowroot Java APM Collector

Performance tuning Java Apps tends to happen one of two ways. You’re in a culture that is prepared, has tools, has been laying the ground work, and has included it in the planning. Or… the other alternative, someone’s rolled out something, and is unhappy with performance, and now needs answers yesterday. Often when you’re in the second scenario, no tools or culture is present, and you’ll have to start from the ground up.  It’s hard, and often expensive, to do a Java Application Performance Monitoring tool in a big way.  Glowroot isn’t the richest APM but it might be a good starting point.

Getting Started

So, with Glowroot, getting started can be as easy adding a single JVM argument to your app. That will embed the whole thing, with an embedded web site, right in your app. Done.  For my needs, the app was a micro-service, that runs replicas behind load balancers, so embedding Glowroot into the app just isn’t practical as targeting a specific endpoint on a specific service is a bit of a whack-a-mole situation.  Instead I needed Glowroot to push the data out to a central collector with a site there.  Glowroot supports this out of the box and it even vaguely documents it too. Vaguely.

Setting Up a Collector

So I’ve created a project to help spin up and use a centralized collector.  The project gives you a docker compose file that will bring up Glowroot as a collector, and an instance of Cassandra it requires. There are notes there too on connecting to it.

Basically

Using the project/notes (README.md) you:

  1. Pick a host
  2. Run docker-compose on the provided compose file
  3. Download the Glowroot distribution and point it at your collector
  4. Add JVM args to your app
  5. Run your app

Done.  Your app info will appear in the collector website.

 

Sloppy Fat Jar in Gradle

In Java, one deployment approach is to bundle all you dependencies into a single fat jar and then use “java -jar foo.jar” to run things.  I use this often, and there are several Gradle plugins that facilitate doing it. The plugins tend to offer nice features like name space collision resolution, what if the same class or resource appears in two dependencies?  But recently I stumbled across this little Gradle gem for making what I’ll call a sloppy fat jar:

All it does is, in a single line (7), unpack all your dependencies into your jar. Totally brute force and crude, but then it doesn’t require a plugin or any configuration. Also it doesn’t tie into anything else, so for example it worked in a Kotlin build where other plugins got totally confused.

Java Combinators

I’m not a purist about programming paradigms. I try to look for value and incorporate what I can.  Recently I read a series on Combinators in Java.  Functional programming is a paradigm I see a lot of value in and try to bring it’s strengths to my code, and in particular I’m not happy with currying in Java, so the article caught my eye.

But… the articles to me seemed too purist.  Maybe it was just the examples given.  My first reaction was that the “combinators” discussed, before, after, around, where little more that AOP and no mention of that was cited. There are a lot of ways to do AOP in Java and it wasn’t clear this approach offered much above any other.  Additionally the offered solution seemed very heavy on form.

Consider the Before example:

Looking at that, it seemed like the following achieved the same more simply:

Reading on, each example played out that way. There was a lot of what seemed like extraneous stuff, and additionally the before, after, should have drawn from the Java 8 terminology and been, compose, andThen. The articles approach did yield typed higher order functions, but I’m not clear where I’d want that.  Sadly the author didn’t reply to questions, so I may have simply missed the boat, but for now, I’ll stick with my simpler approach.

 

JDBC, Generated Keys, Oracle Issues

Recently, using JDBC, I needed to retrieve the generated keys from a row I’d just inserted. For example you’re inserting a word into the following table and want the id:

Not something I’d done before, but very sane, and the solution was easily found:

This worked great in my H2 embedded database where my unit tests ran, and in the MariaDB I ran integration tests against.  However when I used the code against an Oracle database … FAIL … something about a type mismatch.  So what went wrong?

The issue is Oracle stuffs a RowId into every record, not because you ask it to, but because it just does. I’m sure this addition makes all sorts of Oracle magic possible. Generally one just ignores it, or at least I do, but in this case Oracle rubs your nose in its decision.  How? When the code above runs against Oracle, the ResultSet for the generated keys it returns, does not contain the generated key you put in the schema, but the RowId Oracle did!

Of course there is another solution.  The following, while a bit more verbose, works with all the database engines I tested:

Be warned, these snippets aren’t working general solutions, but the exemplified approach is.  What Oracle needs is to be told which columns were generated, otherwise it assumes the RowId, and luckily other database engines are happy to work this way too.

Worth Noting Too

JDBC offers ways to get the generated keys via both Statement and PreparedStatement. Only the PreparedStatement routes seem to work with Oracle, and the generated keys ResultSet in Oracle doesn’t seem to know the column names, only their positions (I’ll research the meta data there when I get a chance).

Gradle, JUnit5, Jacoco Working

The way information is dispersed on the Internet is pretty cool sometimes.  I’ve visited this same topic a couple times and never managed to get JUnit5 and Jacoco working with Gradle.  Fresh searches never turned up a working solution.  The other day, looking at my blog stats I saw an intriguing referrer to one of my past posts. The reference was from a blog written in Japanese. Google translate yielded an awkward version that seemed to offer a solution.  Since the Gradle code needed no translation I tried out some of the changes shown and – viola!

So, Here’s the Working Solution

The goal was to employ JUnit5, generate Jacoco reports, and feed those into Codecov.com. Here’s the snippet of working solution.

I believe the secret sauce I missed was in lines 23 and 27.  To see the project that I tested this with, the repo is here.