I encountered this before, here is what I did:
Split the local transaction with the remote procedure call.
I think it's not a big deal if the order sending fails. In this case, either the order is placed but not set to "sent" or the order is rollbacked. The business operator can intervene if the order is not send or the customer will call if the order is not placed.
But it's annoying if there is something wrong with the transaction after sending the order successfully. In this case, if the order is rollbacked, the intervention is more difficult because we lost the supplier's notification. The notification usually contains an supplier's order identifier, therefore we could cancel the order with this identifier if necessary.
So we decide to use messaging.
1) The PlaceOrderService is responsible for storing the order and sends a message.
2) The consumer of the message sends the order to the suppler and sends a message containing the supplier's notification.
3) The other consumer of the notification message update the order state.
Each step modifies only one aggregate or just call the remote.
Hope this helps.
Update
1.How would you implement the messaging part here
I adopt the solution mentioned in Eric Evans' dddsample, ApplicationEvents. It's just a simple interface and an jms implementation, something like
public void placeOrder(...) {// method in application service
....//order making
orderRepository.store(order);
applicationEvents.orderWasPlaced(order);//injected applicationEvents
//better move this step out of transaction boundary if not using 2pc commit
//make the method returnning order and use decorator to send the message
// placeOrder(...) {
// Order order = target.placeOrder(...);//transaction end here
// applicationEvents.orderWasPlaced(order);
// return order;
// }
}
public class JmsApplicationEvents implements ApplicationEvents {
public void orderWasPlaced(Order order) {
//sends the message using messaging api of your platform
}
}
2.I see you mention suppliers notification, but let's assume this is done through email (which will be the primary scenario here) I would like to know that the transaction was performed without errors (i.e. no smtp or connection failure), but cannot rely on a response that the order was actually received would that change anything?
hmm.. I have never build an trading application based on email, but here is my suggestions:
Messaging solution still fits if you need strong consistency. Messaging is transactional and could involve in global transaction while email doesn't.
Messaging provides more availability (your order making will not fail even if the mailserver is down) and scalability(queues).
Failure handling is more difficult in messaging solution, usually needs compensating actions. And it's more difficult for the user to get the processing information. For example, you have to notify the user about the progress of the order processing since the following steps are asynchronous. And an email should be sent to the customer if the order is rejected by the supplier.
But messaging does add extra complexity and takes you more effort to build and maintain. You have to evaluate is the gain worth the cost. Actually, I have also built several systems in synchronous solution(they don't require high throughput and availability), they works fine most of the time, only less than ten of orders fail due to the connection problem within a year, so it's not worthy to build an automatic error handling mechanism at all.