Update Command Model
Adjust the OrderAggregate to contain an OrderLine aggregate member. The OrderLine is added as soon as a Product is added through the AddProductCommand. The OrderLine member is capable of handling the increment and decrement product count commands, to increase/decrease the number of instances for that OrderLine. Decreasing the count below 1 will publish the ProductRemovedEvent from within the OrderLine. Additional business validation is added to unsure a given Product isn't added twice (adding a second should go through increment) and that the products aren't adjusted as soon as the product is confirmed. #BAEL-4767
This commit is contained in:
		
							parent
							
								
									ef1167b037
								
							
						
					
					
						commit
						886368a4c3
					
				| @ -1,19 +1,27 @@ | ||||
| package com.baeldung.axon.commandmodel; | ||||
| 
 | ||||
| import static org.axonframework.modelling.command.AggregateLifecycle.apply; | ||||
| 
 | ||||
| import org.axonframework.commandhandling.CommandHandler; | ||||
| import org.axonframework.eventsourcing.EventSourcingHandler; | ||||
| import org.axonframework.modelling.command.AggregateIdentifier; | ||||
| import org.axonframework.spring.stereotype.Aggregate; | ||||
| package com.baeldung.axon.commandmodel.order; | ||||
| 
 | ||||
| import com.baeldung.axon.coreapi.commands.AddProductCommand; | ||||
| import com.baeldung.axon.coreapi.commands.ConfirmOrderCommand; | ||||
| import com.baeldung.axon.coreapi.commands.PlaceOrderCommand; | ||||
| import com.baeldung.axon.coreapi.commands.ShipOrderCommand; | ||||
| import com.baeldung.axon.coreapi.events.OrderConfirmedEvent; | ||||
| import com.baeldung.axon.coreapi.events.OrderPlacedEvent; | ||||
| import com.baeldung.axon.coreapi.events.OrderShippedEvent; | ||||
| import com.baeldung.axon.coreapi.events.ProductAddedEvent; | ||||
| import com.baeldung.axon.coreapi.events.ProductRemovedEvent; | ||||
| import com.baeldung.axon.coreapi.exceptions.DuplicateOrderLineException; | ||||
| import com.baeldung.axon.coreapi.exceptions.OrderAlreadyConfirmedException; | ||||
| import com.baeldung.axon.coreapi.exceptions.UnconfirmedOrderException; | ||||
| import org.axonframework.commandhandling.CommandHandler; | ||||
| import org.axonframework.eventsourcing.EventSourcingHandler; | ||||
| import org.axonframework.modelling.command.AggregateIdentifier; | ||||
| import org.axonframework.modelling.command.AggregateMember; | ||||
| import org.axonframework.spring.stereotype.Aggregate; | ||||
| 
 | ||||
| import java.util.HashMap; | ||||
| import java.util.Map; | ||||
| 
 | ||||
| import static org.axonframework.modelling.command.AggregateLifecycle.apply; | ||||
| 
 | ||||
