DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Because the DevOps movement has redefined engineering responsibilities, SREs now have to become stewards of observability strategy.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Related

  • Using Lombok Library With JDK 23
  • Reading an HTML File, Parsing It and Converting It to a PDF File With the Pdfbox Library
  • Exploring Exciting New Features in Java 17 With Examples
  • How To Approach Dependency Management in Java [Video]

Trending

  • Code Reviews: Building an AI-Powered GitHub Integration
  • Apple and Anthropic Partner on AI-Powered Vibe-Coding Tool – Public Release TBD
  • The End of “Good Enough Agile”
  • Agile’s Quarter-Century Crisis
  1. DZone
  2. Coding
  3. Java
  4. Considerations on Updating Enterprise Java Projects From Java 8 to 11

Considerations on Updating Enterprise Java Projects From Java 8 to 11

A general update from Java 8 to Java 11 is not easy, but also is not impossible.

By 
Víctor Orozco user avatar
Víctor Orozco
·
Sep. 30, 20 · Tutorial
Likes (3)
Comment
Save
Tweet
Share
4.4K Views

Join the DZone community and get the full member experience.

Join For Free

The purpose of this article is to consolidate all difficulties and solutions that I've encountered while updating Java EE projects from Java 8 to Java 11 (and beyond). It's a known fact that Java 11 has a lot of new characteristics that are revolutionizing how Java is used to create applications, despite being problematic under certain conditions.

This article is focused on Java/Jakarta EE, but it could be used as basis for other enterprise Java frameworks and libraries migrations.

Is it possible to Update Java EE/MicroProfile Projects From Java 8 to Java 11?

Yes, absolutely. My team has been able to bump at least two mature enterprise applications with more than three years in development, being:

A Management Information System (MIS)

Example site

  • Time for migration: 1 week
  • Modules: 9 EJB, 1 WAR, 1 EAR
  • Classes: 671 and counting
  • Code lines: 39480
  • Project's beginning: 2014
  • Original platform: Java 7, Wildfly 8, Java EE 7
  • Current platform: Java 11, Wildfly 17, Jakarta EE 8, MicroProfile 3.0
  • Web client: Angular

Mobile POS and Geo-fence

Example migration site

  • Time for migration: 3 weeks
  • Modules: 5 WAR/MicroServices
  • Classes: 348 and counting
  • Code lines: 17160
  • Project's beginning: 2017
  • Original platform: Java 8, Glassfish 4, Java EE 7
  • Current platform: Java 11, Payara (Micro) 5, Jakarta EE 8, MicroProfile 3.2
  • Web client: Angular

Why Should I Ever Consider Migrating to Java 11?

As everything in IT, the answer is "It depends . . .". However there are a couple of good reasons to do it:

  1. Reduce attack surface by updating project dependencies proactively
  2. Reduce technical debt and most importantly, prepare your project for the new and dynamic Java world
  3. Take advantage of performance improvements on new JVM version
  4. Take advantage from improvements of Java as programming language
  5. Sleep better by having a more secure, efficient and quality product

Why Java Updates From Java 8 to Java 11 Are Considered Difficult?

From my experience with many teams, because of this:

Changes in Java Release Cadence

Java SE release cycle timeline

Currently, there are two big branches in JVMs release model:

  • Java LTS: With a fixed lifetime (3 years) for long term support, being Java 11 the latest one
  • Java current: A fast-paced Java version that is available every 6 months over a predictable calendar, being Java 15 the latest (at least at the time of publishing for this article)

The rationale behind this decision is that Java needed dynamism in providing new characteristics to the language, API and JVM, which I really agree.

Nevertheless, it is a know fact that most enterprise frameworks seek and use Java for stability. Consequently, most of these frameworks target Java 11 as "certified" Java Virtual Machine for deployments.

Usage of Internal APIs

Java version graphic

Java 9 introduced changes in internal classes that weren't meant for usage outside JVM, preventing/breaking the functionality of popular libraries that made use of these internals -e.g. Hibernate, ASM, Hazelcast- to gain performance.

Hence, to avoid it, internal APIs in JDK 9 are inaccessible at compile time (but accessible with --add-exports), remaining accessible if they were in JDK 8 but in a future release they will become inaccessible, in the long run this change will reduce the costs borne by the maintainers of the JDK itself and by the maintainers of libraries and applications that, knowingly or not, make use of these internal APIs.

Finally, during the introduction of JEP-260 internal APIs were classified as critical and non-critical, consequently critical internal APIs for which replacements are introduced in JDK 9 are deprecated in JDK 9 and will be either encapsulated or removed in a future release.

Anyway, you are inside the danger zone if:

  1. Your project compiles against dependencies pre-Java 9 depending on critical internals.
  2. You bundle dependencies pre-Java 9 depending on critical internals.
  3. You run your applications over a runtime -e.g. Application Servers — that include pre Java 9 transitive dependencies.

