Java 11 Migration
In the following we provide the steps taken in order to migrate the Synapse backend from JDK 8 to JDK 11.
Compile Time Issues
The root pom.xml of the Synapse backend services was updated, in particular the maven-compiler-plugin with now take the new parameter
<release>11</release>
. The old<source/>
and<target/>
were removed.The
lib-doi
module complained of a duplicated module importing org.w3c.dom.* classes:"The package org.w3c.dom is accessible from more than one module: <unnamed>, java.xml"
This was caused by theXerces
library that imported thexml-apis
. To solve this the xml-apis artifact was excluded from the xerces-impl dependency:<dependency> <groupId>xerces</groupId> <artifactId>xercesImpl</artifactId> <version>2.12.2</version> <exclusions> <exclusion> <groupId>xml-apis</groupId> <artifactId>xml-apis</artifactId> </exclusion> </exclusions> </dependency>
javax
imports were missing (those were removed from the JDK). In particular we needed the javax annotation api that were imported where needed:<dependency> <groupId>javax.annotation</groupId> <artifactId>javax.annotation-api</artifactId> <version>1.3.2</version> </dependency>
The lib-javadoc module complained of a duplicated module importing com.sun.javadoc.* classes:
"The package com.sun.javadoc is accessible from more than one module: <unnamed>, jdk.javadoc"
This was caused by the com.sun tools dependency that was removed. Note that the lib-javadoc uses the old doclet api, that was superseded byjdk.javadoc.doclet
. It was not necessary to port the code using the jdk.javadoc.* to the new doclet, but it is deprecated in the JDK 11 and will need to be refactored when we move to a more recent version of the JDK since they will be removed.
Runtime Issues
Several
java.lang.NoClassDefFoundError: javax/xml/bind/DatatypeConverter
exceptions were noted, in order to solve this thejaxb-api
needed to be imported (was removed from the JDK):<dependency> <groupId>javax.xml.bind</groupId> <artifactId>jaxb-api</artifactId> </dependency>
The same
java.lang.NoClassDefFoundError: javax/xml/bind/DatatypeConverter
was also caused by an old version ofjjwt
. The dependency was updated to the latest version and the code adapted to the changes introduced by the new version.Noted several Illegal access warnings:
Guice
was updated to the latest version.
Build Changes
The only change needed to run the build against java 11 was to update the docker base image we use to run the build from
maven:3-jdk8
tomaven:3-amazoncorretto-11
. Note that we now use the amazon corretto distribution of the JDK that is the same we use in production.
Test Failures
EvaluationRoundDBOTest and DataAccessNotificationDaoImplTest assertions failed:
This was caused by a change in the JDK in the Instant.now() implementation that now produces microsecond resolution in JDK11 while it was milliseconds in the past. The SQL timestamp is milliseconds so the test were failing when comparing the data back from the database that was truncated.
To resolve this the code was adapted to make sure to truncate the Instant to milliseconds:Failures of ClaimsWithAuthTime class due to changes in the jjwt library, the code was adapted to the new implementation.
Several failures such as:
Caused by: javax.net.ssl.SSLProtocolException: Cannot decode named group: x25519:
This was by far the trickiest issue. The tests were failing only during the jenkins build. Locally the single test class was working properly. Made sure to use the same exact JDK version, connecting to the exact same remote DB instance and tried updated the mysql connector and connections pool library but locally the tests were passing but still failing during the build.
Realized that there is a subtle difference, when running a single test class locally from the IDE other classes are not taken into account, while the build on jenkins uses the maven surfire plugin that runs the tests in a different context, in particular in the context of the “managers” module. Some classes in the managers must have had some different setup that was messing with the SSL handshake.
Since the error pointed to an algorithm mismatch somewhere in the code the security providers must have been altered. The culprit was a static initialization in theDockerTokenUtil
class:This piece of code would remove the default providers globally and replace it with the bouncy castle implementation, since x255519 is an EC then the mismatch was thrown because the Bouncy Castle implementation didn’t match it.
To solve this the static initializer was removed and instead theKeyPairUtil
(that contained various methods to sign and generate tokens) was updated to use the bouncy castle provider (note that the test were passing also with the standard JDK security providers but for historical reasons we left the bouncy castle implementation instead).The
BaseControllerExceptionHandlerAdviceTest
was failing due to and old version of theReflections
library. The library was updated to the latest version.The
BeanTest
started failing due to the update of theReflections
library, in particular one of the tests was verifying that any supposedly read-only method (e.g. prefixed withget
) didn’t have the @*WriteTransaction annotations. The new version of the library picked up more classes than the previous one so we had to add more exclusions to the test (e.g. we have some methods that are prefixed with a get verbiage that do actually need a write transaction).
Deployment changes
The only change was to update the Java version used in the stack builder for the beanstalk cloudformation template from 8 to 11.
Notes
The changes above apply to the Synapse backend only, the deployment was tested successfully in the dev account. Other dependencies didn’t need to be updated. Other projects might need to be updated as needed if they depend on the latest version of Synapse backend code.