Axon framework snapshotevents not getting populated after exceeding threshold on Axon 4.4

Viewed 182

I am currently implementing a cqrs application using Axon4.4/Springboot/Java. My application works well except for the fact that it isn't generating the snapshots after exceeding the event count snapshot trigger threshold (which for testing purposes I have set to 3). I am using Mongo db. I can actually see the snapshotevents in the axonframework db, but the snapshot event count is still 0. Please what am i missing? Thanks Please see below my config -- SnapshotConfig:

@Configuration
public class SnapshotConfig {
 @Bean
    public SpringAggregateSnapshotterFactoryBean snapshotfactorybean() {
        return new SpringAggregateSnapshotterFactoryBean();
    }

    @Bean
    public SpringAggregateSnapshotter snapshotter(ParameterResolverFactory parameterResolverFactory, EventStore eventStore, TransactionManager transactionManager) {
        Executor executor = Executors.newFixedThreadPool(5);
        return new SpringAggregateSnapshotter.Builder().eventStore(eventStore)
                .parameterResolverFactory(parameterResolverFactory)
                .executor(executor)
                .transactionManager(transactionManager)
                .build();
    }
 @Bean
    public AggregateFactory<BuyerAggregate> buyerAggregateFactory() {
        SpringPrototypeAggregateFactory<BuyerAggregate> aggregateFactory = new SpringPrototypeAggregateFactory<BuyerAggregate>("buyerAggregate");
        aggregateFactory.setBeanName("buyerAggregateFactory");
        return aggregateFactory;
    }

 @Bean("buyerRepository")
    public EventSourcingRepository<BuyerAggregate> buyerRepository(Snapshotter snapshotter, EventStore eventStore, ParameterResolverFactory parameterResolverFactory) {

        return  EventSourcingRepository.builder(BuyerAggregate.class)
                .aggregateFactory(buyerAggregateFactory())
                .eventStore(eventStore)
                .parameterResolverFactory(parameterResolverFactory)
                .snapshotTriggerDefinition(buyerAggregateSnapshotTrigger(snapshotter))
                .build();

    }
@Bean("buyerAggregateSnapshotTrigger")
    public SnapshotTriggerDefinition buyerAggregateSnapshotTrigger(Snapshotter snapshotter) {
        return new EventCountSnapshotTriggerDefinition(snapshotter, 3);
    }

The db config is something like this:

@Bean
    public MongoClient mongo() {
        var mongoFactory = new MongoFactory();
        var mongoSettingsFactory = new MongoSettingsFactory();
        mongoSettingsFactory.setMongoAddresses(Collections.singletonList(new ServerAddress(mongoHost, mongoPort)));
        mongoFactory.setMongoClientSettings(mongoSettingsFactory.createMongoClientSettings());
        return mongoFactory.createMongo();
    }

    @Bean
    public MongoTemplate axonMongoTemplate(){
        return DefaultMongoTemplate.builder()
                .mongoDatabase(mongo(), mongoDatabase)
                .build();
    }

    @Bean
    public TokenStore tokenStore(Serializer serializer) {
        return MongoTokenStore.builder()
                .mongoTemplate(axonMongoTemplate())
                .serializer(serializer)
                .build();
    }

    @Bean
    public EventStorageEngine storageEngine(MongoClient mongoClient){
        return MongoEventStorageEngine.builder()
                .eventSerializer(serializer())
                .snapshotSerializer(serializer())
                .mongoTemplate(DefaultMongoTemplate.builder().mongoDatabase(mongoClient).build())
                .build();
    }

    @Bean
    public ObjectMapper objectMapper(){
        var objectMapper = new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
        return objectMapper;
    }

    public Serializer serializer(){
        return new JacksonSerializer.Builder()
                .objectMapper(objectMapper())
                .build();
    }


    @Bean
    public EmbeddedEventStore eventStore(EventStorageEngine storageEngine, AxonConfiguration configuration) {
        return EmbeddedEventStore.builder()
                .storageEngine(storageEngine)
                .messageMonitor(configuration.messageMonitor(EventStore.class, "eventStore"))
                .build();
    }

And my aggregate snippet is as follows:

@Aggregate(snapshotTriggerDefinition = "buyerAggregateSnapshotTrigger", repository = "buyerRepository")
public class BuyerAggregate {

    @AggregateIdentifier
    private String id;
    private Buyer buyer;
1 Answers

Configuration wise, you should be able to come by with the following:

// somewhere in a config package...
@Configuration
public class AxonConfig {
    // among other configuration methods...

    @Bean
    public SnapshotTriggerDefinition buyerAggregateSnapshotTrigger(
        Snapshotter snapshotter
    ) {
        return new EventCountSnapshotTriggerDefinition(snapshotter, 3);
    }
}

// somwehere in a command package...
@Aggregate(snapshotTriggerDefinition = "buyerAggregateSnapshotTrigger")
public class BuyerAggregate {
    // state, command handlers and event sourcing handlers...
}

So, the custom Snapshotter configuration should not be necessary in your example.

Next to this, I am wondering why you're using Axon 4.4 actually. Have you tried using the latest release? This is 4.5.3 currently, by the way.

Nonetheless, there is sadly not that much to deduce from the provided code. As Lucas Campos also comments, it might be beneficial to share a small sample project which consistently shows the error you are experiencing. That we, others, can run it locally to notice the predicament. And more importantly, it allows others (like me) to do some debugging.

I also want to share something on the Mongo Event Store selection in your sample. At AxonIQ, there's a tendency to not recommend the usages of Mongo as a storage solution. This is actually shared in the Reference Guide. Also, AxonIQ's CTO, Allard Buijze, explains it nicely in this video as well.

I'd recommend giving Axon Server a try, as it is a dedicated Event Store implementation. You'd be certain to comply with all the Event Store requirements when taking that path.

Related