I am fairly new to Axon and I am attempting to create an aggregate that can be deleted and recreated. I am using event sourcing and a deleted event is allowed. I am essentially maintaining a list of supported countries for the application. Currently, I am using a boolean, but I read somewhere there is a way to flag an aggregate as deleted instead? How does this work in Axon 3?
@Entity
@EqualsAndHashCode
@Aggregate(repository = "jpaCountryRepository")
@NoArgsConstructor
public class Country {
@Id
@AggregateIdentifier
private CountryCode code;
private boolean active;
@CommandHandler
public Country(AddCountryCommand command) {
apply(new AddCountryEvent(command.getCode(), command.getName()));
}
public void handle(RemoveCountryCommand command) {
apply(new RemoveCountryEvent(command.getCode()));
}
@EventSourcingHandler
public void on(AddCountryEvent event) {
code = event.getCode();
active = true;
}
@EventSourcingHandler
public void on(RemoveCountryEvent event) {
active = false;
}
}
If you are maintaining a list of countries then your AR is that list, not the individual country. That list probably has a meaning business wise (AllowedCountriesForExport for example) and you should name it accordingly. Makes sense ?
That makes a lot of sense! How do I manage my aggregate Identifiers with a list being my aggregate? In that scenario I feel like this is more of a hashmap with country being a key? Thank you for the advice!
Gotta that makes sense. Since the @AggregateIdentifier annotation right now links me to a specific record in my table, does that mean I would want to adjust that to just be the @Id of the “MyCountryList” Java class and then in the commandHandlers retrieve the appropriate record?
whether you’re better of modeling each country as a separate aggregate or as one containing a list, depends on a lot of factors. If you decide to use one with a list, then your @TargetAggregateIdentifier will have to target the identifier of the list.
But going back to your initial question, about deleting and recreating an aggregate, if you can “undelete”, then you don’t really delete. If an aggregate is flagged as deleted, then all commands on it are rejected. The only way to “undelete” an aggregate, it so change the code and prevent the event to mark an aggregate as deleted.
What you probably want is a state where certain commands (probably all, but Recreate…Command) are rejected. That’s just state validation that you need to implement in your Command Handlers using fields (boolean or other) in your aggregate.