Snapshotting warns when it exceeds the threshold

When snapshotting exceeds the threshold, it throws the following warning

org.axonframework.eventsourcing.IncompatibleAggregateException(Aggregate identifier must be non-null after applying an event. Make sure the aggregate identifier is initialized at the latest when handling the creation event.)

Can you suggest a solution?
Thank you

Hi Kuldeep,

There could be several things going wrong, it would be best to look at how the aggregate is serialized, and maybe build a test around it.

Assuming you use Jackson, and it’s indeed related, you can solve it in several ways. Likely the aggregate I’d field is private, without getters. If you add a public getter, Jackson should also serialize the aggregate id. There are several other solutions, like adding Jackson annotations.

1 Like

Hi @Gerard
I have fixed it by configuring EmbeddedEvnetStore Configuration.
Earlier I was using:

  return MongoEventStorageEngine.builder()
                    .mongoTemplate(DefaultMongoTemplate.builder()
                            .mongoDatabase(mongoClient).build())
                    .eventSerializer(JacksonSerializer
                            .defaultSerializer())
                    .snapshotSerializer(JacksonSerializer
                            .defaultSerializer())
                    .build();

After removing .snapshotSerializer(JacksonSerializer .defaultSerializer())

Now, Snapshots are created fine, but for a new command still replaying the previous events. And because of that, In EventSourcinghandler there is a logic that executes for previous events to rebuild the state of an Aggregate. It takes time for execution.

    @EventSourcingHandler
    public void on(final GroupCreatedEvt evt)
            throws InvalidProtocolBufferException {

        this.cmId = evt.getId();
        final GroupCreated groupCreated = ProtoSerDer.fromJsonToProtoBuf(
                evt.getGroupCreated(), GroupCreated.class).orElseThrow();
        this.data.created(groupCreated);
    }

Shouldn’t a new command rebuilds the state from the created snapshots?
It seems, when applying a new event it replays the events from the domain events.
Then what is the significance of snapshotting?
Is there any further configuration required for utilizing snapshots?

Are you sure the snapshots are created? By default, without a snapshot filter set, it should make a snapshot each time. You could check the logging and/or the snapshots collection in mongo.

