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
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

Enterprise AI Trend Report: Gain insights on ethical AI, MLOps, generative AI, large language models, and much more.

2024 Cloud survey: Share your insights on microservices, containers, K8s, CI/CD, and DevOps (+ enter a $750 raffle!) for our Trend Reports.

PostgreSQL: Learn about the open-source RDBMS' advanced capabilities, core components, common commands and functions, and general DBA tasks.

AI Automation Essentials. Check out the latest Refcard on all things AI automation, including model training, data security, and more.

Related

  • Building a Performant Application Using Netty Framework in Java
  • Leveraging Java's Fork/Join Framework for Efficient Parallel Programming: Part 1
  • Five Java Developer Must-Haves for Ultra-Fast Startup Solutions
  • Java 11 to 21: A Visual Guide for Seamless Migration

Trending

  • PostgresML: Streamlining AI Model Deployment With PostgreSQL Integration
  • OWASP Top 10 Explained: SQL Injection
  • Python for Beginners: An Introductory Guide to Getting Started
  • Data Flow Diagrams for Software Engineering
  1. DZone
  2. Coding
  3. Java
  4. Converting ActiveMQ to Jakarta (Part II)

Converting ActiveMQ to Jakarta (Part II)

In this article, learn more about migrating a mature code base to Jakarta based on the impacts of the new Jakarta framework.

By 
Matt Pavlovich user avatar
Matt Pavlovich
·
Mar. 25, 24 · News
Like (1)
Save
Tweet
Share
257 Views

Join the DZone community and get the full member experience.

Join For Free

Many Java developers are staring down an upgrade to their applications due to the impacts of the new Jakarta framework. In Part I, I blogged an intro to Jakarta (DZone article, and original post) to provide a primer.

Straight forward, right? Just change all import javax.foo to import jakarta.foo and ship it! No? Oh dang.

Having recently gone through this exercise with a large and well-established open-source project that is at the core of the HYTE platform, I’m here to share. I believe my experience is representative of what many enterprise Java developers are also going through and wanted to share lessons learned and insights going through the process. Let's dive in.

Background

ActiveMQ is the most widely used messaging broker in the world. ActiveMQ is the engine that powers HYTE MQ which is the engine of HYTE’s Messaging Platform as a Service. The ActiveMQ code base is mature, with over 30 Maven modules, and covers a range of many of the most widely used Jakarta EE APIs. 

This Isn’t “Hello World”

Jumping straight to Jakarta was not a realistic option for ActiveMQ as it is widely adopted for messaging and integration infrastructure. A key feature of ActiveMQ is its ability to be easily embedded in unit tests which has led to many other open-source projects using it as a test dependency to certify those projects’ JMS integration capabilities. 

While the Jakarta namespace changes itself is very minor, the heavy lifting for a large existing Java-based code base is going to come from paying dues on any outstanding technical debt and then upgrading ActiveMQ to adopt changes in the specification.

ActiveMQ’s Technical Debt

Upgrading Supported JMS Version

Before making the namespace transition, ActiveMQ needed to modernize the supported JMS API version and upgrade support from the JMS 1.1 version to the JMS 2.0 version of the JMS API specification. This revision change is a decent-sized jump as it added a new set of API classes that allow for a simplified coding interface and runtime exceptions vs checked exceptions.

Fortunately, the JMS 2.0 API specification upgrade did not break or remove anything from the JMS 1.1 specification. This enabled an upgrade approach that could be readily followed in enterprise code bases as well. I’ll blog in more detail about this in a separate post. 

The Servlet specification did have breaking changes, as did Spring v5 to Spring v6. This meant that ActiveMQ’s code using these APIs and frameworks needed to be refactored.

Upgrading Frameworks

Large Java-based code bases will often rely on many other frameworks—especially in unit and integration tests. This presents a big challenge in converting a mature code base because not all frameworks are currently actively maintained or have a Jakarta-supported release. For example, some popular tools, such as Jolokia, do not have Jakarta-based releases. Others are in a chicken-and-egg problem (such as Apache Camel), where they have dependencies (usually for unit tests or integration tests) that need to have Jakarta-based releases before they can, in turn, provide a Jakarta-based release themselves.

Upgrading Jetty Version

Frameworks that made releases to support Jakarta did so appropriately in a major version upgrade. For example, ActiveMQ was using Jetty 9. To get a Jetty version that supported Jakarta namespaces, ActiveMQ needed to upgrade to Jetty v11. However, Jetty did not *only* change Jakarta namespaces between v9.x, v10.x and v11.x. Along the way, internal Jetty APIs changed. This means ActiveMQ needs to adopt those API changes at the same time as the Jakarta namespace change. If I had one do-over, it would be to adopt Jetty v10 in ActiveMQ 5.18.x and then level-set those API changes first. This would have reduced the scope and differences between the ActiveMQ 5.18.x and 6.0.x releases. Additionally, this would make any source tree management of back-ported patches easier.

