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

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

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

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

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Related

  • Java EE 6 Pet Catalog with GlassFish and MySQL
  • How to Embed a jBPM Process in a Java EE Application
  • Managed Scheduled Executor Service vs EJB Timer
  • What Do We Know About Tomcat 9.0

Trending

  • Navigating Change Management: A Guide for Engineers
  • Dropwizard vs. Micronaut: Unpacking the Best Framework for Microservices
  • Building an AI/ML Data Lake With Apache Iceberg
  • Simplifying Multi-LLM Integration With KubeMQ
  1. DZone
  2. Coding
  3. Java
  4. A Systematic Approach for Java Software Upgrades

A Systematic Approach for Java Software Upgrades

Old is gold, and this is true in the case of software systems too. But, you need to keep them updated. This writing guides you in upgrading software systems.

By 
Binildas Christudas user avatar
Binildas Christudas
·
Mar. 25, 25 · Analysis
Likes (1)
Comment
Save
Tweet
Share
4.5K Views

Join the DZone community and get the full member experience.

Join For Free

The amount of business logic embedded in the form of code in software systems is so huge and valuable that you don’t always need to think in terms of replacing them with entirely new systems. Rather, software systems should facilitate evolution both in terms of functionality and in terms of technological upgrades. 

This is truer in transactional systems, especially in domains including, but not limited to, finance, travel, transportation, logistics (TTL), and e-commerce. While much literature has been written about how to manage functional changes in software applications, technology upgrades are non-trivial, and many times, developers are left out to try and test their own intuition. 

In this writing, we attempt to lay out how a systematic approach can bring more definitiveness not only to the engineering process for software upgrades but also to other aspects of it, especially in acting as an aid for the estimation process for upgrade projects. Though we use Java as a language paradigm for our discussions, all or many of the approaches are applicable to other programming language scenarios, too.

Setting the Context

Our organization is in the business of providing SaaS-based products worldwide for the TTL industry. The mainstream products use new-generation technology and architecture and can accommodate multi-tenancy in the same runtime process operated from the public cloud. 

Our organization also provides services for customer-built and customer-operated solutions. At times, due to customer-specific needs and preferences and since the customer organization is large and has its own IT upgrade and lifecycle timelines, they have not been upgrading the underlying technology to match the industry’s pace.

We have been recently working on a Software upgrade project whose original version was written more than a decade ago. The application is being used for a subdomain of the Airline operations by one of the Airline companies. This application has been built using Java and the J2EE (Java 2 Enterprise Edition) technologies, leveraging Struts for the presentation tier, EJB (Enterprise Java Beans) 2.0 as the middle tier technology, and using Oracle RAC (Real Application Cluster) in the persistence layer. 

There are more than a dozen other software libraries and components, most of them from the OSS (Open-Source Software) world. While the customer organization has already put up a roadmap for shifting business functionality using the latest software stack and architecture, the immediate requirement is to do all essential technology upgrades in the currently running codebase and keep the application running till the release of the new product.

Figure 1 lists the different technologies used by the application.

Figure 1: As Is Technology Landscape

Figure 1: As Is Technology Landscape


As you can see in Figure 1, the top portion of the list enumerates the main components and libraries, whereas the bottom portion of the list enumerates the various runtime and platform technologies used to host the application. Though Spring is listed as a component here, it’s used for a planetary and standalone module, not as a container for the main application.

As mentioned already, the objective is to do a technology refresh without any change in business functionality. A technology refresh is a structured initiative aimed at updating the software system to a newer version. This may involve upgrading the application, framework and components, operating system, database, or any other software component to improve functionality, security, and/or performance. 

To rephrase, a technology refresh is not a complete trial-and-error method but instead a structured and systematic way of planning the target versions of the various software elements involved. The subsequent sections will walk you through one feasible approach we adopted for doing the same.

Java Upgrade

Java was created at Sun Microsystems, Inc., where James Gosling and team worked with the intention of creating a new language that would allow consumer electronic devices to communicate with each other. 

Even though work on the language began in 1991, the early version of Java was released in 1995 and has come a long way since its inception, and with each release, it brings new features and improvements that enhance programming flexibility, capability, and performance.

