What are the advantages of AggregateFactories esp in consideration of Snapshotting or CQRS?

Hello,

can someone tell me what the advantages are of an Aggregate Factory over a simple Aggregate?

The only advantage I can read out is that it automatically recreates the Aggregate from

events it loaded from the event store.

It could also mean: from different event stores (maaaaaayybeeee :wink: ) This then would consider a good advantage maybe over normal Aggregates.

Probably from AggregateSnapshot instances ?

In the docs entry on Snapshotting we read that with AggregateFactories

Configuring multiple aggregate factories allows you to use a single Snapshotter to create snapshots for a variety of aggregate types.

Are these the only advantages?

Additionally, there is no information how I configure that Axon uses AggregateFactories and how to connect those to different Repositories.

Could you provide me with some information on that? I mean, a vector as to where or how to use the Configuration API or alternatively how to define the appripriate Spring Beans. Also, what types of AggregateFactories are there and on what does it depend which type suits my needs best?

Yours sincerely,
überSpotz

Hey @uberSpotz

I understand your confusion. Sadly, the ambiguous naming of some methods and classes in the Axon Framework API and the lack of good explanation in the docs (something we are improving) contribute to such confusion. It took me too quite a while to wrap my head around it.

So, you are comparing incomparable things. An Aggregate is a domain object. One that you create to perform a business-level, state-changing operations. An Aggregate Factory is an infrastructure component. One that, in some cases, is responsible for constructing instances of your Aggregates .

There are two ways of storing the data an Aggregate needs:

  • store the current state (state-stored aggregates)
  • store every change (event-sourced aggregates)

An Aggregate Repository (it’s a DDD concept, don’t confuse it with Spring or JPA repositories) is responsible for storing and loading Aggregates. Depending on which approach is used, the repository is backed by either some DB to store state or an EventStore to store events (changes).

When an Aggregate instance is loaded, the data is loaded either by setting the fields of the Aggregate with values from the DB or calling methods on the Aggregate to rebuild the state from every past change recorded in the EventStore. The latter is what an Aggregate Factory does.

So despite the generic name, the Aggregate Factory in Axon Framework is only used for constructing event-sourced aggregates (note the interface lives in org.axonframework.eventsourcing package). It is not something you’d typically need to directly use or customize (unless you need to tweak the Aggregate construction logic).

Regarding your question

You can configure a repository per Aggregate. In the Command Model Repositories docs there is an example that shows how to do it with both Configuration API and SpringBoot.

Dear @milendyankov
sadly there is neither information how to connect a snapshotter to an AggregateFactory nor on the docs entry on Snapshotting how to register an Aggregate with an AggregateFactory. On the latter, there is at least information on how to register an Aggregate together with a Repository and an EventStore.

For the first thing I had to take a look at
https://apidocs.axoniq.io/4.5/org/axonframework/eventsourcing/AggregateSnapshotter.Builder.html#aggregateFactories-java.util.List-

So my makeshift Snapshotting configuration looks like this. I only need some help with configuring Snapshot Filters. But I will make another thread for this. (There is sadly also no code examples on the Snapshotting docs entry yet)


// https://docs.axoniq.io/reference-guide/axon-framework/tuning/event-snapshots#filtering-snapshot-events
// https://apidocs.axoniq.io/4.5/org/axonframework/eventsourcing/snapshotting/SnapshotFilter.html
SnapshotFilter giftCardSnapshotFilter = snapshotData -> /* allow or disallow this snapshotData */;

/* falsch ? richtig? */
AggregateConfigurer<GiftCard> giftCardConfigurer =
    AggregateConfigurer.defaultConfiguration(GiftCard.class)
        .configureSnapshotTrigger(config -> new EventCountSnapshotTriggerDefinition(
            config.snapshotter(), 500))
                                   
        // https://apidocs.axoniq.io/4.6/org/axonframework/config/AggregateConfigurer.html#configureFilterEventsByType-java.util.function.Function-
        .configureFilterEventsByType(config -> /* ??? */)
                                   
        // https://docs.axoniq.io/reference-guide/axon-framework/tuning/event-snapshots#filtering-snapshot-events
        .configureSnapshotFilter(config -> giftCardSnapshotFilter);
													 
Configurer configurer = DefaultConfigurer.defaultConfiguration()
    // For learning purposes I just like to make things explicit
    
    // https://apidocs.axoniq.io/4.6/org/axonframework/config/Configurer.html#configureSnapshotter-java.util.function.Function-
    .defaultSnapshotter(config -> new AggregateSnapshotter.builder()
        .eventStore(EmbeddedEventStore eventstore)
        
        // https://apidocs.axoniq.io/4.5/org/axonframework/common/DirectExecutor.html
        .executor(DirectExecutor executor)
        
        
        // https://apidocs.axoniq.io/4.5/org/axonframework/eventsourcing/AggregateSnapshotter.Builder.html#eventStore-org.axonframework.eventsourcing.eventstore.EventStore-
        .aggregateFactories(List<AggregateFactory<?>> aggregateFactories)
        
        // https://apidocs.axoniq.io/4.6/org/axonframework/config/DefaultConfigurer.html#configureAggregate-org.axonframework.config.AggregateConfiguration-
        .configureAggregate(giftCardConfigurer)
        
        .build();
    )
                                        
    // https://apidocs.axoniq.io/4.6/org/axonframework/config/DefaultConfigurer.html#configureAggregate-org.axonframework.config.AggregateConfiguration-
    .configureAggregate(giftCardConfigurer);

You usually don’t need to do this. The framework does it for you. You only need to change the factory implementation when the GenericAggregateFactory doesn’t match your needs. Note that when you use Spring autoconfiguration, Axon Framework automatically switches to SpringPrototypeAggregateFactory instead, allowing injecting other Spring beans in your aggregate instances.

Only if those are not enough for you, you should consider Implementing your own Aggregate Factory If that’s what you do, you can configure your custom factory via AggregateConfigurer.configureAggregateFactory(...)

You don’t. Knowing how to deal with snapshots is a feature of the AggregateFactory. You can’t just generically change that for any factory. If you absolutely need to do that, you most likely need to create your own factory.

Note that, much like with AggregateFactory above, there are two Snapshotter implementations - AggregateSnapshotter and SpringAggregateSnapshotter. The only thing you need to configure is the SnapshotTriggerDefinition that tells the framework when to trigger a snapshot. The filtering is optional, but if you need to do that too, the Filtering Snapshot Events doc has an example.

1 Like

Dear @milendyankov

thanks for your answer.

Could maybe you give me an implementation example ?

I know how to implement a Repository for an Aggregate and configure it but I haven’t come accross an AggregateFactory implementation yet.

Thanks !

Thanks

Good to know. This way I can cross AggregateSnapshotter.Builder (Axon Framework 4.6.8 API) from my configuration.