Jetty Did Everything Right

ActiveMQ 5.x needed to make 2 major version jumps in Jetty releases to get to Jakarta. This is an example of a larger-than-expected effort where enterprise users will see the scope of Jakarta migrations keep creeping scope higher and taking longer than expected. In ActiveMQ’s case, the components that use Jetty are not critical paths for most users. The Jetty-based components support HTTP and web socket transports for clients. These are less frequently used and require fewer patches. Had the ActiveMQ components that required Jetty been in a critical path, or anticipated a high number of back-ports going forward, having an ActiveMQ 5.x release make the upgrade to Jetty 10 before starting the Jakarta transition would have been the better move. 

Curveball

While the ActiveMQ Jakarta migration work was in progress Jetty made the move to release a v12 that supported both javax.* and jakarta.* namespaces. Had Jetty 12.x been available at the start of the migration process, the decision would have been a no-brainer and both ActiveMQ 5.x and ActiveMQ 6.x would have moved to Jetty 12. This still may happen down the road.

The Path Taken

Step 1

Implement JMS 2.0 support in the non-Jakarta releases. ActiveMQ 5.18.x release includes the majority of JMS 2.0 features (see: Apache ActiveMQ JMS / Jakarta status page).

Step 2

Add a transitional client jar, so developers can begin to integrate their Jakarta-based client-side applications with the non-Jakarta-based ActiveMQ server side. The activemq-client-jakarta module was created as a simple repackaging of the standard activemq-client (which uses javax.jms namespace), but using the jakarta.jms namespace. This is a big win! Now, any application using ActiveMQ as a JMS client that needs Jakarta-based client capabilities is no longer blocked while waiting for the open-source project to complete the full Jakarta-based transition. Spring Boot’s v3.x ActiveMQ starter was updated to use the activemq-client-jakarta to provide transitional support to users for a few months until the full Jakarta-based ActiveMQ release was completed. 

Step 3

Analysis of the ActiveMQ broker-side support for Jakarta

Step 4

Refactor ActiveMQ for required changes. Pay down technical debt. Spring and Jetty changes. Remove and replace unmaintained dependencies.

Step 5

Modernize code base. Update language features for Java JDK 17, align Maven dependencies, etc.

Step 6

Release Jakarta-based ActiveMQ 6.0.0

Transition Approach Scope Creep

As users began to adopt the activemq-client-jakarta library released with Active 5.18.x, it became apparent that many users needed more than just the simple client jar to support Jakarta in their application. Applications following HYTE best practices would also need a Jakarta supported activemq-jms-pool project for connections to be pooled and refreshed over time. Addiitonally, users on legacy J2EE platforms needed the activemq-ra and activemq-rar modules to support Jakarta.

Additionally, many users use the ability to quickly embed an ActiveMQ broker in a unit test to run integration and smoke tests. Without a Jakarta-enabled broker, their application test suite would not pass. At this point, it became apparent that the best way forward was to get the full Jakarta release out the door. 

While the approach of creating a transitional client was designed to lessen the impact to end-users, it ended up having unforeseen impacts that would have delayed the full Jakarta-support had the ActiveMQ community gone down that path to support Jakarta libraries for activemq-jms-pool, activemq-ra, and activemq-rar.

Modernization Will Continue

ActiveMQ 6.x may introduce javax-based modules (ie activemq-client-javax and activemq-jms-pool-javax) to provide backward compatibility to javax.jms users and allow them to stay aligned with the going forward features, but those plans have not been formalized. For now, javax.jms users can use activemq-client from ActiveMQ 5.18.x and connect with an ActiveMQ 6.x broker and vice-versa.

 Jakarta and Java JDK releases will continue to iterate and provide value to coders. HYTE will continue to modernize ActiveMQ to adopt updates and language features that will benefit ActiveMQ users.

Getting over the big update to Jakarta sets up ActiveMQ for less impactful changes going forward.

Java Development Kit Framework Java (programming language)

Published at DZone with permission of Matt Pavlovich. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Building a Performant Application Using Netty Framework in Java
  • Leveraging Java's Fork/Join Framework for Efficient Parallel Programming: Part 1
  • Five Java Developer Must-Haves for Ultra-Fast Startup Solutions
  • Java 11 to 21: A Visual Guide for Seamless Migration

Partner Resources


Comments

ABOUT US

  • About DZone
  • Send 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: