Migration to java 21

👣 Steps

Update parent pom.xml

<properties>
    <java.version>21</java.version>
    <maven.compiler.source>${java.version}</maven.compiler.source>
    <maven.compiler.target>${java.version}</maven.compiler.target>
</properties>

Update Dockerfile

FROM amazoncorretto:21-alpine

Update JVM_OPTIONS if you want to use ZGC

-XX:+UseZGC -XX:+ZGenerational

🐛 Issues encountered

✅ Fatal error compiling: error: invalid target release: 21

When compiling with Maven, I got the following error:

$ mvnd clean verify
...
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.11.0:compile (default-compile) on project record-id: Fatal error compiling: error: invalid target release: 21 -> [Help 1]
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.11.0:compile (default-compile) on project reactor-logging: Fatal error compiling: error: invalid target release: 21 -> [Help 1]
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.11.0:compile (default-compile) on project grpc-api: Fatal error compiling: error: invalid target release: 21 -> [Help 1]

It's because I was using mvnd which was still using Java 17:

$ mvnd --version
Apache Maven Daemon (mvnd) 0.9.0 linux-amd64 native client (fa3cc5d66458a8526bd543de85566293113dacc4)
Terminal: org.jline.terminal.impl.PosixSysTerminal with pty org.jline.terminal.impl.jansi.linux.LinuxNativePty
Apache Maven 3.8.7 (b89d5959fcde851dcb1c8946a785a163f14e1e29)
Maven home: /home/l-lin/.asdf/installs/mvnd/0.9.0
Java version: 17, vendor: Eclipse Adoptium, runtime: /home/l-lin/.asdf/installs/java/adoptopenjdk-17.0.0+35
Default locale: en_US, platform encoding: UTF-8
OS name: "linux", version: "6.5.7-arch1-1", arch: "amd64", family: "unix"

✅ java.lang.NoSuchFieldError

$ mvn clean verify
...
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.11.0:compile (default-compile) on project reactor-logging: Fatal error compiling: java.lang.NoSuchFieldError: Class com.sun.tools.javac.tree.JCTree$JCImport does not have member field 'com.sun.tools.javac.tree.JCTree qualid' -> [Help 1]

I need to upgrade Lombok. By bumping spring-boot to 3.1.5, it mitigates the issues:

<spring-boot.version>3.1.5</spring-boot.version>

✅ Unsupported class file major version 65

$ mvn clean verify
...
java.lang.instrument.IllegalClassFormatException: Error while instrumenting com/bioserenity/aqtp/domain/configuration/EnvironmentTest.
        at org.jacoco.agent.rt.internal_3570298.CoverageTransformer.transform(CoverageTransformer.java:94)
        at java.instrument/java.lang.instrument.ClassFileTransformer.transform(ClassFileTransformer.java:244)
...
[ERROR] Failed to execute goal org.jacoco:jacoco-maven-plugin:0.8.7:report (default) on project configuration-variables-by-env: An error has occurred in JaCoCo report generation.: Error while creating report: Error while analyzing /home/l-lin/work/cloud-aqtp/domain/configuration-variables-by-env/target/classes/com/bioserenity/aqtp/domain/configuration/Environment.class. Unsupported class file major version 65 -> [Help 1]

Upgrade Jacoco:

<jacoco-maven-plugin.version>0.8.11</jacoco-maven-plugin.version>

🚧 Mockito cannot mock this class: interface

$ mvn clean verify
...
[ERROR] com.bioserenity.aqtp.domain.simulation.adapter.checker.RetryCheckerTest.givenCheckSucceedAtOnce_whenChecking_thenDecoratedCheckerIsCalledOnce  Time elapsed: 0.017 s  <<< ERROR!
org.mockito.exceptions.base.MockitoException:
 
Mockito cannot mock this class: interface com.bioserenity.aqtp.domain.simulation.port.checker.Checker.
 
If you're not sure why you're getting this error, please open an issue on GitHub.
 
 
Java               : 21
JVM vendor name    : Eclipse Adoptium
JVM vendor version : 21+35-LTS
JVM name           : OpenJDK 64-Bit Server VM
JVM version        : 21+35-LTS
JVM info           : mixed mode, sharing
OS name            : Linux
OS version         : 6.5.9-arch2-1
 
 
You are seeing this disclaimer because Mockito is configured to create inlined mocks.
You can learn about inline mocks and their limitations under item #39 of the Mockito class javadoc.
 
Underlying exception : org.mockito.exceptions.base.MockitoException: Could not modify all classes [interface com.bioserenity.aqtp.domain.simulation.port.checker.Checker]
        at com.bioserenity.aqtp.domain.simulation.adapter.checker.RetryCheckerTest.setUp(RetryCheckerTest.java:31)
Caused by: org.mockito.exceptions.base.MockitoException: Could not modify all classes [interface com.bioserenity.aqtp.domain.simulation.port.checker.Checker]
        at com.bioserenity.aqtp.domain.simulation.adapter.checker.RetryCheckerTest.setUp(RetryCheckerTest.java:31)
Caused by: java.lang.IllegalStateException:
 
Byte Buddy could not instrument all classes within the mock's type hierarchy
 
This problem should never occur for javac-compiled classes. This problem has been observed for classes that are:
 - Compiled by older versions of scalac
 - Classes that are part of the Android distribution
        at com.bioserenity.aqtp.domain.simulation.adapter.checker.RetryCheckerTest.setUp(RetryCheckerTest.java:31)
Caused by: java.lang.IllegalArgumentException: Java 21 (65) is not supported by the current version of Byte Buddy which officially supports Java 20 (64) - update Byte Buddy or set net.bytebuddy.experimental as a VM property
        at com.bioserenity.aqtp.domain.simulation.adapter.checker.RetryCheckerTest.setUp(RetryCheckerTest.java:31)
...
[ERROR] Errors:
[ERROR]   RetryCheckerTest.setUp:31 Mockito
Mockito cannot mock this class: interface c...

assertj-core in v3.24.2 is still using an old version of bytebuddy (v1.12.21) whereas it should have used 1.14.9 (version provided by Mockito). Available only on the next release of assertj v3.25.0.