Search code examples
javacqrsaxon

How can I delete an AggregateMember on Axon?


I have an aggregate Organization which can have several addresses. So we have modeled this OrganizationDeliveryAddress as an Aggregate Member. On the OrganizationDeliveryAddress we command and event sourcing handlers for the entity itself.

Here's my current implementation:

@Aggregate
public class Organization {

  private @AggregateIdentifier
  @NonNull UUID organizationId;

  @AggregateMember
  private final List<OrganizationDeliveryAddress> deliveryAddresses = new ArrayList<>();

  @CommandHandler
  public UUID on(AddOrganizationDeliveryAddressCommand command) {
    val addressId = UUID.randomUUID();
    val event = new OrganizationDeliveryAddressAddedEvent(command.getOrganizationId(), addressId, command.getAddress());
    AggregateLifecycle.apply(event);
    return addressId;
  }

  @EventSourcingHandler
  public void on(OrganizationDeliveryAddressAddedEvent event) {

    val address = new OrganizationDeliveryAddress(event.getOrganizationDeliveryAddressId(), false);
    deliveryAddresses.add(address);
  }

}

 

public class OrganizationDeliveryAddress {

  private @EntityId
  @NonNull UUID organizationDeliveryAddressId;
  
  @CommandHandler
  public void on(RemoveOrganizationDeliveryAddressCommand command) {
    AggregateLifecycle.apply(new OrganizationDeliveryAddressRemovedEvent(command.getOrganizationId(),
        command.getOrganizationDeliveryAddressId()));
  }

  @EventSourcingHandler
  public void on(@SuppressWarnings("unused") OrganizationDeliveryAddressRemovedEvent event) {
    if (organizationDeliveryAddressId.equals(event.getOrganizationDeliveryAddressId())) {
      AggregateLifecycle.markDeleted();
    }
  }

}

We want to remove one of the addresses, but it looks like not just the address, but the entire aggregate is deleted.

So here's my question: How can I instruct Axon Framework to remove the OrganizationDeliveryAddress Aggregate Member?


Solution

  • The AggregateMember is not an Aggregate per se but just a member of another Aggregate. This is why if you call AggregateLifecycle.markDeleted(); it will mark the Aggregate itself as deleted.

    To 'delete' an AggregateMember you should do the opposite as adding it, which means you can have an @EventSourcingHandler method on your Aggregate listening to the OrganizationDeliveryAddressRemovedEvent. This method would be responsible to find the right DeliveryAddress on your AggregateMember (deliveryAddresses) or even better a Map as you will see below and simply remove it from that. A pseudo-code could be something like this:

    // Organization.java
    ...
    @AggregateMember
    private final Map<UUID, OrganizationDeliveryAddress> deliveryAddressItToDeliveryAddress = new HashMap<>();
    ...
    @EventSourcingHandler
    public void on(@SuppressWarnings("unused") OrganizationDeliveryAddressRemovedEvent event) {
        Assert.isTrue(deliveryAddressItToDeliveryAddress.containsKey(event.getOrganizationDeliveryAddressId()), "We do not know about this address");
        deliveryAddressItToDeliveryAddress.remove(event.getOrganizationDeliveryAddressId());
    }