question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Publish a DomainEventMessage outside of an aggregate

See original GitHub issue

Hello,

it’s more a question or feature request than an issue. I’m working in the Smart Home/IoT-domain and our system consumes events (messages) from gateways/devices via AMQP. The events represent domain events and we want to store them in the event store (keyword: event sourcing). Gateways/devices are our aggregate roots and we want to able to reconstruct their state based on events (keyword: digital twins). I need a way to apply a GenericDomainEventMessage outside of an aggregate. The simplest solution would be to to use the EventBus to publish the GenericDomainEventMessage. The Event Message could have a field with an @TargetAggregateIdentifier annotation. The EventBus then knows how to set the aggregateIdentifier in the event store and how to increase the sequenceNumber.

What do you think?

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Reactions:1
  • Comments:7 (2 by maintainers)

github_iconTop GitHub Comments

2reactions
smcvbcommented, Feb 20, 2018

Hi @RobWin,

Interesting use case you’ve got there. Typically I’d not be overly enthusiastic to let outside sources influence your aggregates, but this seems a little different from the other use cases I’ve come across. I’ve discussed it with @abuijze and we’ve not reached the point that it should be a feature in the framework yet, but created this yourself should be fairly easy.

So, what I’d suggest to do is the following:

  • You’ll need the latest sequence number to set your domain events at the right spot in the store. To grab the latest sequence id for a given aggregate, you can use the EventStore#lastSequenceNumberFor(String aggregateIdentifier).
  • To instantiate the GenericDomainEventMessage you’re going to append you can just call the constructor of the GenericDomainEventMessage, providing the aggregate type, the aggregateIdentifier (which you’ve previously used to pull the sequence number), the sequenceNumber you’ve retrieved in the previous operation and the payload, being the event you’ve received. You can additionally provide you own meta data as a Map, which could contain the correlation id of the AMQP message, a message identifier and a timestamp. I’d suggest to leave the latter two to the GenericDomainEventMessage constructor, but you could provide your own if necessary.
  • After you’ve created your GenericDomainEventMessage, you can call the EventBus#publish(List<? extends EventMessage<?>> events) function to publish your event. If you’re using the EmbeddedEventStore (which I guess you will), the event will be stored, and after that handled by any Event Listeners you have.

The only caveat to this is that the EventStore#lastSequenceNumberFor(String aggregateIdentifier) is not in a release yet. It’s already part of 3.2 though, which should be released somewhere end of month.

Would this solution work out for you @RobWin?

0reactions
metalpalocommented, Mar 7, 2018

Hi guys

I think that I have similar problem.

Concretely I use sagas to handle payment transaction. My scenario is following:

  1. Clients send starts/end payment commands PaymentStartCommad and PaymentEndCommad to command handler what is same class as my aggregate BankAccount with aggregate identifier uid
  2. Command handler (within my aggregate) just applies PaymentStartedEvent and PaymentEndEvent to saga instance
  3. Saga handles PaymentStartedEvent(@EndSaga) by way that schedules other event PaymentExpiredEvent(after 30 seconds) that something wrong and payment is aborted
  4. Saga also handles PaymentEndEvent(@EndSaga) and cancel scheduled event PaymentExpiredEvent

When PaymentExpiredEvent occurs it is stored into db where event identifier is same as aggregate identifier column . That means that such event can not be used during event sourcing of my aggregate.

Q: Am I right? Is this correct behaviour?

If so, what I can do as RobWin mentioned is to trigger another PaymentExpiredCommand from saga and create similar ExpiredEvent which will be joind with aggregate. But I want to avoid this if possible.

Q: What can I do?

thank you very much

Read more comments on GitHub >

github_iconTop Results From Across the Web

How to publish Domain Events in axon framework
In saga, I wanna publish domain events. but to instantiate DomainEventMessage, I need to put sequenceNumber but I have no idea how to...
Read more >
How do you publish an event intended only for @EventHandler ...
How do you publish a GenericEventMessage that only gets routed to @EventHandler -annotated methods that are not defined on @Aggregate ? Here's the...
Read more >
org.axonframework.eventsourcing.DomainEventMessage ... - Tabnine
getSequenceNumber (Showing top 20 results out of 315) ... Publish an event to the aggregate root and its entities first and external event...
Read more >
AbstractEventStore (Axon Framework core 4.0-M2 API) - Javadoc.io
Returns a Stream of all DomainEventMessages that have been staged for publication by an Aggregate with given aggregateIdentifier .
Read more >
Yet another "Make sure the Aggregate Identifier is initialized ...
The exception occurs after creating the Aggregate, when I try to update it via ... I once spent too many minutes of my...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found