Only can insert event one time

It is possible to insert data for the first time, but if i request it again, an error occurs.
I expected it to be stored in the event store again. Did I think somthing wrong?

here is my code.

@RestController
@RequestMapping(value = ["/samples"])
class SampleController(
    private val commandGateway: CommandGateway
) {

    @PostMapping
    @ResponseStatus(value = HttpStatus.ACCEPTED)
    fun saveSample(@RequestBody request: CreateSampleRequest): CompletableFuture<CompletableFuture<String>> {
        return this.commandGateway.send<CompletableFuture<String>>(
            CreateSampleCommand(
                id = request.id,
                stuff = request.stuff
            )
        )
    }
}
@Aggregate
class SampleAggregate {

    @AggregateIdentifier
    private lateinit var id: String
    private var status: SampleStatus? = null

    constructor()

    @CommandHandler
    @CreationPolicy(AggregateCreationPolicy.CREATE_IF_MISSING)
    fun handle(command: CreateSampleCommand) {
        apply(
            SampleCreatedEvent(
                sampleId = command.id,
                stuff = command.stuff,
                status = SampleStatus.CREATED
            )
        )
    }

    @EventSourcingHandler
    fun on(event: SampleCreatedEvent) {
        this.id = event.sampleId
        this.status = event.status
    }
}
data class CreateSampleCommand(
    @TargetAggregateIdentifier
    val id: String,
    val stuff: String
)

i use jackson serializer like this.

@Bean
    fun storageEngine(client: MongoClient): EventStorageEngine {
        return MongoEventStorageEngine
            .builder()
            .mongoTemplate(this.mongoTemplate(client))
            .snapshotSerializer(JacksonSerializer.defaultSerializer())
            .eventSerializer(JacksonSerializer.defaultSerializer())
            .build()
    }

i get this error below after i request again.

Cannot construct instance of `com.example.SampleCreatedEvent` (no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
 at [Source: (byte[])"{"sampleId":"123","stuff":"Lorem Ipsum","status":"CREATED"}"; line: 1, column: 2]

how to solve this problem?
i don’t know how to do and what’s wrong with it
please let me know

Hey there! For kotlin data-classes Jackson needs its kotlin module, is it in your application?
See: GitHub - FasterXML/jackson-module-kotlin: Module that adds support for serialization/deserialization of Kotlin (http://kotlinlang.org) classes and data classes.

1 Like

Seems a problem with serialization, as you are using Kotlin, you probably need both the jackson-module-kotlin dependency, as maybe the kotlin-maven-allopen and kotlin-maven-noarg as dependency in the spring-boot-maven-plugin, assuming you are using maven. For example a pom from a demo project.

Seems like AggregateCreationPolicy ALWAYS matches what you want, there is more information in the reference guide.

@Morlack thank you to quick reply!

after registering kotlinmodule, i can insert twice!

but still i don’t get it when it used.
i guess in commandhandler, when it checks id from event store if it exist, is it used to serialize?

if it is wrong, let me know when it used please

@imnewone , can you elaborate more on what you mean by “but still i don’t get it when it used.”.

The events are stored on every command, and matching @EventSourcingHandler methods are replayed with these events to construct the state of the aggregate.

@Morlack thank you to reply!

after you comment about replay, now i understand why kotlin module is needed.
However I didn’t understand how it work detail.

i thought event replay from commandhandler but i guess im wrong.

you mean, because of replaying event from eventsourcinghandler, registering kotlin module is needed.
Am I right to understand?

i think i have lack understanding eventsourcinghandler.

if command request, replay event in eventsourcinghandler for check aggregate state.
and then in commandhander, when event applied, the event stored in eventstore.
and again in eventsourcinghandler, aggregate store that state.
finally, pass event bus

is it right? im confiusing…

The module is needed because you use a Kotlin data class. Jackson normally cannot handle that since it looks for a certain style of constructor, which Kotlin data-classes don’t have.

Once the event is written to the database and fetched later, it will need to be deserialized and for this Jackson needs to understand this data-class. That is the reason the module is needed.

The event is needed in the case of building an aggregate, for example. When firing a command to aggregate XYZ, all events for XYZ are fetched from the database and played on the aggregate to build state. For this to happen, the events need to be deserialized. After playing all events on the aggregate, the command is executed.

I hope this clears things up a bit for you. If I may recommend it, we have quite a good video tutorial on most of these concepts here: Quick Start - Axon Reference Guide

1 Like

@Morlack
always thank you for your quick reply!!!

im reading axon refrence littile by little.
I understand abstractly, but I don’t know exactly what kind of handler it plays.
after calling apply method, what they are doing, when eventsourcehandler trigger…

i’ve seen this material([HDTDI] synchronous command message cycle - Google Slides) from internet.
it helps me a little bit. but still not clear.

i will watch the video you recommended. thank you for your recommendation.