Implementing Snapshot in AXON 3.0 : Aggregate Type is unknown in this snapShotter

Hi,

I’m still new to the axon frame work.

I’m trying to implement snapshotting using mongodb in my application and I keep on getting an error saying

"AbstractSnapshotter : An attempt to create and store a snapshot resulted in an exception. Exception summary: Aggregate Type is unknown in this snapshotter: com.myworklife.contacts.domain.contact.Contact"

This is my Java config file

import com.mongodb.MongoClient;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;
import com.myworklife.contacts.domain.contact.Contact;
import com.myworklife.contacts.domain.contact.service.repository.ContactRepository;
import org.apache.logging.log4j.util.Strings;
import org.axonframework.commandhandling.model.Repository;
import org.axonframework.eventsourcing.*;
import org.axonframework.eventsourcing.eventstore.EmbeddedEventStore;
import org.axonframework.eventsourcing.eventstore.EventStorageEngine;
import org.axonframework.eventsourcing.eventstore.EventStore;
import org.axonframework.eventsourcing.eventstore.inmemory.InMemoryEventStorageEngine;
import org.axonframework.mongo.eventsourcing.eventstore.DefaultMongoTemplate;
import org.axonframework.mongo.eventsourcing.eventstore.MongoEventStorageEngine;
import org.axonframework.mongo.eventsourcing.eventstore.MongoTemplate;
import org.axonframework.mongo.eventsourcing.eventstore.documentperevent.DocumentPerEventStorageStrategy;
import org.axonframework.serialization.Serializer;
import org.axonframework.serialization.xml.XStreamSerializer;
import org.axonframework.spring.eventsourcing.SpringAggregateSnapshotterFactoryBean;
import org.axonframework.spring.eventsourcing.SpringPrototypeAggregateFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Collections;
import java.util.List;

@Configuration
public class ContactsEventStorageEngineConfiguration {

@Value("${event.storage.engine.type}")
private String eventStorageEngineType;

@Value("${mongodb.url}")
private String mongoUrl;

@Value("${mongodb.port}")
private Integer mongoPort;

@Value("${mongodb.username}")
private String mongoDbUsername;

@Value("${mongodb.password}")
private String mongoDbPassword;

@Value("${mongodb.dbname}")
private String mongoDbName;

@Value("${mongodb.events.collection.name}")
private String eventsCollectionName;

@Value("${mongodb.events.snapshot.collection.name}")
private String snapshotCollectionName;

@Bean
    public MongoTemplate mongoTemplate(MongoClient mongoClient) {
if (eventStorageEngineType.equals("inmemory")) {
return null;
        }
return new DefaultMongoTemplate(mongoClient, mongoDbName, eventsCollectionName, snapshotCollectionName);
    }

@Bean
    public MongoClient mongoClient() {
if (eventStorageEngineType.equals("inmemory")) {
return null;
        }
        List<ServerAddress> serverAddresses = Collections.singletonList(new ServerAddress(mongoUrl, mongoPort));
if (Strings.isNotEmpty(mongoDbUsername) && Strings.isNotEmpty(mongoDbPassword)) {
            List<MongoCredential> mongoCredentials = Collections.singletonList(
                    MongoCredential.createCredential(mongoDbUsername, mongoDbName, mongoDbPassword.toCharArray()));
return new MongoClient(serverAddresses, mongoCredentials);
        } else {
return new MongoClient(serverAddresses);
        }
    }

@Bean
    public Serializer axonSerializer() {
return new XStreamSerializer();
    }

@Bean
    public EventStorageEngine eventStorageEngine(Serializer axonSerializer, MongoTemplate mongoTemplate) {
if (eventStorageEngineType.equals("inmemory")) {
return new InMemoryEventStorageEngine();
        } else if (eventStorageEngineType.equals("mongodb")) {
return new MongoEventStorageEngine(axonSerializer, null, mongoTemplate, new DocumentPerEventStorageStrategy());
        }

return null;
    }

@Bean
    public SpringAggregateSnapshotterFactoryBean snapshotterFactoryBean() {
return new SpringAggregateSnapshotterFactoryBean();
    }

@Bean
    public AggregateSnapshotter snapShotter(EventStore eventStore, AggregateFactory<Contact> contactAggregateFactory) {
return new AggregateSnapshotter(eventStore);
    }

@Bean
    public SnapshotTriggerDefinition snapshotTriggerDefinition(Snapshotter snapShotter) throws Exception {
return new EventCountSnapshotTriggerDefinition(snapShotter, 1);
    }

@Bean
    public EventStore eventStore(EventStorageEngine eventStorageEngine)  {
return new EmbeddedEventStore(eventStorageEngine);
    }

@Bean
    public Repository<Contact> contactAggregateRepository(EventStore eventStore, SnapshotTriggerDefinition snapshotTriggerDefinition) {
return new ContactRepository(eventStore, snapshotTriggerDefinition);
    }
}

Hi Patrick,

Don’t you forget to pass in the AggregateFactory when creating the AggregateSnapshotter?
When I search the Axon project for when the **Aggregate Type is unknown in this snapshotter** exception is thrown, I see it’s thrown when the aggregateFactory for a given type is null.
The fact your config doesn’t reflect adding the AggregateFactory to the AggregateSnapshotter, leads me to believe this is what you’ve missed.

Hope this helps!

Cheers,

Steven

Hi Patrick,

as Steven suggests, your AggregateSnapshotter needs to know the AggregateFactory for each Aggregate it should create snapshots of. However, when using Spring, Axon can look these up automatically for you. Instead of using AggregateSnapshotter, use the SpringAggregateSnapshotter. It will automatically load required AggregateFactories from the application context. You should be able to autowire all the beans the SpringAggregateSnapshotter requires in its constructor.

Cheers,

Allard