Command vs Event Handlers for dealing with external systems

1,285 views
Skip to first unread message

erich oliphant

unread,
Feb 24, 2014, 8:55:42 PM2/24/14
to axonfr...@googlegroups.com
Hi, I'm trying to figured out the best way to handle calling an external system.  Everything I've read indicates that this is generally best handled in event handlers, but upon reflection it seems a bit contradictory.  Let's say I send a "BuyOrder" command that at some point needs to call a credit card processing gateway.  It seems more 'natural' to handle the processing in the command handler, becuse the subsequent events would be based on say what happened during the processing (e.g. a OrderBought event, a CreditCardDeclined event etc).  I'm not sure how to address this on the event side as it doesn't seem correct to just handle the BuyOrder by directly 'applying' say an 'OrderBought' because it actually hasn't happened yet.

btiernay

unread,
Feb 24, 2014, 9:23:56 PM2/24/14
to axonfr...@googlegroups.com
What about naming  "PlaceBuyOrder" and "BuyOrderPlaced" or "EnterBuyOrder" and "BuyOrderEntered" since really a "buy order" is a noun in most investing circles.

bui...@gmail.com

unread,
Feb 25, 2014, 1:03:31 PM2/25/14
to axonfr...@googlegroups.com
The advice is to call external services in event handlers. The reason is that command handling should generally perform as fast as possible. External services typically don't guarantee anything. 
The event handler would react on ...RequestedEvent type events, and confirm/acknowledge them once the external service has responded.

That doesn't mean you can't call external services from your aggregate.

Cheers,

Allard
--
You received this message because you are subscribed to the Google Groups "Axon Framework Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to axonframewor...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

erich oliphant

unread,
Feb 25, 2014, 2:23:06 PM2/25/14
to axonfr...@googlegroups.com
Good point ;) Though this was more of a typical e-commerce cart-ish scenario

erich oliphant

unread,
Feb 25, 2014, 2:35:45 PM2/25/14
to axonfr...@googlegroups.com
Hmm.  Ok I think I'm following, but I thought, perhaps incorrectly that event handlers shouldn't emit more events.  So is something like the following 'ok'?


class Order {

  @CommandHandler
   void purchase(command:PurchaseOrder) {
       
       apply (PurchaseOrderRequested)
      
   }

   @EventHandler
    void handle(PurchaseOrderRequested) {
      //call external, then
      apply(OrderPurchased)
      - or -
      apply(CreditCardDenied)     
   }

bui...@gmail.com

unread,
Feb 25, 2014, 2:44:20 PM2/25/14
to axonfr...@googlegroups.com
Sorry, I wasn't clear enough. With event handlers, I meant those outside of the aggregate. You're right that an EventSourcingHandler (internal EventHandler) cannot generate more events. 
Hope that makes more sense. 

Cheers,

Allard

erich oliphant

unread,
Feb 25, 2014, 4:25:42 PM2/25/14
to axonfr...@googlegroups.com
Ok so that same model would be 'ok' if it were more like this?


@Component
class Purchaser {

erich oliphant

unread,
Feb 25, 2014, 4:29:36 PM2/25/14
to axonfr...@googlegroups.com
And that Purchaser would need to be 'ReplayAware' as well, in order to ignore events that do call out.

Allard Buijze

unread,
Feb 26, 2014, 2:32:05 AM2/26/14
to Axon Framework Users
Hi Erich,

the Purchaser is in fact a Saga. Saga's don't always have to be implemented with Axon's Saga support. In some cases, a singleton bean is just enough. In this case, there is not enough "process" to justify a full-blown saga.

However, Saga's are not replayable, as they cause side-effects. So it is important that you never assign such a bean to a replayable cluster.

In your purchaser, you cannot apply events. Instead, you should send commands to confirm or reject a payment:

@Component
class Purchaser {

 @EventHandler
    void handle(PurchaseOrderRequested) {
      //call external, then
      commandGateway.send(... ConfirmOrderPurchase)
      - or -
      commandGateway.send(... RejectPurchaseOrder)     
   }
}

Cheers,

Allard

erich oliphant

unread,
Feb 26, 2014, 11:51:18 AM2/26/14
to axonfr...@googlegroups.com
Ah ok, that's much clearer :)
Reply all
Reply to author
Forward
0 new messages