Publish External Event from the Aggregate

After the aggregate is updated, I want to publish out the latest value of the aggregate as an event without having an additional action on the command handler. I don’t want this logic run when building the aggreagate from the database though!

The bad line in my eyes below is ‘publisher.publish(stockItem.invoke(x -> x.getSupply()))’ below. This is called after addAdjustment updates the aggregate and saves the event to the backing store.

The line is in the commandhandler but I think it’s better design to raise something inside ‘addAdjustment’ method?

Option 1 - use commandbus, inside andThen or andThenApply
Option 2 - use sometype of non-domain aggregate event
Option 3- as I have done

It would be nice to have it outside the UoW too!

I’m using EmbeddedEventStore and a Cassandra Backend.

@CommandHandler
public void handle(StockItemFCStockSupplyCommand command) throws Exception {
LOGGER.info(“Handling StockItemFCStockSupplyCommand …”);
Aggregate stockItem = null;
String sku = command.getSku();

try {
stockItem = repository.load(sku);
}
catch (AggregateNotFoundException e) {
stockItem = repository.newInstance(()-> new StockItem(sku));
}
catch (Exception e) {
LOGGER.error(e.getMessage());
throw e;
}

stockItem.execute(aggregateRoot -> aggregateRoot.addAdjustment(command.getQuantity()));

//Publish the Latest Supply Record to NOSQL Implementation
publisher.publish(stockItem.invoke(x -> x.getSupply()));
}

@AggregateRoot
@Revision(“1.0”)
public class StockItem {
private static final Logger LOGGER = LoggerFactory.getLogger(StockItem.class);
@AggregateIdentifier
private String aggregateIdentifier;
private int supply;

public StockItem() { }

public StockItem(String aggregateIdentifier) {
LOGGER.info("Creating a new Aggregate " + aggregateIdentifier);
apply(new StockItemCreatedEvent(aggregateIdentifier, 0));
}

public void addAdjustment(Integer quantity) {
LOGGER.trace(“addAdjustment - Raising StockItemSupplyEvent”);
apply(new StockItemAdjustmentEvent(this.aggregateIdentifier, quantity));
//Add something here or use andThen or andThenApply?
}

@EventSourcingHandler
private void on(StockItemCreatedEvent event) {
LOGGER.info(“StockItemCreatedEvent …” + event.getAggregateIdentifier());
this.aggregateIdentifier = event.getAggregateIdentifier();
this.supply = event.getQuantity();
}

@EventSourcingHandler
private void on(StockItemAdjustmentEvent event) {
LOGGER.trace(String.format(“StockItemAdjustmentEvent {%s},{%s}”, event.getAggregateIdentifier(), event.getQuantity()));
this.supply += event.getQuantity();
}

public int getSupply() {
return this.supply;
}
}

Hi Gerard,

I’m not sure I really understand what you’re trying to achieve. Sending out the state of an aggregate as an event is a very awkward thing to do, and I feel this is an attempt to solve some issue that probably has a better way to be fixed.

You say “I don’t want this logic run when building the aggregate from the database though!” Logic in command handlers is never executed when an aggregate is loaded. It is always executed on a loaded aggregate. So you can just “apply” the event you want published, even an apply(this), if you are really, really, sure (and then think again) that you want to publish the aggregate state.

In your example, it looks like you just want to publish the current level of stock for a specific item. That’s information that could very well have its place in the StockItemAdjustmentEvent. It could say: item x reduced by 10, now have 20 in stock.

Hope this helps.
Cheers,

Allard