Any of these situations means that your application has a probability of not being compatible with JVMs above Java 8. At least not without updating your dependencies, which also could uncover breaking changes in library APIs creating mandatory refactors.

Removal of CORBA and Java EE modules from OpenJDK

Removal of Java EE and COBRA modules

Also during Java 9 release, many Java EE and CORBA modules were marked as deprecated, being effectively removed at Java 11, specifically:

  • java.xml.ws (JAX-WS, plus the related technologies SAAJ and Web Services Metadata)
  • java.xml.bind (JAXB)
  • java.activation (JAF)
  • java.xml.ws.annotation (Common Annotations)
  • java.corba (CORBA)
  • java.transaction (JTA)
  • java.se.ee (Aggregator module for the six modules above)
  • jdk.xml.ws (Tools for JAX-WS)
  • jdk.xml.bind (Tools for JAXB)

As JEP-320 states, many of these modules were included in Java 6 as a convenience to generate/support SOAP Web Services. But these modules eventually took off as independent projects already available at Maven Central. Therefore it is necessary to include these as dependencies if our project implements services with JAX-WS and/or depends on any library/utility that was included previously.

IDEs and Application Servers

Eclipse installation details

In the same way as libraries, Java IDEs had to catch-up with the introduction of Java 9 at least in three levels:

  1. IDEs as Java programs should be compatible with Java 9
  2. IDEs should support new Java versions as programming language -i.e. Incremental compilation, linting, text analysis, modules-
  3. IDEs are also basis for an ecosystem of plugins that are developed independently. Hence if plugins have any transitive dependency with issues over JPMS and/or internal classes, these also have to be updated

Overall, none of the Java IDEs guaranteed that plugins will work in JVMs above Java 8. Therefore you could possibly run your IDE over Java 11 but a legacy/deprecated plugin could prevent you to run your application.

How Do I Update?

You must notice that Java 9 launched three years ago, hence the situations previously described are mostly covered. However you should do the following verifications and actions to prevent failures in the process:

  1. Verify server compatibility
  2. Verify if you need a specific JVM due support contracts and conditions
  3. Configure your development environment to support multiple JVMs during the migration process
  4. Verify your IDE compatibility and update
  5. Update Maven and Maven projects
  6. Update dependencies
  7. Include Java/Jakarta EE dependencies
  8. Execute multiple JVMs in production

Verify Server Compatibility

Cat cartoon

Mike Luikides from O'Reilly affirms that there are two types of programmers. In one hand we have the low level programmers that create tools as libraries or frameworks, and on the other hand we have developers that use these tools to create experience, products and services.

Java Enterprise is mostly on the second hand, the "productive world" resting in giant's shoulders. That's why you should check first if your runtime or framework already has a version compatible with Java 11, and also if you have the time/decision power to proceed with an update. If not, any other action from this point is useless.

The good news is that most of the popular servers in enterprise Java world are already compatible, like:

  • Apache Tomcat.
  • Apache Maven.
  • Spring.
  • Oracle WebLogic.
  • Payara.
  • Apache TomEE.
    ... among others.

If you happen to depend on non compatible runtimes, this is where the road ends unless you support the maintainer to update it.

Verify if You Need a Specific JVM

Issues fixed in JDK 15 per organization

On a non-technical side, under support contract conditions you could be obligated to use an specific JVM version.

OpenJDK by itself is an open source project receiving contributions from many companies (being Oracle the most active contributor), but nothing prevents any other company to compile, pack and TCK other JVM distribution as demonstrated by Amazon Correto, Azul Zulu, Liberica JDK, etc.

In short, there is software that technically could run over any JVM distribution and version, but the support contract will ask you for a particular version. For instance:

  • WebLogic is only certified for Oracle HotSpot and GraalVM
  • SAP Netweaver includes by itself SAP JVM

Configure Your Development Environment to Support Multiple JDKs

Since the jump from Java 8 to Java 11 is mostly an experimentation process, it is a good idea to install multiple JVMs on the development computer, being SDKMan and jEnv the common options:

SDKMan

SDK Man

SDKMan is available for Unix-Like environments (Linux, Mac OS, Cygwin, BSD) and as the name suggests, acts as a Java tools package manager.

It helps to install and manage JVM ecosystem tools -e.g. Maven, Gradle, Leiningen- and also multiple JDK installations from different providers.

jEnv

jEnv logo

Also available for Unix-Like environments (Linux, Mac OS, Cygwin, BSD), jEnv is basically a script to manage and switch multiple JVM installations per system, user and shell.

If you happen to install JDKs from different sources -e.g Homebrew, Linux Repo, Oracle Technology Network- it is a good choice.

