AggregateIdentifierNotInitializedException when we use a generated id

@Entity
public class Project extends AbstractAnnotatedAggregateRoot {

@Id
@GeneratedValue
private Long id;

private String name;

}

My entity looks like the above I am using the jpaRepository for persistence.
When i use the below code for persistence

Project project = new Project(initiateProjectCommand.name);
projectRepository.add(project);

It fails with the AggregateIdentifierNotInitializedException exception. It expects that id field should already be having a value … is this ok?

@Entity
public class Project extends AbstractAnnotatedAggregateRoot {

@Id
@GeneratedValue
private Long id;

@AggregateIdentifier
private String projectId = “1”;

}

I then updated my entity to look like the above. However it still fails, because the locateIdentifierField in AggregateAnnotationInspector locates the id field first which is not initialized.

@Entity
public class Project extends AbstractAnnotatedAggregateRoot {

@AggregateIdentifier
private String projectId = “1”;

// Note the change in order

@Id
@GeneratedValue
private Long id;

}

The above code works ! Some how i think there is a bug lurking around here. How do we publish event which using the JpaRepository for persistence of aggregates ?

"The AbstractAnnotatedAggregateRoot also requires that the field containing the aggregate identifier is annotated with@AggregateIdentifier. If you use JPA and have JPA annotations on the aggregate, Axon can also use the @Id annotation provided by JPA.

"

Quoted from the reference manual, this is not quite followed in spirit and functionality, please let me know if there is something i have missed out … thanks

I could figure this out myself and i am posting the solution here.

We need to override the

public Object getIdentifier() method, and return the Unique Identifier.

In the below case it the method would like …

@Override
public Object getIdentifier() {
return projectId;
}

Thanks

Hi Sudarshan,

the problem is that you must initialize the identifier of the aggregate, at the latest when handling the first event generated by the aggregate. Generating a value in the database (I’m assuming you do “regular” ORM here, instead of Event Sourcing) is not supported for an EventSourcedAggregate implementation of exactly this reason.
Implementing getIdentifier() will only cover the problem, not solve it. Having two fields, one annotated with @Id and the other with @AggregateIdentifier is not really good practice either. Your aggregate should really only have on ID.

If you don’t care about using an Event Sourced Aggregate, you can also implement AbstractAggregateRoot. Instead of "apply"ing events, you can “register” them. Registered events are published when the repository stores the aggregate. Otherwise, let the aggregate generate a value, or (even better in some cases) use client-generated ID’s.

Hope this helps.
Cheers,

Allard