Upgrading to Axon Framework 4.7

Breaking Changes...Our Apologies

Different than usual, upgrading to Axon Framework 4.7.x may just impact your application.
To deal with the Javax-to-Jakarta adjustment, we introduced several dedicated modules in Axon Framework 4.6.
However, this approach, combined with our desire to support Spring Framework 6 and Spring Boot 3, did not work ideally enough in our eyes. 

From a Framework management perspective, but more importantly, also for a general user experience with Axon.

As such, we have moved away from this solution in favor of introducing specific Javax and Jakarta versions of the Framework’s JPA infrastructure components.
Although this makes the Framework flexible enough to support several approaches, it likely means you will face breaking changes.
For that, we want to extend our apologies, as this differs from our desired approach towards minor releases.

Having shared this, we think it is paramount to provide some level of guidance to help you traverse the migration toward the 4.7 release of Axon Framework.
To that end, we can deduce a few reasonable scenarios, which we will list below.
Additionally, you can find a more to-the-point approach in our Reference Guide.

Note that regardless of the scenario you’re on, it is generally helpful to adjust incrementally and be well-prepared.
For example, upgrading from Spring Boot 2.5 to 3.0 right away may cause issues that would’ve been clear if you first upgraded to 2.7.
Lastly, the scenarios do not contain a migration path from Jakarta to Javax, as this is not a recommended scenario to be in.

Migration Automation

If you want help with migrating to any of the following scenarios, you can roughly take two routes:

  1. Follow the description and make all changes manually

  2. Use the Axon Framework 4.7 OpenRewrite recipes described in this blog.

Option one has the benefit that you're in full control.
And you know all of the adjustments you need to make.
However, option two will greatly simplify your upgrade to Axon Framework 4.7. 
Please take both into consideration, selecting the most feasible option for your environment.

Scenario 1: Upgrading to 4.7, sticking with Javax

If you want to upgrade to Axon Framework 4.7 but refer to stay (for the time being) on Javax because you, for example, remain on Spring Boot 2, you need to take into account the following adjustments:

  • First and foremost, if you do not have any manual configuration at all, as may be the case when you’re using the Framework’s starter, upgrading should be as simple as changing the version number.
    This holds as we have adjusted the axon-spring-boot-starter to deal with both Spring Boot 2 and Spring Boot 3.

  • Axon Framework’s classes using Javax Persistence, either explicitly (based on the package name containing jpa) or implicitly (as per used dependencies), have been moved to dedicated legacyjpa directories.

  • Thus, if you configured the 'JpaTokenStore' manually, for example, you will need to use the deprecated 'JpaTokenStore' from the legacy package.
    Similarly, if you have constructed a customized 'JpaEventStorageEngine', you must adjust your import statements accordingly.

  • Axon Framework’s classes using Javax Validation have been moved to dedicated legacyvalidation directories.
    Thus, if you configured the 'BeanValidationInterceptor' manually, for example, you will need to use the deprecated 'BeanValidationInterceptor' from the legacy package.

  • The 'TokenEntry' no longer extends from the 'AbstractTokenEntry' class, which was a necessary evil to comply with Hibernate 6.
    If you have customized the 'TokenEntry' or 'AbstractTokenEntry', either in code or through configuration (like an orm.xml file), you will be required to rebase your changes on the current 'TokenEntry'.

  • The 'SagaEntry' no longer extends from the 'AbstractSagaEntry' class, which was a necessary evil to comply with Hibernate 6.
    If you have customized the 'SagaEntry' or 'AbstractSagaEntry', either in code or through configuration (like an orm.xml file), you will be required to rebase your changes on the current 'SagaEntry'.

For your convenience, we have added an exhaustive list of all “old” JPA and Javax Validation infrastructure components in the appendix of this blog.

Scenario 2: Upgrading to 4.7, sticking with Jakarta

If you want to upgrade to Axon Framework 4.7 and were already using jakarta, that likely means you used the Framework’s [module-name]-jakarta modules.
Note that these have been removed in the 4.7 release entirely in favor of adjusting the Javax infrastructure components for Jakarta variants. 

As such, your sole change should be to replace the Jakarta-specific Axon Framework module you depend on with the default module.
So, if you, for example, depended on axon-messaging-jakarta, you can now depend on axon-messaging directly.

Scenario 3: Upgrading to 4.7, and upgrading to Jakarta