Hi @Gerard
We have configured a snapshot

 @Bean
    public SnapshotTriggerDefinition
    xyzSnapshotTrigger(
        final Snapshotter snapshotter,
        @Value("${axon.aggregate.order.snapshot-threshold:10}")
        final int threshold) {
        return new EventCountSnapshotTriggerDefinition(snapshotter,
            threshold);

and used it in aggregate like

@Aggregate(snapshotTriggerDefinition = "xyzSnapshotTrigger")
public class XYZ {
 //
}
...
Here is the screenshot with reference to the snapshot
![MicrosoftTeams-image|690x281](upload://jZzOo38eyr67zELBsH7FxpSQ9wR.png)

But do you see them?

yes, Here it is

{
  "_id": {
    "$oid": "6389e8aa6ccbd324e987278d"
  },
  "aggregateIdentifier": "33591f70-da1a-49f5-9e46-87494e2570b6",
  "type": "ClassMaster",
  "sequenceNumber": {
    "$numberLong": "13"
  },
  "serializedPayload": "<com.xyz.engine.classification.master.XYZ>....................//MANYLines.........<cmId>33591f70-da1a-49f5-9e46-8749</com.xyz.engine.classification.master.XYZ>",
  "timestamp": "2022-12-02T11:59:40.259Z",
  "payloadType": "com.xyz.engine.classification.master.XYZ",
  "payloadRevision": null,
  "serializedMetaData": "<meta-data><entry><string>traceId</string><string>2dfeda5a-aeeb-4374-9197-1fd995e2055e</string></entry><entry><string>correlationId</string><string>2dfeda5a-aeeb-4374-9197-1fd995e2055e</string></entry></meta-data>",
  "eventIdentifier": "9629f140-0160-470b-9ece-0c46fdda025c"
}

Based on the configuration, a snapshot should be created every 10 events. So not every time. I would expect it to start with the most recent snapshot, then apply the events produced since, and after new events are applied, it might create a new snapshot optionally. Do you have any indication it’s not happening that way?

Right @Gerard
Snapshot is created every 10th event.
But next event is not starting from the snapshot created.

For example- If set threshold value to 10, then 9 events stored in domainevents and 10th event creates snapshot, as well as it also stores in domainevents collection.

Yes, that is right. But when it then rebuilds the aggregate it ignores the snapshots, and builds the aggregate using only the events? Snapshotting has no effect on how/where/when the events are stored.

Yes, @Gerard Right
It is ignoring snapshot. Snapshot has no effect.
It rebuild aggregate using events only.

Are you sure? How do you know this?

HI @Gerard
Looked into the logs and found this

23:50:31.033 WARN  org.axonframework.eventsourcing.eventstore.AbstractEventStore -
                    Error reading snapshot for aggregate [33591f70-da1a-49f5-9e46-87494e2570b6]. Reconstructing from entire event stream. 
com.thoughtworks.xstream.security.ForbiddenClassException: com.xyz.engine.classification.master.XYZ
	at com.thoughtworks.xstream.security.NoTypePermission.allows(NoTypePermission.java:26)
	at com.thoughtworks.xstream.mapper.SecurityMapper.realClass(SecurityMapper.java:74)
	at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:125)
	at com.thoughtworks.xstream.mapper.CachingMapper.realClass(CachingMapper.java:47)
	at org.axonframework.serialization.AbstractXStreamSerializer.classForType(AbstractXStreamSerializer.java:170)```

So there is an error related to using XStream. It’s likely easier to get it to work using Jackson. But at least the cause is clear now. The stored snapshot can’t be deserialized.

Yes @Gerard
That error got resolved by configuring storageEngine() like:

            //-------------
            String[] newString = new String[]{"org.axonframework.**", "**"};
            XStream xStream = new XStream();
            xStream.allowTypesByWildcard(newString);
            XStream xStream1 =
                XStreamSerializer.builder().xStream(xStream).build()
                    .getXStream();
            final MongoClient mongoClient = MongoClients.create(settings); //NOSONAR
            return MongoEventStorageEngine.builder()
                    .mongoTemplate(DefaultMongoTemplate.builder()
                            .mongoDatabase(mongoClient, eventStore)
                            .build())
                .eventSerializer(JacksonSerializer
                    .defaultSerializer())
                .snapshotSerializer(XStreamSerializer.builder()
                    .xStream(xStream1).build())
                .build();

It is not reading from snapshots (as the record in MongoDB increases, the performance slows down) and when the snapshots sequence no reached 92, it throws a warning
(set snapshot threshold = 47)

11:47:27.038 WARN  org.axonframework.eventsourcing.AbstractSnapshotter -
                    An attempt to create and store a snapshot resulted in an exception. Exception summary: An event for aggregate [33591f70-da1a-49f5-9e46-87494e2570b6] at sequence [92] was already inserted 

Here is the used configuration for the snapshots;

    @Bean
    public SpringAggregateSnapshotter snapshotter(
        final ParameterResolverFactory parameterResolverFactory,
        final EventStore eventStore,
        final TransactionManager transactionManager) {
        Executor executor = Executors.newSingleThreadExecutor();
        return SpringAggregateSnapshotter.builder()
            .eventStore(eventStore)
            .parameterResolverFactory(parameterResolverFactory)
            .executor(executor)
            .transactionManager(transactionManager)
            .build();
    }
        @Bean
        public SnapshotTriggerDefinition giftCardSnapshotTriggerDefinition (
        final Snapshotter snapshotter){
            return new EventCountSnapshotTriggerDefinition(snapshotter, 3);
        }

And I found another issue related to sequence no.
For Example:
Set threshold = 10;
then Snapshot Sequence is not increasing consistently.
Our understanding is that a snapshot should create with sequence numbers like 9, 19, 28, 37, 46, and so on, but instead of 46 it shows 47.

Maybe it’s better to create new topics for new things. Regarding the exception, do you have several instances of the application running?

I don’t understand you second remark, set to 10, I would expect a snapshot every 10 events. Which could be a bit off when multiple events are applied at the same time. But I wouldn’t expect a snapshot every 9 events.

1 Like