Polymorphic Aggregate Migration

Polymorphic aggregates allow you to define a hierarchy where subtypes inherit command and event sourcing handlers from their superclasses. For a detailed guide on how to model these, please refer to the modeling section.

Let’s take a look at the following example:

public abstract class Card {}

public class GiftCard extends Card {}

public class OpenLoopGiftCard extends GiftCard {}
public class RechargeableGiftCard extends GiftCard {}

In Axon Framework 4, polymorphic aggregates were often configured using Spring’s @Aggregate annotation on both the base and subclasses. When using the manual configuration API, you would use AggregateConfigurer.

In Axon Framework 5, you register the hierarchy through the EventSourcingConfigurer.

  • Axon Framework 5 (Declarative)

  • Axon Framework 5 (AutoDetected)

  • Axon Framework 4

public class AxonConfig {
    // ...
    public void configure(EventSourcingConfigurer configurer) {
         configurer.registerEntity(
                EventSourcedEntityModule.declarative(String.class, GiftCard.class)
                        .messagingModel((configuration, builder) -> PolymorphicEntityMetamodel.forSuperType(GiftCard.class)
                                .addConcreteType(AnnotatedEntityMetamodel.forConcreteType(
                                        OpenLoopGiftCard.class,
                                        configuration.getComponent(ParameterResolverFactory.class),
                                        configuration.getComponent(MessageTypeResolver.class),
                                        configuration.getComponent(MessageConverter.class),
                                        configuration.getComponent(EventConverter.class)
                                ))
                                .addConcreteType(AnnotatedEntityMetamodel.forConcreteType(
                                        RechargeableGiftCard.class,
                                        configuration.getComponent(ParameterResolverFactory.class),
                                        configuration.getComponent(MessageTypeResolver.class),
                                        configuration.getComponent(MessageConverter.class),
                                        configuration.getComponent(EventConverter.class)
                                ))
                                .build())
        );
                                    // other phases (factory, etc.) omitted for brevity
    }
}

In most cases, you can rely on auto-detection of polymorphic entities by Axon Framework 5. Simply register the base type, and the framework will discover the subtypes automatically.

@EventSourcedEntity(
    concreteTypes = {
            OpenLoopGiftCard.class,
            RechargeableGiftCard.class
    }
)
public class GiftCard extends Card {
    // ...
}

public class AxonConfig {
    // ...
    public void configure(EventSourcingConfigurer configurer) {
        configurer.registerEntity(
                EventSourcedEntityModule.autodetected(String.class, GiftCard.class)
        );
    }
}
public class AxonConfig {
    // ...
    public void configure(Configurer configurer) {
        Set<Class<? extends GiftCard>> subtypes = Set.of(
            OpenLoopGiftCard.class,
            RechargeableGiftCard.class
        );

        configurer.configureAggregate(
            AggregateConfigurer.defaultConfiguration(GiftCard.class)
                               .withSubtypes(subtypes)
        );
    }
}