If you want to upgrade to Axon Framework 4.7 and want to start moving towards the Jakarta namespace because you, for example, want to upgrade to Spring Boot 3 as well, please take the following pointers into consideration:

  • As the Framework’s “old” Javax components are replaced for Jakarta variants, you will not have to adjust any import statements or dependencies from the Framework.

  • When using Spring Framework and/or Spring Boot, you will want to move to Spring Framework 6 and Spring Boot 3 too.
    Axon Framework will automatically wire the right beans if you’re using our starter dependency.
    Be certain to use the latest versions when possible, which ensures you benefit from the latest patches.
    Note that this shift will also require you to upgrade to JDK17 or higher.
    Some useful links are the Spring documentation, this Spring Cloud post, and this post from javatechonline.com, for example.

  • When you are using Hibernate in your project, you need to upgrade it to version 6 or higher to move to the Jakarta namespace.
    The most impact this shift has on your Framework application is how version 6 constructs a default sequence generator.
    In Hibernate 5 and below, the absence of sequence generator configuration led to a HIBERNATE_SEQUENCE that’s used for all your entities.
    There are two tables in Axon Framework using a sequence generator, which are the domain_event_entry (for all your events) and association_value_entry (for Saga associations) tables.
    In Hibernate 6, this behavior changed towards constructing a dedicated sequence generator per entity name [entity-name]_SEQ.
    In Axon Framework, you would thus get a DOMAIN_EVENT_ENTRY_SEQ and ASSOCIATION_VALUE_ENTRY_SEQ.
    Henceforth, if you have not defined dedicated sequences for either of these entities and upgraded to Hibernate 6, you end up with new sequences starting at zero.
    This will have an extensive impact on how your Event Store behaves, as Axon uses the sequences of the DOMAIN_EVENT_ENTRY to form a global ordering of your events.
    Hence, you are inclined to correctly define your sequence generators for (at least) the even- and association-value tables.
    Ideally, you should define a dedicated sequence generator per table you have.
    If this is not in place, the easiest way forward is to disable this behavior from Hibernate 6.
    In a Spring Boot application, you can, for example, achieve this by setting the spring.jpa.properties.hibernate.id.db_structure_naming_strategy to legacy.
    You can check out this migration guide for more specifics on migration to Hibernate 6.

  • Although this should go without saying, it is recommended you look for any Javax mentions in your code base and replace those with Jakarta equivalents.

Scenario 4: Greenfield Axon Framework project

You have nothing to worry about in this case.
You can use the latest version of Axon Framework, combined with Javax or Jakarta, and Spring Boot 2 (if you’re on Javax!) or Spring Boot 3.
Do note that if you want to use Spring Boot 3, you are inclined to use JDK17 or higher.

Conclusion

In the previous sections, we have explained why we feel this breaking change, although against our regular tendencies, was required.
Furthermore, we described several scenarios you may have when you want to use Axon Framework 4.7.
Each of these contains a list of the most important things to consider when upgrading.

If any questions remain, please reach out to us!
We aim to make this upgrade as straightforward as possible, so knowing the struggles you're in will help us improve this guide.

Appendix - Legacy Infrastructure Components

Note that to shorten the contents, we replaced org.axonframework for * in the tables below.

Javax Persistence

Axon Framework 4.6 Axon Framework 4.7
*.common.jpa.EntityManagerProvider *.common.legacyjpa.EntityManagerProvider
*.common.jpa.PagingJpaQueryIterable *.common.legacyjpa.PagingJpaQueryIterable
*.common.jpa.SimpleEntityManagerProvider *.common.legacyjpa.SimpleEntityManagerProvider
*.eventhandling.deadletter.jpa.DeadLetterJpaConverter *.eventhandling.deadletter.legacyjpa.DeadLetterJpaConverter
*.eventhandling.deadletter.jpa.EventMessageDeadLetterJpaConverter *.eventhandling.deadletter.legacyjpa.EventMessageDeadLetterJpaConverter
*.eventhandling.deadletter.jpa.JpaDeadLetter *.eventhandling.deadletter.legacyjpa.JpaDeadLetter
*.eventhandling.deadletter.jpa.JpaSequencedDeadLetterQueue *.eventhandling.deadletter.legacyjpa.JpaSequencedDeadLetterQueue
*.eventhandling.tokenstore.jpa.JpaTokenStore *.eventhandling.tokenstore.legacyjpa.JpaTokenStore
*.eventsourcing.eventstore.jpa.JpaEventStorageEngine *.eventsourcing.eventstore.legacyjpa.JpaEventStorageEngine
*.eventsourcing.eventstore.jpa.SQLErrorCodesResolver *.eventsourcing.eventstore.legacyjpa.SQLErrorCodesResolver
*.modelling.command.GenericJpaRepository *.modelling.command.legacyjpa.GenericJpaRepository
*.modelling.saga.repository.jpa.JpaSagaStore *.modelling.saga.repository.legacyjpa.JpaSagaStore
*.springboot.autoconfig.JpaAutoConfiguration *.springboot.autoconfig.legacyjpa.JpaJavaxAutoConfiguration
*.springboot.autoconfig.JpaEventStoreAutoConfiguration *.springboot.autoconfig.legacyjpa.JpaJavaxEventStoreAutoConfiguration
*.springboot.util.jpa.ContainerManagedEntityManagerProvider *.springboot.util.legacyjpa.ContainerManagedEntityManagerProvider

 

Javax Validation

Axon Framework 4.6 Axon Framework 4.7
*.messaging.interceptors.BeanValidationInterceptor *.messaging.interceptors.legacyvalidation.BeanValidationInterceptor
*.messaging.interceptors.JSR303ViolationException *.messaging.interceptors.legacyvalidation.JSR303ViolationException
 
 
Steven van Beelen
Lead Developer - Axon Framework. Steven has a keen interest in Axon Framework and how it approaches software architecture. He helps small and large clients build Axon applications, provides training, develops the framework and is active in the Axon community. Broader interests include domain driven design, messaging patterns and event sourcing.
Steven van Beelen

Share: