Axon 3 handling deleted Aggregates

All,

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 ?

Jorg

Jorg,

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!

You would create an actual java class “MyCountryList” encapsulating the actual collection (map or list does not matter)

Jorg

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?

Unsure, I do not have enough context of the actual business case you are trying to solve.

Jorg

Hi Matthew,

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.

Hope that helps.
Cheers,

Allard