Find a way to load the aggregate object from id and sequence number

I’m trying to find a way to, given an event store, provides the aggregate from id and sequence number;

Does anyone have idea how to help us do that?

1 Like

Hi Lorenzo: This is be possible using the EventSourcingRepository API:

https://apidocs.axoniq.io/4.6/org/axonframework/eventsourcing/EventSourcingRepository.html

You can pass the eventStore to the Repository builder

val repo =  EventSourcingRepository
      .builder(YOUR_AGGREGATE::class.java)
      //.parameterResolverFactory(parameterResolverFactory)
      .eventStore(eventStore)
      .build()

and then load the aggregateInstance via

val aggregate = repo.load(identifier)

Note that though this is technically possible, you should keep in mind CQRS, which means that on the command side you probably will seldomly deal with this configuration yourself because the registered aggregate will handle commands and state automatically, and on the read side you will create custom projections based on events.

2 Likes

Hi this is what i’ve been testing.

I expected to get the AccountAggregate loaded until version spacified … but i receive always the last version.

public class AccountQueryServiceImpl implements AccountQueryService {

    private final EventStore eventStore;
    private UnitOfWork<?> unitOfWork;
    private AccountRepository accountRepository;
    private EventSourcingRepository<AccountAggregate> testSubject;

    .....

    @Override
    public AccountQueryEntity getAccount(String accountNumber, Long sequenceNumber) {
        if (sequenceNumber == null) {
            return accountRepository.findById(accountNumber).get();
        }
        unitOfWork = DefaultUnitOfWork.startAndGet(null);
        testSubject = EventSourcingRepository
            .builder(AccountAggregate.class)
            
            //.parameterResolverFactory(parameterResolverFactory)
            .eventStore(eventStore)
            .filterByAggregateType()
            .build();
        
        Object aggregate = testSubject.load(accountNumber, sequenceNumber).getWrappedAggregate().getAggregateRoot();

Is there a way to load the Aggregate “state” passing id and axonSeqeunenceNumber ?

I’m trying to do the same thing using Axon Framework 4.8.0, but without success. I also can’t find documentation or examples on how to achieve this. So I’m wondering if anyone was able to do this?

I’ve debugged the internal code of Axon, and it seems that the expectedVersion argument in Repository.load(String aggregateIdentifier, Long expectedVersion) is never actually being used to limit the stream of domain events.

The way I’ve tested it (and didn’t work) was:

var message = new GenericMessage(...);
var unitOfWork = DefaultUnitOfWork.startAndGet(message);

var personAggregate = personEventSourcingRepository.load(id, sequence);
personAggregate.execute(p -> {
	log.info("At this point I incorrectly get the latest version");
});

// Statement below also returns the latest version incorrectly
var person = personAggregate.getWrappedAggregate().getAggregateRoot();

Edit:
It seems this question was asked a long time ago, with a proposal implementation to add support to the framework. But there was no further reply

Hey @Bridge98 and @Pieter-Jan_Savat,

As you’ve found out, there’s no means to retrieve an Aggregate and limit how far you want it to load events with Axon Framework’s automatically provided components.
To be able to do so, you would be required to retrieve the event stream for a specific aggregate from the EventStore directly, create the empty aggregate instance manually, and invoke every applicable event sourcing handler for the events within the stream up to and until the sequenceIdentifier you want to load.

Mind you, doable (the above steps should get you there), but not default support from Axon Framework at this stage. If you do go this route, be sure to traverse Axon Framework’s code base and ask questions on the forum :+1:

Concerning this line specific from you, @Pieter-Jan_Savat:

The expectedVersion field is filled by Axon Framework whenever you use the @TargetAggregateVersion annotation on a field in the command you dispatch. This can be used to “tell” AF that “I expect the model to be at this position, and no further.”
In short, it’s not something that provides you with the functionality you’re looking for.

I hope the above helps both of you a little further!
Besides this, would you mind sharing with me/us why you’re looking for this functionality exactly?
Knowing the use cases helps me to deduce the priority for new functionality we add to Axon Framework.

Thanks in advance!