Hi
the AF5 migration guide says that you can use @InjectEntity in the static entity creator method:
CreationPolicy.CREATE_IF_MISSINGIf you need “only create if missing” logic, you can implement it within the static handler by checking for the existence of an optional state parameter.
@CommandHandler public static void handle(IssueGiftCard cmd, EventAppender eventAppender, @InjectEntity @Nullable GiftCard giftCard) { if (giftCard != null) { throw new IllegalStateException("GiftCard already exists"); } eventAppender.append(new GiftCardIssued(cmd.cardId(), cmd.amount())); }
I don’t know if this is “just” a bug in the migration docs or if this is a bug in Axon.
I get an EntityAlreadyExistsForCreationalCommandHandlerException before the static handle method is called again with the entity injected.
Simple example reproducing this using the CourseCreation example:
@Validated
@EventSourced(tagKey = FacultyTags.COURSE_ID, idType = CourseId.class)
@Slf4j
public class CourseCreation {
private boolean created = false;
private CourseId id;
private int capacity;
@CommandHandler
public static void create(
@Valid CreateCourse command,
EventAppender appender,
@InjectEntity @Nullable CourseCreation entity) {
if (entity == null) {
appender.append(
new CourseCreated(
command.courseId(),
command.name(),
command.capacity()
)
);
} else {
// do something different
}
}
@EntityCreator
public CourseCreation(CourseCreated courseCreated) {
this.id = courseCreated.courseId();
this.created = true;
this.capacity = courseCreated.capacity();
}
}
Following test fails:
fixture.given()
.events(new CourseCreated(courseId, "Introduction to Axon Framework", 30))
.when()
.command(new CreateCourse(courseId, "Introduction to Axon Framework", 30))
.then()
.success()
;
with
org.axonframework.modelling.entity.EntityAlreadyExistsForCreationalCommandHandlerException: Creational command handler for command [org.axonframework.examples.university.write.createcourse.CreateCourse#0.0.1] encountered an already existing entity: [org.axonframework.examples.university.write.createcourse.CourseCreation@6b68cb27]
at org.axonframework.modelling.entity.ConcreteEntityMetamodel.handleInstance(ConcreteEntityMetamodel.java:147)
at org.axonframework.modelling.entity.annotation.AnnotatedEntityMetamodel.handleInstance(AnnotatedEntityMetamodel.java:500)
at org.axonframework.modelling.entity.EntityCommandHandlingComponent.lambda$handle$1(EntityCommandHandlingComponent.java:107)
at java.base/java.util.concurrent.CompletableFuture.uniApplyNow(CompletableFuture.java:684)
at java.base/java.util.concurrent.CompletableFuture.uniApplyStage(CompletableFuture.java:662)
at java.base/java.util.concurrent.CompletableFuture.thenApply(CompletableFuture.java:2200)
at org.axonframework.modelling.entity.EntityCommandHandlingComponent.handle(EntityCommandHandlingComponent.java:103)
Klaus