Java 25, the next Long-Term-Support (LTS) version of the Java language and runtime platform, will be officially released in September 2025. Figure 2 illustrates the published roadmap for Java SE support.

Figure 2: Oracle Java SE Support Roadmap (Note: Adapted from Oracle)

Figure 2: Oracle Java SE Support Roadmap (Note: Adapted from Oracle)


As of today, the option is to target Java 21, which has extended support until September 2031. Remember that our objective is to do all essential technology upgrades in the currently running codebase and keep the application running till the release of the new product for which 2031 gives us a clear 5-year extended life for the application from today (2025), which should be sufficiently enough by which the new product will be cut over.

Replacements for Deprecated Modules With Java EE APIs

Java EE comprises the legacy of Java EE development, including Java EE Platform version 8. Even though the code is developed by Oracle, it is generally only available as history archives. 

So, to adopt an active Enterprise Java development platform, you need to transition to the Eclipse Foundation Jakarta EE. Jakarta EE is an open-source, cloud-native Java platform for enterprise applications governed by the Eclipse Foundation, which is the successor to Java EE (Java Platform, Enterprise Edition) previously maintained by Oracle under the JCP (Java Community Process). In 2017, Oracle transferred Java EE to the Eclipse Foundation, leading to its rebranding as Jakarta EE. 

During 2020, Jakarta EE 9 brought the Namespace changes (javax.* → jakarta.*). While EJB 3.0 (Java EE 5, 2006) uses the javax.ejb package, the later EJB 4.0 (Jakarta EE 9, 2020) uses the jakarta.ejb package as part of the Jakarta EE transition. 

In Figure 1, you can see that EJB 2.0 is the current specification adopted, and the application has been deployed in the WildFly Application container 10.1.0. WildFly has progressively reduced support for many legacy technologies, including those for EJB 2.x. While it continues to support EJB 2.x MDBs (Message Driven Beans) and stateful and stateless session beans, it no longer supports CMP (Container Managed Persistence) or EJB 2.x entity beans. 

Since the application depends on EJB 2.0, you need to consider using an older version of WildFly that still supports these features. This will make the upgrade project meaningless. The alternative is to update the application to use more recent versions of the EJB specification, such as EJB 3.x, which would enhance compatibility with the latest WildFly releases.

Approach for EJB Upgrade

Having thought about a sketch for the EJB upgrade, the next logical step is to think about how to go about in effecting the upgrade. In 2013, EJB specification 3.2 was released as a part of Java EE 7. This spec aligns with JPA 2.1. (Java Persistence API). For ease of development and to minimize boilerplate code, Hibernate is widely used as a JPA implementation. 

As of this writing, Hibernate 6.6 is the latest stable version. However, you should limit your urge to target this version for the upgrade for the time being. Instead, you should target Hibernate 4.3 since it was the first version to provide complete support for JPA 2.1, ensuring easy integration with EJB 3.2 components. We will look at this again towards the end of our discussion.

Application Container Upgrade

As discussed earlier, we have a compelling need to target Java 21. The earliest version of WildFly that supports Java SE 21 is WildFly 30, which was released in October 2023. WildFly 35 is the current version. For a reason like the decision on the target version of Hibernate, we will tentatively fix the target version of WildFly to be WildFly 30 (Not WildFly 35), or some version greater than 30.

The analysis so far is based on previous experience and on information available from different websites of the library providers. As you can see, by deciding that we need to update the application to use more recent versions of the EJB specification, such as EJB 3.x, we are able to provide initial estimates for the upgrade project which could also accommodate the efforts required to do code changes to comply to EJB 3.x API and deployment schemas.

Now, there is the next question: “Why can’t we target the latest available versions for Hibernate, WildFly, etc.?”

How do we answer this question?

Container Version vs. Component Version Dilemma

In Figure 1, the top portion of the list enumerates the different components and libraries whereas the bottom portion of the list enumerates the various runtime and platform (aka container) technologies used to host the application. 

We need to have a strategy to finalize the target versions of all main containers as well as component technologies. Let us understand the challenge here with the help of Figure 3.

Figure 3: A structured approach to reveal version compatibility

Figure 3: A structured approach to reveal version compatibility


