Hi!
I have a use case, where I legitimately have to create an event using Event Gateway from an API call. The external system (which does not use Event Sourcing) notifies me that something has happened, so I translate it into an event. That system will retry its notification in some cases, so I have to ensure I don’t create duplicate events.
So, I found that I can wrap my event into a GenericDomainEventMessage specifying the aggregate id. And then I am able to find it using an EventStore, so I can throw “already exists”. Please, take a look at the code and tell if you see any issues/improvements as it does feel very hacky, but it may be fine because my use case is already hacky by itself and probably not expected from Axon perspective.
import lombok.RequiredArgsConstructor;
import org.axonframework.eventhandling.GenericDomainEventMessage;
import org.axonframework.eventhandling.gateway.EventGateway;
import org.axonframework.eventsourcing.eventstore.EventStore;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/documents")
public class DocumentController {
private final EventGateway eventGateway;
private final DocumentMapper mapper;
private final EventStore eventStore;
@PostMapping
public void acceptNotificationDocumentCreated(@RequestBody DocumentCreateRequest documentDto) {
DocumentCreatedEvent documentCreatedEvent = mapper.toDocumentCreatedEvent(documentDto);
assertThatDocumentDoesNotExist(documentDto.getId());
eventGateway.publish(new GenericDomainEventMessage<>(
Document.class.getSimpleName(),
documentDto.getId(),
//have to use -1 because later down the chain this aggregate is "actually" created with 0 and we get a SQL error
-1L,
documentCreatedEvent
));
}
private void assertThatDocumentDoesNotExist(String id) {
if (eventStore.lastSequenceNumberFor(id).isPresent()) {
throw new DocumentException(ErrorType.DOCUMENT_ALREADY_EXISTS, "with id " + id);
}
}
}
Btw, does it make sense to use GenericTrackedDomainEventMessage in this case? Not sure how though