Support for the `jakarta` namespace in Axon Framework 4.6
I don't blame you if you don't know what that means. Frameworks like Spring do a great job of preventing developers from knowing what's under the hood. That's the price to pay for convenience, I guess. But whether you are aware or not, most "modern & fancy" techs (Spring included) rely on some of the good old Java EE specifications and their respective implementations. So is Axon Framework. And there's been a long-ignored change in that space that we finally addressed.
The background
The above-mentioned significant change in the Java Enterprise space occurred a few years back. It's a consequence of Oracle donating Java EE to the Eclipse Foundation and the name changing to Jakarta EE. Since then, the larger Java community has been evolving the (42 as of Jakarta EE 10) specifications. Previously, many of the classes and interfaces defined in those specifications were located in sub-packages of the javax
package. The namespace was used in many XML schemas too. Unfortunately, Oracle and the Eclipse Foundation did not reach an agreement allowing the community to modify the javax
package namespace further. So in Jakarta EE 9, a replacement parent package was introduced - jakarta
. New versions of the specifications forced their implementations to, sooner or later, make a significant breaking change in the respective codebases. Unsurprisingly many postponed implementing the latest versions for as long as possible.
The overall impact area
The change had a massive impact on almost all projects. Here are just the most popular specs with breaking changes :
- Java Servlet
- Java Server Pages
- Java Faces
- Java Messaging
- CDI
- Java XML Binding
- Java XML Web Services
- EJB
- JAX-RS
- JPA
- JTA
If you are curious, here is an almost complete list of what needs to be replaced with what.
The problem is manageable for products directly using one or a few specs. The true nightmare is when you depend on several libraries that exchange objects in those namespaces. It's not possible to upgrade one without upgrading all the others. This means upgrades need to wait until all dependencies support the new namespaces.
The impact on Axon Framework
Most of the specifications mentioned above are out of the scope of Axon Framework. However, some features (state-stored aggregates, tracking tokens, persisting projections, etc.) use the JPA and JTA specifications to allow developers to put data in and query from relational databases. In such cases, the framework expects developers to add respective dependencies and configure proper instances of javax.persistence.EntityManager
, javax.transaction.TransactionManager
, and similar types. This is where the usage of the old namespace introduces issues. For example, it is impossible to use Axon Framework 4.5.x or earlier with newer versions of Hibernate (6.0.0 onwards). Furthermore, using any 3rd party libraries depending on the newer JPA and JTA implementations is also next to impossible.
As if that is not enough, the apparent solution - changing the package names - is not a solution. Doing so would make it impossible to use older versions of any 3rd party libraries and frameworks that still depend on the javax
packages. The most notable example is Spring Framework. Thus, there needs to be a solution that allows developers to pick which package names they want to use.
The solution
As you may know, Axon Framework is a modular framework. Doing some analysis revealed that the namespace change impacts only three modules. Namely:
messaging
modeling
eventsourcing
So, much like many other frameworks, we decided to build and release a <NAME>-jakarta
versions of those. But that introduces a problem with maintainability and evolvability. Duplicating the code means every functional change touching those areas would have to be done twice. Every test covering those areas would have to be cloned too.
Solving problems like this is where Eclipse Transformer comes in handy. This great tool (kudos to BJ Hargrave and everyone who worked on it) allows you to transform Java binaries, making changes to packages, type names, and related resource names. And it works like a charm. If you look at the source code of messaging-jakarta, modelling-jakarta, and eventsourcing-jakarta modules, you'll see nothing more than a POM and some properties. During build time, the Maven plug-in uses the classes compiled by the original modules, replaces the names in the bytecode, and generates the respective <NAME>-jakarta
versions. It also does this to the test classes, enabling us to run all the existing tests with the new namespaces. We went even further and applied the same approach to the integrationtests-jakarta
module to ensure proper end-to-end testing after the bytecode changes.
How to use it
There are two popular ways to include Axon Framework in a project.
If you are using Spring/SpringBoot, nothing really changes. At the time of writing, the Spring Framework does not support the jakarta
namespace (according to their announcement, the change is planned for version 6, scheduled for Q4 2022). Thus the respective Spring modules in Axon Framework still depend on the original messaging
, modeling
, and eventsourcing
modules.
If you are configuring Axon Framework yourself, starting with version 4.6.0, you have two options. You could keep using the original config
module and stick to the javax
namespace. To use the jakarta
namespace, you simply replace the dependency in your POM with the config-jakarta
module. That's it - an eight symbols difference.
What the future holds
I'm super happy and proud we found a way to introduce such a valuable improvement in a non-invasive, backward-compatible way without increasing the maintenance efforts.
Assuming there are no significant hidden drawbacks waiting to be discovered, we'll stick to the approach for the upcoming releases. Long-term though, we'll likely make the jakarta
namespace the default. Especially when we start providing support for Spring 6, that will be a necessary and expected move. Whether, at that point, there will still be a need for support for javax
packages remains to be seen. We may, for example, reverse the process and provide <NAME>-javax
autogenerated backward-compatible modules if that is the case.
What's even more exciting about the future is that now we can help developers in many more ecosystems. The work on a Jakarta CDI 4 compatible extension is already in progress. I can't wait to see Axon Framework providing location transparency in various Quarkus, Micronaut, and Helidon microservices. Or be used to design the domain model or provide valuable "memories" to enterprise solutions based on one of the many Jakarta EE implementations.
I'll keep you posted as things evolve. Stay tuned!