| @Aggregate | ||||
| public class OrderAggregate { | ||||
| @ -22,13 +30,33 @@ public class OrderAggregate { | ||||
|     private String orderId; | ||||
|     private boolean orderConfirmed; | ||||
| 
 | ||||
|     @AggregateMember | ||||
|     private Map<String, OrderLine> orderLines; | ||||
| 
 | ||||
|     @CommandHandler | ||||
|     public OrderAggregate(PlaceOrderCommand command) { | ||||
|         apply(new OrderPlacedEvent(command.getOrderId(), command.getProduct())); | ||||
|         apply(new OrderPlacedEvent(command.getOrderId())); | ||||
|     } | ||||
| 
 | ||||
|     @CommandHandler | ||||
|     public void handle(AddProductCommand command) { | ||||
|         if (orderConfirmed) { | ||||
|             throw new OrderAlreadyConfirmedException(orderId); | ||||
|         } | ||||
| 
 | ||||
|         String productId = command.getProductId(); | ||||
|         if (orderLines.containsKey(productId)) { | ||||
|             throw new DuplicateOrderLineException(productId); | ||||
|         } | ||||
|         apply(new ProductAddedEvent(orderId, productId)); | ||||
|     } | ||||
| 
 | ||||
|     @CommandHandler | ||||
|     public void handle(ConfirmOrderCommand command) { | ||||
|         if (orderConfirmed) { | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         apply(new OrderConfirmedEvent(orderId)); | ||||
|     } | ||||
| 
 | ||||
| @ -45,6 +73,7 @@ public class OrderAggregate { | ||||
|     public void on(OrderPlacedEvent event) { | ||||
|         this.orderId = event.getOrderId(); | ||||
|         this.orderConfirmed = false; | ||||
|         this.orderLines = new HashMap<>(); | ||||
|     } | ||||
| 
 | ||||
|     @EventSourcingHandler | ||||
| @ -52,8 +81,18 @@ public class OrderAggregate { | ||||
|         this.orderConfirmed = true; | ||||
|     } | ||||
| 
 | ||||
|     @EventSourcingHandler | ||||
|     public void on(ProductAddedEvent event) { | ||||
|         String productId = event.getProductId(); | ||||
|         this.orderLines.put(productId, new OrderLine(productId)); | ||||
|     } | ||||
| 
 | ||||
|     @EventSourcingHandler | ||||
|     public void on(ProductRemovedEvent event) { | ||||
|         this.orderLines.remove(event.getProductId()); | ||||
|     } | ||||
| 
 | ||||
|     protected OrderAggregate() { | ||||
|         // Required by Axon to build a default Aggregate prior to Event Sourcing | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| @ -0,0 +1,83 @@ | ||||
| package com.baeldung.axon.commandmodel.order; | ||||
| 
 | ||||
| import com.baeldung.axon.coreapi.commands.DecrementProductCountCommand; | ||||
| import com.baeldung.axon.coreapi.commands.IncrementProductCountCommand; | ||||
| import com.baeldung.axon.coreapi.events.OrderConfirmedEvent; | ||||
| import com.baeldung.axon.coreapi.events.ProductCountDecrementedEvent; | ||||
| import com.baeldung.axon.coreapi.events.ProductCountIncrementedEvent; | ||||
| import com.baeldung.axon.coreapi.events.ProductRemovedEvent; | ||||
| import com.baeldung.axon.coreapi.exceptions.OrderAlreadyConfirmedException; | ||||
| import org.axonframework.commandhandling.CommandHandler; | ||||
| import org.axonframework.eventsourcing.EventSourcingHandler; | ||||
| import org.axonframework.modelling.command.EntityId; | ||||
| 
 | ||||
| import java.util.Objects; | ||||
| 
 | ||||
| import static org.axonframework.modelling.command.AggregateLifecycle.apply; | ||||
| 
 | ||||
| public class OrderLine { | ||||
| 
 | ||||
|     @EntityId | ||||
|     private final String productId; | ||||
|     private Integer count; | ||||
|     private boolean orderConfirmed; | ||||
| 
 | ||||
|     public OrderLine(String productId) { | ||||
|         this.productId = productId; | ||||
|         this.count = 1; | ||||
|     } | ||||
| 
 | ||||
|     @CommandHandler | ||||
|     public void handle(IncrementProductCountCommand command) { | ||||
|         if (orderConfirmed) { | ||||
|             throw new OrderAlreadyConfirmedException(command.getOrderId()); | ||||
|         } | ||||
| 
 | ||||
|         apply(new ProductCountIncrementedEvent(command.getOrderId(), productId)); | ||||
|     } | ||||
| 
 | ||||
|     @CommandHandler | ||||
|     public void handle(DecrementProductCountCommand command) { | ||||
|         if (orderConfirmed) { | ||||
|             throw new OrderAlreadyConfirmedException(command.getOrderId()); | ||||
|         } | ||||
| 
 | ||||
|         if (count <= 1) { | ||||
|             apply(new ProductRemovedEvent(command.getOrderId(), productId)); | ||||
|         } else { | ||||
|             apply(new ProductCountDecrementedEvent(command.getOrderId(), productId)); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     @EventSourcingHandler | ||||
|     public void on(ProductCountIncrementedEvent event) { | ||||
|         this.count++; | ||||
|     } | ||||
| 
 | ||||
|     @EventSourcingHandler | ||||
|     public void on(ProductCountDecrementedEvent event) { | ||||
|         this.count--; | ||||
|     } | ||||
| 
 | ||||
|     @EventSourcingHandler | ||||
|     public void on(OrderConfirmedEvent event) { | ||||
|         this.orderConfirmed = true; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public boolean equals(Object o) { | ||||
|         if (this == o) { | ||||
|             return true; | ||||
|         } | ||||
|         if (o == null || getClass() != o.getClass()) { | ||||
|             return false; | ||||
|         } | ||||
|         OrderLine orderLine = (OrderLine) o; | ||||
|         return Objects.equals(productId, orderLine.productId) && Objects.equals(count, orderLine.count); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public int hashCode() { | ||||
|         return Objects.hash(productId, count); | ||||
|     } | ||||
| } | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user