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 entity polymorphism reference.
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
import org.axonframework.eventsourcing.EventSourcedEntityFactory;
import org.axonframework.eventsourcing.configuration.EventSourcedEntityModule;
import org.axonframework.eventsourcing.configuration.EventSourcingConfigurer;
import org.axonframework.messaging.core.MessageTypeResolver;
import org.axonframework.messaging.core.annotation.ParameterResolverFactory;
import org.axonframework.messaging.core.conversion.MessageConverter;
import org.axonframework.messaging.eventhandling.conversion.EventConverter;
import org.axonframework.messaging.eventstreaming.EventCriteria;
import org.axonframework.messaging.eventstreaming.Tag;
import org.axonframework.modelling.entity.PolymorphicEntityMetamodel;
import org.axonframework.modelling.entity.annotation.AnnotatedEntityMetamodel;
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())
.entityFactory(c -> EventSourcedEntityFactory.fromNoArgument(OpenLoopGiftCard::new))
.criteriaResolver(c -> (id, ctx) -> EventCriteria.havingTags(Tag.of("cardId", id)))
.build()
);
}
}
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.
import org.axonframework.eventsourcing.annotation.EventSourcedEntity;
import org.axonframework.eventsourcing.annotation.reflection.EntityCreator;
import org.axonframework.eventsourcing.annotation.reflection.InjectEntityId;
@EventSourcedEntity(
tagKey = "cardId",
concreteTypes = {
OpenLoopGiftCard.class,
RechargeableGiftCard.class
}
)
public class GiftCard extends Card {
// ...
@EntityCreator
protected GiftCard(@InjectEntityId String cardId) {
// ...
}
}
import org.axonframework.eventsourcing.configuration.EventSourcedEntityModule;
import org.axonframework.eventsourcing.configuration.EventSourcingConfigurer;
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)
);
}
}
See also
-
Polymorphic Entities: full reference for
@EventSourcedEntity(concreteTypes = {…}), the@EntityCreatorfactory pattern, andPolymorphicEntityMetamodelconfiguration in Axon Framework 5