Finally, if you use Windows the common alternative is to automate the switch using .bat files however I would appreciate any other suggestion since I don't use Windows so often. 

Verify Your IDE Compatibility and Update

Please remember that any IDE ecosystem is composed by three levels:

  1. The IDE acting as platform
  2. Programming language support
  3. Plugins to support tools and libraries

After updating your IDE, you should also verify if all of the plugins that make part of your development cycle work fine under Java 11.

Update Maven and Maven Projects
Maven logo

Probably the most common choice in Enterprise Java is Maven, and many IDEs use it under the hood or explicitly. Hence, you should update it.

Besides installation, please remember that Maven has a modular architecture and Maven modules version could be forced on any project definition. So, as rule of thumb you should also update these modules in your projects to the latest stable version.

To verify this quickly, you could use versions-maven-plugin:

XML
 




xxxxxxxxxx
1


 
1
<plugin>
2
      <groupId>org.codehaus.mojo</groupId>
3
      <artifactId>versions-maven-plugin</artifactId>
4
      <version>2.8.1</version>
5
</plugin>



Which includes a specific goal to verify Maven plugins versions:

Shell
 




xxxxxxxxxx
1


 
1
mvn versions:display-plugin-updates



After that, you also need to configure Java source and target compatibility, generally this is achieved in two points.

As properties:

XML
 




xxxxxxxxxx
1


 
1
<properties>
2
        ...
3
    <maven.compiler.source>11</maven.compiler.source>
4
    <maven.compiler.target>11</maven.compiler.target>
5
</properties>



As configuration on Maven plugins, specially in maven-compiler-plugin:

XML
 




xxxxxxxxxx
1


 
1
<plugin>
2
    <groupId>org.apache.maven.plugins</groupId>
3
    <artifactId>maven-compiler-plugin</artifactId>
4
    <version>3.8.0</version>
5
    <configuration>
6
        <release>11</release>
7
    </configuration>
8
</plugin>



Finally, some plugins need to "break" the barriers imposed by Java Modules and Java Platform Teams knows about it. Hence JVM has an argument called illegal-access to allow this, at least during Java 11.

This could be a good idea in plugins like surefire and failsafe which also invoke runtimes that depend on this flag (like Arquillian tests):

XML
 




xxxxxxxxxx
1
20


 
1
<plugin>
2
    <groupId>org.apache.maven.plugins</groupId>
3
    <artifactId>maven-surefire-plugin</artifactId>
4
    <version>2.22.0</version>
5
    <configuration>
6
        <argLine>
7
            --illegal-access=permit
8
        </argLine>
9
    </configuration>
10
</plugin>
11
<plugin>
12
    <groupId>org.apache.maven.plugins</groupId>
13
    <artifactId>maven-failsafe-plugin</artifactId>
14
    <version>2.22.0</version>
15
    <configuration>
16
        <argLine>
17
            --illegal-access=permit
18
        </argLine>
19
    </configuration>
20
</plugin>


Update Project Dependencies

As mentioned before, you need to check for compatible versions on your Java dependencies. Sometimes these libraries could introduce breaking changes on each major version -e.g. Flyway- and you should consider a time to refactor this changes.

Again, if you use Maven versions-maven-plugin has a goal to verify dependencies version. The plugin will inform you about available updates.:

Shell
 




xxxxxxxxxx
1


 
1
mvn versions:display-dependency-updates



Kotlin intro demo in shell

In the particular case of Java EE, you already have an advantage. If you depend only on APIs -e.g. Java EE, MicroProfile- and not particular implementations, many of these issues are already solved for you.

Include Java/Jakarta EE Dependencies

jakarta environment

Probably modern REST based services won't need this, however in projects with heavy usage of SOAP and XML marshalling is mandatory to include the Java EE modules removed on Java 11. Otherwise your project won't compile and run.

You must include as dependency:

  • API definition
  • Reference Implementation (if needed)

At this point is also a good idea to evaluate if you could move to Jakarta EE, the evolution of Java EE under Eclipse Foundation.

Jakarta EE 8 is practically Java EE 8 with another name, but it retains package and features compatibility, most of application servers are in the process or already have Jakarta EE certified implementations:

We could swap the Java EE API:

XML
 




xxxxxxxxxx
1


 
1
<dependency>
2
    <groupId>javax</groupId>
3
    <artifactId>javaee-api</artifactId>
4
    <version>8.0.1</version>
5
    <scope>provided</scope>
6
</dependency>



For Jakarta EE API:

XML
 




xxxxxxxxxx
1


 
1
<dependency>
2
    <groupId>jakarta.platform</groupId>
3
    <artifactId>jakarta.jakartaee-api</artifactId>
4
    <version>8.0.0</version>
5
    <scope>provided</scope>
6
</dependency>



After that, please include any of these dependencies (if needed):

