Spring Boot, Gradle and Java 11

When upgrading a hobby Spring Boot project to Java 11, there were a few issues which reminded me of how closely related Gradle, the Spring Boot plugin, and the java version you’re using are.

Naively trying a gradlew bootRun on the project (which was using Gradle 3.1) resulted in this:

Could not determine java version from '11.0.5'

Fortunately I’d seen that one before, so I upgraded my version of Gradle to 5.1.1 by updating gradle-wrapper.properties.

The next problem was a little more subtle:

Execution failed for task ':findMainClass'.
> org.gradle.api.tasks.SourceSetOutput.getClassesDir()Ljava/io/File;

It looked like an API compatibility issue, so running again with --stacktrace showed that the Spring Boot Gradle plugin was trying to use a method which had been removed from Gradle:

org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':findMainClass'.
...
Caused by: java.lang.NoSuchMethodError: org.gradle.api.tasks.SourceSetOutput.getClassesDir()Ljava/io/File;
        at org.springframework.boot.gradle.run.FindMainClassTask.findMainClass(FindMainClassTask.java:105)

...

So next step is to upgrade the Spring Boot plugin, as it will have been updated to support Gradle 5. This is a hobby project I’ve not maintained for several years, so I had to upgrade from 1.4.3 to 2.2.4. Since I’ve left it so long, I can see some trouble on the horizon! Oh well, it will be worthwhile.

I then had some problems refreshing my Gradle configuration, mostly related to plugin and dependency management declarations. Since Gradle has changed its DSL quite a bit since the version I was on, I ended up grabbing a fresh build.gradle from [start.spring.io] and merging my changes into that.

The Gradle build now seems happy - it gets as far as invoking the java plugin to compile the project. But this is where it fails again as some changes have been made to Spring Data JPA - I was using findOne(ID id) but this has been renamed to findById(ID id), and this now returns an Optional.

Once I’d fixed things up to work with the Optional entities returned from my Repositories, the application started up successfully. But once I logged in, I hit a new problem: There is no PasswordEncoder mapped for the id "null".

It turns out, Spring Security has changed the requirements for password storage. Because this was a hobby project running purely on my home Mac and was not intended to roll out live any time soon, passwords were stored as plain text. The temporary solution was to migrate my existing dev password to be {noop} followed by the plain string it was previously set to. Naturally in a production environment, a real hashing algorithm would be used.

I also encountered a silly issue related to using the Spock groovy test plugin. I had configured the groovy plugin in my top-level build.gradle but had then re-defined the plugins section in my web sub-project, but without the groovy declaration. The sub-project plugins section was overriding the one at top-level, so my groovy test folder was never being recognised on import.