Migration games. Part 1.
With a new release model for Java, Oracle left thousands of developers scratching their head on tons of issues. Do we migrate? What if we do not migrate? Do we migrate to Java 9? Wait, Java 9 is not supported anymore. So do we migrate to Java 10 or do we stick to Java 11, which has long (well, a little bit longer) term support? What about our public API? Do we maintain versions for Java 8 and Java 11? How easy it would be to migrate?
Consensus regarding last question is that there is quite a leap from Java 8 to 9 if you want to modularise your project. However, if you use classpath everything should be pretty simple and you may even enjoy further migrations.
The reality is always somewhat different. There are certain pitfalls, gotchas and in general weird stuff which can make transition from Java 8 eventful and bring lots of joy if you like puzzles.
Maven plugins, Maven dependencies and Java EE modules
While Maven itself support Java 9, there are various plugins, where support for Java 9 is not quite there. For example, we have tripped over JAXB2 plugins. In our configuration projects use jaxb2-maven-plugin, few newer projects use maven-jaxb2-plugin. During migration process both did not work under Java 9.
I have checked today (15th of May, 2018), jaxb2-maven-plugin team is warming up for big push to make it work anytime soon, maven-jaxb2-plugin has released 5 days ago a snapshot for 0.14, which suppose to work on Java 9.
The working alternative was cxf-xjc-plugin. It is a part of Apache CXF and it was very nice to deal with something which worked straight away without any hassle.
Another big effort was to crack problem of EE modules visibility. In Java 9 EE modules are not included in JDK and you need to use --add-modules option to add them. So far so good.
I take a project, I compile it with Java 9, it is happy. I run tests, it complains that class javax.annotation.Priority can’t be found.
javax.annotation is a transitive dependency to lots of XML related things, in my case it was JAX-RS Jersey client. I add javax.annotation as provided dependency, all the same.
Replace Jersey with CXF JAX-RS client, all the same. Did some reading, head scratching, Martini meditation, listened to my heart and to my gut. My gut said “surefire, it must be surefire”. “Thank you, gut. Here is more Martini for you” was my generous reply.
Further investigation established that surefire could not see EE modules and I had to feed them via — add-modules. Next two hours were spent excercising different positions on trying to
push javax.annotation into surefire. Everything indicated that it should be
but it was all the same, javax.annotation.Priority could not be seen. In the morning, I went through surefire issues tracker and discovered incredibly informative issue 1424. The answer was there and it was
Please pause reading and let this sink in. You need to add java.base to make javax.annotation visible <emoji of exploding head>. That easily makes top 3 of most counterintuitive solutions in my 20+ years of experience in software development.
Second solution would be to add following dependency
which is a bit easier to digest.
As it is my first attempt to share knowledge I would like to stop for now. To conclude, I would like to say that migrating Java 8 to Java 9 via classpath was a good and useful excercise.
It was great that I could avoid code refactoring, but with Java 10 and Java 11 that step might be inevitable. If you rely on old libraries or if you rely on libraries which use reflections you will have to deal with it in some way.
In further blogs I will explore philosophical questions “Migrate or not to migrate?” and “Who benefits?”.