Java Beans Activation

Java EE

XML
 




xxxxxxxxxx
1


 
1
<dependency>
2
    <groupId>javax.activation</groupId>
3
    <artifactId>javax.activation-api</artifactId>
4
    <version>1.2.0</version>
5
</dependency>



Jakarta EE

XML
 




xxxxxxxxxx
1


 
1
<dependency>
2
    <groupId>jakarta.activation</groupId>
3
    <artifactId>jakarta.activation-api</artifactId>
4
    <version>1.2.2</version>
5
</dependency>


JAXB (Java XML Binding)

Java EE

XML
 




xxxxxxxxxx
1


 
1
<dependency>
2
    <groupId>javax.xml.bind</groupId>
3
    <artifactId>jaxb-api</artifactId>
4
    <version>2.3.1</version>
5
</dependency>



Jakarta EE

XML
 




xxxxxxxxxx
1


 
1
<dependency>
2
    <groupId>jakarta.xml.bind</groupId>
3
    <artifactId>jakarta.xml.bind-api</artifactId>
4
    <version>2.3.3</version>
5
</dependency>



Implementation

XML
 




xxxxxxxxxx
1


 
1
<dependency>
2
    <groupId>org.glassfish.jaxb</groupId>
3
    <artifactId>jaxb-runtime</artifactId>
4
    <version>2.3.3</version>
5
</dependency>


JAX-WS

Java EE

XML
 




xxxxxxxxxx
1


 
1
<dependency>
2
    <groupId>javax.xml.ws</groupId>
3
    <artifactId>jaxws-api</artifactId>
4
    <version>2.3.1</version>
5
</dependency>



Jakarta EE

XML
 




xxxxxxxxxx
1


 
1
<dependency>
2
    <groupId>jakarta.xml.ws</groupId>
3
    <artifactId>jakarta.xml.ws-api</artifactId>
4
    <version>2.3.3</version>
5
</dependency>



Implementation (runtime)

XML
 




xxxxxxxxxx
1


 
1
<dependency>
2
    <groupId>com.sun.xml.ws</groupId>
3
    <artifactId>jaxws-rt</artifactId>
4
    <version>2.3.3</version>
5
</dependency>



Implementation (standalone)

XML
 




xxxxxxxxxx
1


 
1
<dependency>
2
    <groupId>com.sun.xml.ws</groupId>
3
    <artifactId>jaxws-ri</artifactId>
4
    <version>2.3.2-1</version>
5
    <type>pom</type>
6
</dependency>


Java Annotation

Java EE

XML
 




xxxxxxxxxx
1


 
1
<dependency>
2
    <groupId>javax.annotation</groupId>
3
    <artifactId>javax.annotation-api</artifactId>
4
    <version>1.3.2</version>
5
</dependency>



Jakarta EE

XML
 




xxxxxxxxxx
1


 
1
<dependency>
2
    <groupId>jakarta.annotation</groupId>
3
    <artifactId>jakarta.annotation-api</artifactId>
4
    <version>1.3.5</version>
5
</dependency>


Java Transaction

Java EE

XML
 




xxxxxxxxxx
1


 
1
<dependency>
2
    <groupId>javax.transaction</groupId>
3
    <artifactId>javax.transaction-api</artifactId>
4
    <version>1.3</version>
5
</dependency>



Jakarta EE

XML
 




x


 
1
<dependency>
2
    <groupId>jakarta.transaction</groupId>
3
    <artifactId>jakarta.transaction-api</artifactId>
4
    <version>1.3.3</version>
5
</dependency>


CORBA

In the particular case of CORBA, I'm aware of its adoption. There is an independent project in eclipse to support CORBA, based on Glassfish CORBA, but this should be investigated further.

Multiple JVMs in Production

If everything compiles, tests and executes. You did a successful migration.

Some deployments/environments run multiple application servers over the same Linux installation. If this is your case it is a good idea to install multiple JVMs to allow stepped migrations instead of big bang.

For instance, RHEL based distributions like CentOS, Oracle Linux or Fedora include various JVM versions:

bash terminal

Most importantly, If you install JVMs outside directly from RPMs(like Oracle HotSpot), Java alternatives will give you support:

current selection or type selection number

However on modern deployments probably would be better to use Docker, specially on Windows which also needs .bat script to automate this task. Most of the JVM distributions are also available on Docker Hub:

Docker Hub repository

Java (programming language) Java virtual machine Java EE XML mobile app Dependency Apache Maven Library

Published at DZone with permission of Víctor Orozco. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Using Lombok Library With JDK 23
  • Reading an HTML File, Parsing It and Converting It to a PDF File With the Pdfbox Library
  • Exploring Exciting New Features in Java 17 With Examples
  • How To Approach Dependency Management in Java [Video]

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!