Report about updating a Java project from JDK 8 to JDK 11
Tags: java, gradle
Published: 2019-03-23 14:20:06

---
title: Report about updating a Java project from JDK 8 to JDK 11
published: true
description: Experience description of the upgrade of a small Java project from JDK version 8 to 11 with Gradle and IntellJ on MacOS.
tags: java, gradle
---

The Java version 8 has reached its end of life. Since January 2019 the free, commercial version doesn't receive updates anymore (see [oracle.com](https://www.oracle.com/technetwork/java/java-se-support-roadmap.html)).

So (unless you want to switch to non-mainstream JDK providers like [AdoptOpenJDK](https://adoptopenjdk.net/) or [Amazon Corretto](https://aws.amazon.com/en/corretto/)) it's time to upgrade all Java projects to the latest version. Or at least to the latest long-term support version.

This blog post is an experience report about the steps which need to be done on that path.

# Assessing status quo

## Environment

The project which is going to be updated is rather small. It's a **Spring Boot** application which uses **Apache Wicket** as web framework and **Gradle** for the build management. The primary development environment is a **MacBook Pro** and the **IntelliJ** IDE.

## Overview over installed JVMs

On MacOS, with this command on the terminal, all JVMs which are installed on the system can be listed:

```
$ /usr/libexec/java_home -V
Matching Java Virtual Machines (3):
    10.0.1, x86_64:	"Java SE 10.0.1"	/Library/Java/JavaVirtualMachines/jdk-10.0.1.jdk/Contents/Home
    9.0.1, x86_64:	"Java SE 9.0.1"	/Library/Java/JavaVirtualMachines/jdk-9.0.1.jdk/Contents/Home
    1.8.0_152, x86_64:	"Java SE 8"	/Library/Java/JavaVirtualMachines/jdk1.8.0_152.jdk/Contents/Home

/Library/Java/JavaVirtualMachines/jdk-10.0.1.jdk/Contents/Home
```

In this case they were installed via [Homebrew](https://brew.sh/), so an overview can also be provided by the following command:

```
brew cask list
```

The JDK which is being used by Gradle is determined by the environment variable `JAVA_HOME`. With such like instructions in the `.bash_profile`, the versions can be switched easily:

```
export JAVA_8_HOME=$(/usr/libexec/java_home -v1.8)
export JAVA_9_HOME=$(/usr/libexec/java_home -v9)
export JAVA_10_HOME=$(/usr/libexec/java_home -v10)

alias java8='export JAVA_HOME=$JAVA_8_HOME'
alias java9='export JAVA_HOME=$JAVA_9_HOME'
alias java10='export JAVA_HOME=$JAVA_10_HOME'

# use JDK 8 by default
export JAVA_HOME=$JAVA_8_HOME
```

# Installing JDK 11

Via Homebrew, the OpenJDK 11 can be installed like this:

```
brew update
brew tap homebrew/cask-versions
brew search java
brew cask install java11
```

(See [stackoverflow.com](https://stackoverflow.com/a/52524114/2339010)) for further details.

Now Java 11 can be added into the `.bash_profile`:

```
export JAVA_11_HOME=$(/usr/libexec/java_home -v11)

alias java11='export JAVA_HOME=$JAVA_11_HOME'
```

After starting a new terminal tab, it should now be ready for use:

```
$ java11
$ java -version
openjdk version "11.0.2" 2019-01-15
OpenJDK Runtime Environment 18.9 (build 11.0.2+9)
OpenJDK 64-Bit Server VM 18.9 (build 11.0.2+9, mixed mode)
```

# Upgrading the Java project

## Upgrade dependencies

> My most urgent advice for you today then, is this: If you're using Java 9 or later, upgrade to the latest versions of all your tools and dependencies. -- [Mark Reinhold](https://www.youtube.com/watch?v=wHoRBvt3U6o)

From Java 8 to Java 9 some breaking changes where introduced in the language. So projects might run into problems, if the libraries they have included depend upon changed language features. So it is a good idea to start the actual migration by updating all the dependencies to their latest version. With Gradle this process is supported by the [Gradle Versions Plugin](https://github.com/ben-manes/gradle-versions-plugin):

```
$ gradle dependencyUpdates -Drevision=release

------------------------------------------------------------
: Project Dependency Updates (report to plain text file)
------------------------------------------------------------

The following dependencies are using the latest release version:
 - com.giffing.wicket.spring.boot.starter:wicket-spring-boot-starter:2.1.5
 - javax.xml.bind:jaxb-api:2.3.1
...

The following dependencies have later release versions:
 - com.google.guava:guava [27.0.1-jre -> 27.1-jre]
     https://github.com/google/guava
 - io.spring.dependency-management:io.spring.dependency-management.gradle.plugin [1.0.6.RELEASE -> 1.0.7.RELEASE]
 - org.projectlombok:lombok [1.18.4 -> 1.18.6]
     https://projectlombok.org
 - org.springframework.boot:spring-boot-gradle-plugin [2.1.2.RELEASE -> 2.1.3.RELEASE]
     https://projects.spring.io/spring-boot/#/spring-boot-parent/spring-boot-tools/spring-boot-gradle-plugin
...
 - org.wicketstuff:wicketstuff-annotation [8.2.0 -> 8.3.0]
     http://wicketstuff.org
```

Also Gradle should be updated to its latest version:

```
brew upgrade gradle
```

Further, the IDE and all its plugins should be up-to-date.

## Update the language level in the Gradlefile

Now we are ready to increase the Java version number in the `build.gradle` file:

```
subprojects {
    sourceCompatibility = 11
    targetCompatibility = 11
```

## Use JDK 11 in the IDE

Afterwards we need to switch to JDK 11 in IntelliJ. This can be done by going to the menu entry "File > Project structure". The new version and the language level can be selected in the Project SDK dropdown menu. If it is not available yet, it can be added in the "Platform Settings" section.

![Screenshot "Project structure" dialog](https://thepracticaldev.s3.amazonaws.com/i/qv7kx40sv7gkdrugavt1.png)

Also check in the "Preferences" that the new compilation target is being used:

![Screenshot "Preferences" dialog](https://thepracticaldev.s3.amazonaws.com/i/88bexvv97uxa0k0a41h7.png)

Now build the project and run the unit tests. If you are lucky there are no errors.

## Use JDK 11 on the terminal

Then try to do so in the terminal:

```
gradle clean check
```

In the case of [this project](https://github.com/ksch-workflows/ksch-workflows), there was only one problem: The build via the terminal failed because the Lombok library could not be loaded. The fix for this was fairly simple, just adding those two dependency declarations in the `build.gradle` file:

```
annotationProcessor("org.projectlombok:lombok:${lombokVersion}")
testAnnotationProcessor("org.projectlombok:lombok:${lombokVersion}")
```

# Final test

After all the updates, verify that the application is still running correctly:

```
gradle clean bootRun -Dspring.profiles.active=qa
```

No further problem did occur. So all in all, upgrading to Java 11 was easier than expected:

https://github.com/ksch-workflows/ksch-workflows/commit/f5724e627eeaab2b7fb7a2e4a581091f4d0ee628

# Cleanup

Last but not least, obsolete Java versions can be removed from the development environment:

## Uninstall via Homebrew

```
brew uninstall java9
brew uninstall java10
```

## Hard deletion

If they where not installed via Homebrew, this is the way to delete old Java versions:

```
$ cd /Library/Java/JavaVirtualMachines
$ sudo rm -rf jdk-9.0.1.jdk jdk-10.0.1.jdk
```