Figure 3 is an attempt to represent a superimposed view of the compatibility of various versions of the components or libraries with that of the runtime container or platform. Remember, this illustration is just representative, so do the various numbering (time and versions), nothing to do with the actuals.

Ideally, we would want the upgrade to target the latest versions of Java and WildFly, which are two separate vertically thick lines tending towards the right extreme of the diagram, black color for WildFly and blue color for Java. In the left extreme, we have listed the different components and libraries to be upgraded row-wise. Towards the middle, we have represented the general availability of various versions (v1, v2, v3, etc. in lower X-Axis) of each library as we traverse through the timeline (2025, 2026, 2027, etc. in upper X-Axis).

As of today (2025), we have an urge to upgrade the application since all or many of the library versions are outdated and hence pose a risk. This is shown by the red vertical strip. The dark green represents the availability of production releases of higher versions and the light green indicates that there is also a published roadmap available for later versions. 

Assuming our objective is to enhance the life of the currently running application for another 5 years (until 2030), if for some reason there are libraries with uncertainties (no release candidate available, nor even a published roadmap available) until 2030, then that poses a risk. Such risk areas are marked with an amber color in Figure 3. Suppose those libraries are mainstream OSS libraries with active community support. In that case, there is every reason to believe that those will be de-risked in the future (down the line 2 or 3 years) when the respective vendors or communities publish an extended roadmap.

Having understood this view, the next step is to assess the compatibility of various released versions of the components or libraries with that of the runtime container or platform. Assume that we are now at the start of the project's execution. Such an analysis during the start of the project will make the lines of Java and WildFly converge towards the left (again, just representative), indicative of the compatibility of the versions of Java and WildFly with those of each of the components and libraries. 

From this, we need to choose the minimum of the versions of Java and/or WildFly that are compatible with all or most of the components and libraries. Even though we need to choose the minimum of the versions of Java and/or WildFly, our objective should still be to “maximize the versions of Java and/or WildFly compatible with all or most of the components and libraries.” To restate this with respect to Figure 3, our objective should be to “minimize the concaveness of Java and/or WildFly lines.”

For example, if we start with Java 21 and WildFly 30 as our objective for the upgrade, we can still try out and check if a higher version of WildFly can still be chosen. Similarly, though we targeted Hibernate 4.3 as a minimum version, we can now attempt to see if a higher version of Hibernate could be adopted and so do with other libraries too. Figure 4 illustrates how the upgrade objective looks like with the learnings we have gained so far.

Figure 4: To Be Technology Landscape

Figure 4: To Be Technology Landscape


You need to appreciate that while some decisions on the upgrade projects could be made even before we start the project execution, a few other activities are iterative, and hence, you need to provision enough slack in the effort estimation. This is evident from Figure 4, where a few libraries are still in the state “To be analyzed,” which will get sorted out as we progress with the upgrade project.

Let us now list out how the typical project execution will progress, as follows:

  • Align the container runtime (WildFly) and programming platform (JEE, JSE) to versions supported until at least 2030.
  • Target the upgrade of libraries and components to the latest versions compatible with the container runtime.
  • Iterate: In case of library or component conflicts, target the next previous version (with a roadmap extending to or near 2030).
  • Perform regression and functional validation.
  • Conduct performance and endurance validations.
  • Assess and (re)size the infrastructure as needed.

As you can see, we have now moved from a complete trial-and-error-based approach to a more structured and systematic approach to plan and execute the technology upgrade of our application.

Conclusion

Technology upgrades of software applications are not green field projects most of the time. You need to carry the baggage of technology and architecture choices, and you still need to de-risk the running application from security, legal, and related business risks. 

A combination of previous experience and a structured approach can provide a great deal of definitiveness to the overall planning and execution of such upgrade projects. As mentioned earlier, many of the steps and processes discussed in this writing can be applied to projects in technologies other than Java, too.

Java EE Software application Java (programming language)

Opinions expressed by DZone contributors are their own.

Related

  • Java EE 6 Pet Catalog with GlassFish and MySQL
  • How to Embed a jBPM Process in a Java EE Application
  • Managed Scheduled Executor Service vs EJB Timer
  • What Do We Know About Tomcat 9.0

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!