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; | package com.baeldung.axon.commandmodel.order; | ||||||
| 
 |  | ||||||
| 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; |  | ||||||
| 
 | 
 | ||||||
|  | import com.baeldung.axon.coreapi.commands.AddProductCommand; | ||||||
| import com.baeldung.axon.coreapi.commands.ConfirmOrderCommand; | import com.baeldung.axon.coreapi.commands.ConfirmOrderCommand; | ||||||
| import com.baeldung.axon.coreapi.commands.PlaceOrderCommand; | import com.baeldung.axon.coreapi.commands.PlaceOrderCommand; | ||||||
| import com.baeldung.axon.coreapi.commands.ShipOrderCommand; | import com.baeldung.axon.coreapi.commands.ShipOrderCommand; | ||||||
| import com.baeldung.axon.coreapi.events.OrderConfirmedEvent; | import com.baeldung.axon.coreapi.events.OrderConfirmedEvent; | ||||||
| import com.baeldung.axon.coreapi.events.OrderPlacedEvent; | import com.baeldung.axon.coreapi.events.OrderPlacedEvent; | ||||||
| import com.baeldung.axon.coreapi.events.OrderShippedEvent; | 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 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 | @Aggregate | ||||||
| public class OrderAggregate { | public class OrderAggregate { | ||||||
| @ -22,13 +30,33 @@ public class OrderAggregate { | |||||||
|     private String orderId; |     private String orderId; | ||||||
|     private boolean orderConfirmed; |     private boolean orderConfirmed; | ||||||
| 
 | 
 | ||||||
|  |     @AggregateMember | ||||||
|  |     private Map<String, OrderLine> orderLines; | ||||||
|  | 
 | ||||||
|     @CommandHandler |     @CommandHandler | ||||||
|     public OrderAggregate(PlaceOrderCommand command) { |     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 |     @CommandHandler | ||||||
|     public void handle(ConfirmOrderCommand command) { |     public void handle(ConfirmOrderCommand command) { | ||||||
|  |         if (orderConfirmed) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         apply(new OrderConfirmedEvent(orderId)); |         apply(new OrderConfirmedEvent(orderId)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -45,6 +73,7 @@ public class OrderAggregate { | |||||||
|     public void on(OrderPlacedEvent event) { |     public void on(OrderPlacedEvent event) { | ||||||
|         this.orderId = event.getOrderId(); |         this.orderId = event.getOrderId(); | ||||||
|         this.orderConfirmed = false; |         this.orderConfirmed = false; | ||||||
|  |         this.orderLines = new HashMap<>(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @EventSourcingHandler |     @EventSourcingHandler | ||||||
| @ -52,8 +81,18 @@ public class OrderAggregate { | |||||||
|         this.orderConfirmed = true; |         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() { |     protected OrderAggregate() { | ||||||
|         // Required by Axon to build a default Aggregate prior to Event Sourcing |         // 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