1
votes

In my application, we are using axon 3.3.3 and mongo db as event store

we have situation to save all events whenever user updated his profile information.

below is use case

  1. user has created his profile (aggregate id : 101) In mongodb(CreateEvent) has been saved with 101 aggregate id.
  2. user has updated his profile info, so we would like to store UpdateEvent in mongo db(event store)

    But getting below exception

    13:52:49.643 [http-nio-7030-exec-3] ERROR o.a.c.c.C.[.[.[.[dispatcherServlet] - Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.axonframework.commandhandling.model.ConcurrencyException: An event for aggregate [101] at sequence [0] was already inserted] with root cause com.mongodb.MongoBulkWriteException: Bulk write operation error on server 127.0.0.1:27017. Write errors: [BulkWriteError{index=0, code=11000, message='E11000 duplicate key error collection: mytest.domainevents index: uniqueAggregateIndex dup key: { : "101", : 0 }', details={ }}]. at com.mongodb.connection.BulkWriteBatchCombiner.getError(BulkWriteBatchCombiner.java:176) at com.mongodb.connection.BulkWriteBatchCombiner.throwOnError(BulkWriteBatchCombiner.java:205) at com.mongodb.connection.BulkWriteBatchCombiner.getResult(BulkWriteBatchCombiner.java:146) at com.mongodb.operation.BulkWriteBatch.getResult(BulkWriteBatch.java:227) at com.mongodb.operation.MixedBulkWriteOperation.executeBulkWriteBatch(MixedBulkWriteOperation.java:276)

so how can i save the updated event ?

Below is the uniqueAggregateIndex in mongo db

{ "aggregateIdentifier" : 1, "sequenceNumber" : 1 }

@Value("${mongo.host:127.0.0.1}")
private String mongoHost;

@Value("${mongo.port:27017}")
private int mongoPort;

@Value("${mongo.db:mytest}")
private String mongoDB;

@Bean
public MongoSagaStore sagaStore() {
    return new MongoSagaStore(axonMongoTemplate());
}

@Bean
public TokenStore tokenStore(Serializer serializer) {
    return new MongoTokenStore(axonMongoTemplate(), serializer);
}

@Bean
public EventStorageEngine eventStorageEngine(Serializer serializer) {
    return new MongoEventStorageEngine(serializer, null, axonMongoTemplate(), new DocumentPerEventStorageStrategy());
}

@Bean
public MongoTemplate axonMongoTemplate() {
    return new DefaultMongoTemplate(mongo(), mongoDB);
}

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

1 Answers

2
votes

Axon uses that index to guarantee that there are no concurrent actions on Aggregates. After all, an Aggregate is a consistency boundary, and all state changes on it should be atomic and highly consistent.

Changing the index to be non-unique is a bad idea. It would only allow for insertion of events that conflict with other events already in the events store.

Given that the problem seems to be at sequence #0, it may be that you accidentally modelled your @CommandHandler method as a constructor. Axon treats these command handlers specially, by creating a new instance, rather than attempt to load an existing one. In your case, an aggregate already exists, as some events were already stored.