{"id":197,"date":"2020-04-08T16:29:47","date_gmt":"2020-04-08T16:29:47","guid":{"rendered":"https:\/\/www.kindsonthegenius.com\/microservices\/?p=197"},"modified":"2020-12-09T08:35:32","modified_gmt":"2020-12-09T08:35:32","slug":"complete-cqrs-application-with-axon-framework-1-step-by-step-guide","status":"publish","type":"post","link":"https:\/\/www.kindsonthegenius.com\/microservices\/complete-cqrs-application-with-axon-framework-1-step-by-step-guide\/","title":{"rendered":"Complete CQRS Application with Axon Framework &#8211; 1 (Step by Step Guide)"},"content":{"rendered":"<p>We would build a complete CQRS application with Axon Framework. I would help you understand the various components that make up a CQRS application. This would be done in two parts:<\/p>\n<ul>\n<li>build the API<\/li>\n<li>build the UI<\/li>\n<\/ul>\n<p>This would be a simple eCommerce application that allows users to place orders. Then when an order is placed, the product stock is updated. In this part we would cover:<\/p>\n<ol>\n<li><a href=\"#t1\">The Transaction Steps<\/a><\/li>\n<li><a href=\"#t2\">The Read and Write Models<\/a><\/li>\n<li><a href=\"#t3\">The Commands and Events<\/a><\/li>\n<li><a href=\"#vid\">Watch the Video<\/a><\/li>\n<\/ol>\n<p>Before we proceed, let&#8217;s present the logical flow of the application.<\/p>\n<p>&nbsp;<\/p>\n<h5><strong id=\"t1\">1. The Transaction Steps<\/strong><\/h5>\n<ul>\n<li>A user clicks on the the &#8220;Order Now!&#8221; button in the UI from a browser<\/li>\n<li>A REST\/JSON request is raised and is routed to the controller<\/li>\n<li>The orderController creates a new order command and sends it via the command gateway (onto the command bus)<\/li>\n<li>The command is routed to the command handler (by the command bus)<\/li>\n<li>The order command handler creates a\u00a0 new order based on the details it received (this is event-sourced)<\/li>\n<li>When the new order is created, it is persisted in the Write DB via the orderRepository<\/li>\n<li>The repository insert emits an order created event<\/li>\n<li>Then using the productId, we retrieve the particular Product aggregate from the Repository (org.axonframework.modelling.command.Repository)<\/li>\n<li>This retrieved product then executes its updateStock using a new UpdateStockCommand as parameter<\/li>\n<li>At this point, the stock is deprecated. This change is effected in the repository and persisted in the Write DB<\/li>\n<li>This repository changes, fires a StockUpdated event<\/li>\n<li>The event handler for StockUpdated event receives this event together with the details<\/li>\n<li>Then the event handler, makes the necessary update in the Read model as well<\/li>\n<\/ul>\n<p>Let&#8217;s now examine the various code components of this workflow<\/p>\n<p>&nbsp;<\/p>\n<h5><strong id=\"t2\">2. The Read and Write Models<\/strong><\/h5>\n<p>As you know, in a CQRS architecture, there are two models.<\/p>\n<p><strong>the Read Model:<\/strong> the normal entity which we always used. A java class annotated with @Entity annotation and represents objects to the stored in the database. This model interface with the data store by extending the import org.springframework.data.jpa.repository.JpaRepository (or CrudRepository).<\/p>\n<p>In this demo, we call the read model for the product, ProductSummary and the code is given below.<\/p>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #555555; font-weight: bold;\">@Entity<\/span>\r\n<span style=\"color: #555555; font-weight: bold;\">@Data<\/span>\r\n<span style=\"color: #555555; font-weight: bold;\">@NoArgsConstructor<\/span>\r\n<span style=\"color: #008800; font-weight: bold;\">public<\/span> <span style=\"color: #008800; font-weight: bold;\">class<\/span> <span style=\"color: #bb0066; font-weight: bold;\">ProductSummary<\/span> <span style=\"color: #333333;\">{<\/span>\r\n    <span style=\"color: #555555; font-weight: bold;\">@Id<\/span>\r\n    <span style=\"color: #008800; font-weight: bold;\">private<\/span> String  id<span style=\"color: #333333;\">;<\/span>\r\n    <span style=\"color: #008800; font-weight: bold;\">private<\/span> Double price<span style=\"color: #333333;\">;<\/span>\r\n    <span style=\"color: #008800; font-weight: bold;\">private<\/span> Integer stock<span style=\"color: #333333;\">;<\/span>\r\n    <span style=\"color: #008800; font-weight: bold;\">private<\/span> String description<span style=\"color: #333333;\">;<\/span>\r\n\r\n    <span style=\"color: #008800; font-weight: bold;\">public<\/span> <span style=\"color: #0066bb; font-weight: bold;\">ProductSummary<\/span><span style=\"color: #333333;\">(<\/span>String id<span style=\"color: #333333;\">,<\/span> Double price<span style=\"color: #333333;\">,<\/span> Integer stock<span style=\"color: #333333;\">,<\/span> String description<span style=\"color: #333333;\">)<\/span> <span style=\"color: #333333;\">{<\/span>\r\n        <span style=\"color: #008800; font-weight: bold;\">this<\/span><span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">id<\/span> <span style=\"color: #333333;\">=<\/span> id<span style=\"color: #333333;\">;<\/span>\r\n        <span style=\"color: #008800; font-weight: bold;\">this<\/span><span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">price<\/span> <span style=\"color: #333333;\">=<\/span> price<span style=\"color: #333333;\">;<\/span>\r\n        <span style=\"color: #008800; font-weight: bold;\">this<\/span><span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">stock<\/span> <span style=\"color: #333333;\">=<\/span> stock<span style=\"color: #333333;\">;<\/span>\r\n        <span style=\"color: #008800; font-weight: bold;\">this<\/span><span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">description<\/span> <span style=\"color: #333333;\">=<\/span> description<span style=\"color: #333333;\">;<\/span>\r\n    <span style=\"color: #333333;\">}<\/span>\r\n<span style=\"color: #333333;\">}<\/span>\r\n<\/pre>\n<p>As for the Order, get it from my <a href=\"https:\/\/github.com\/KindsonTheGenius\/Ecomm\">github repo here<\/a>.<\/p>\n<p>&nbsp;<\/p>\n<p><strong>the Write Model<\/strong>: basically same thing with some differences. However, this is called an aggregate and annotated with @Aggregate annotation. This model interfaces with the data store through a repository that extends org.axonframework.modelling.command.Repository.<\/p>\n<p>In this demo, the write model is called Product as given below.<\/p>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #555555; font-weight: bold;\">@Aggregate<\/span>\r\n<span style=\"color: #008800; font-weight: bold;\">public<\/span> <span style=\"color: #008800; font-weight: bold;\">class<\/span> <span style=\"color: #bb0066; font-weight: bold;\">Product<\/span> <span style=\"color: #333333;\">{<\/span>\r\n    <span style=\"color: #555555; font-weight: bold;\">@AggregateIdentifier<\/span>\r\n    <span style=\"color: #008800; font-weight: bold;\">private<\/span> String id<span style=\"color: #333333;\">;<\/span>\r\n    <span style=\"color: #008800; font-weight: bold;\">private<\/span> Double price<span style=\"color: #333333;\">;<\/span>\r\n    <span style=\"color: #008800; font-weight: bold;\">private<\/span> Integer stock<span style=\"color: #333333;\">;<\/span>\r\n    <span style=\"color: #008800; font-weight: bold;\">private<\/span> String description<span style=\"color: #333333;\">;<\/span>\r\n\r\n    <span style=\"color: #008800; font-weight: bold;\">public<\/span> <span style=\"color: #0066bb; font-weight: bold;\">Product<\/span><span style=\"color: #333333;\">()<\/span> <span style=\"color: #333333;\">{<\/span>\r\n    <span style=\"color: #333333;\">}<\/span>\r\n\r\n    <span style=\"color: #555555; font-weight: bold;\">@CommandHandler<\/span>\r\n    <span style=\"color: #008800; font-weight: bold;\">public<\/span> <span style=\"color: #0066bb; font-weight: bold;\">Product<\/span><span style=\"color: #333333;\">(<\/span>AddProductCommand cmd<span style=\"color: #333333;\">){<\/span>\r\n        apply<span style=\"color: #333333;\">(<\/span> <span style=\"color: #008800; font-weight: bold;\">new<\/span> ProductAddedEvent<span style=\"color: #333333;\">(<\/span>\r\n                cmd<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">getId<\/span><span style=\"color: #333333;\">(),<\/span>\r\n                cmd<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">getPrice<\/span><span style=\"color: #333333;\">(),<\/span>\r\n                cmd<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">getStock<\/span><span style=\"color: #333333;\">(),<\/span>\r\n                cmd<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">getDescription<\/span><span style=\"color: #333333;\">()<\/span>\r\n                <span style=\"color: #333333;\">)<\/span>\r\n        <span style=\"color: #333333;\">);<\/span>\r\n    <span style=\"color: #333333;\">}<\/span>\r\n\r\n    <span style=\"color: #555555; font-weight: bold;\">@CommandHandler<\/span>\r\n    <span style=\"color: #008800; font-weight: bold;\">public<\/span> <span style=\"color: #333399; font-weight: bold;\">void<\/span> <span style=\"color: #0066bb; font-weight: bold;\">handle<\/span><span style=\"color: #333333;\">(<\/span>UpdateStockCommand cmd<span style=\"color: #333333;\">){<\/span>\r\n        <span style=\"color: #008800; font-weight: bold;\">if<\/span><span style=\"color: #333333;\">(<\/span><span style=\"color: #008800; font-weight: bold;\">this<\/span><span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">stock<\/span> <span style=\"color: #333333;\">&gt;=<\/span> cmd<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">getStock<\/span><span style=\"color: #333333;\">()){<\/span>\r\n            apply<span style=\"color: #333333;\">(<\/span><span style=\"color: #008800; font-weight: bold;\">new<\/span> StockUpdatedEvent<span style=\"color: #333333;\">(<\/span>\r\n                    cmd<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">getId<\/span><span style=\"color: #333333;\">(),<\/span> \r\n                    cmd<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">getStock<\/span><span style=\"color: #333333;\">())<\/span>\r\n            <span style=\"color: #333333;\">);<\/span>\r\n        <span style=\"color: #333333;\">}<\/span>\r\n        <span style=\"color: #008800; font-weight: bold;\">else<\/span> <span style=\"color: #333333;\">{<\/span>\r\n            <span style=\"color: #008800; font-weight: bold;\">throw<\/span> <span style=\"color: #008800; font-weight: bold;\">new<\/span> <span style=\"color: #0066bb; font-weight: bold;\">RuntimeException<\/span><span style=\"color: #333333;\">(<\/span><span style=\"background-color: #fff0f0;\">\"Out of Stock!\"<\/span><span style=\"color: #333333;\">);<\/span>\r\n        <span style=\"color: #333333;\">}<\/span>\r\n    <span style=\"color: #333333;\">}<\/span>\r\n\r\n    <span style=\"color: #555555; font-weight: bold;\">@EventSourcingHandler<\/span>\r\n    <span style=\"color: #008800; font-weight: bold;\">public<\/span> <span style=\"color: #333399; font-weight: bold;\">void<\/span> <span style=\"color: #0066bb; font-weight: bold;\">on<\/span><span style=\"color: #333333;\">(<\/span>StockUpdatedEvent evt<span style=\"color: #333333;\">){<\/span>\r\n        id <span style=\"color: #333333;\">=<\/span> evt<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">getId<\/span><span style=\"color: #333333;\">();<\/span>\r\n        stock <span style=\"color: #333333;\">=<\/span> stock <span style=\"color: #333333;\">-<\/span> evt<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">getStock<\/span><span style=\"color: #333333;\">();<\/span>\r\n    <span style=\"color: #333333;\">}<\/span>\r\n\r\n    <span style=\"color: #555555; font-weight: bold;\">@EventSourcingHandler<\/span>\r\n    <span style=\"color: #008800; font-weight: bold;\">public<\/span> <span style=\"color: #333399; font-weight: bold;\">void<\/span> <span style=\"color: #0066bb; font-weight: bold;\">on<\/span><span style=\"color: #333333;\">(<\/span>ProductAddedEvent evt<span style=\"color: #333333;\">){<\/span>\r\n        id <span style=\"color: #333333;\">=<\/span> evt<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">getId<\/span><span style=\"color: #333333;\">();<\/span>\r\n        price <span style=\"color: #333333;\">=<\/span> evt<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">getPrice<\/span><span style=\"color: #333333;\">();<\/span>\r\n        stock <span style=\"color: #333333;\">=<\/span> evt<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">getStock<\/span><span style=\"color: #333333;\">();<\/span>\r\n        description <span style=\"color: #333333;\">=<\/span> evt<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">getDescription<\/span><span style=\"color: #333333;\">();<\/span>\r\n    <span style=\"color: #333333;\">}<\/span>\r\n<span style=\"color: #333333;\">}<\/span>\r\n<\/pre>\n<p>&nbsp;<\/p>\n<h5><strong id=\"t3\">3. The Commands and Events<\/strong><\/h5>\n<p>In CQRS terms, a command is an expression of intent to perform certain operation while an event is a notification that an operation has occurred. So in our Ecommerce demo application, what commands can you think of? How about this:<\/p>\n<p><strong>CreateOrder<\/strong>: that is to place a new order for a product<\/p>\n<p><strong>UpdateStock<\/strong>: deduct the number of product from the stock when an order is placed<\/p>\n<p><strong>AddProduct<\/strong>: add a new product to the stock<\/p>\n<p>Note that, for each command, there is a corresponding event.\u00a0 For this demo, I have placed the commands and events inside the api package. The three commands are placed inside\u00a0 the commands.kt kotlin file while the events are placed inside the events.kt file. This is shown below:<\/p>\n<pre style=\"margin: 0; line-height: 125%;\">data <span style=\"color: #008800; font-weight: bold;\">class<\/span> <span style=\"color: #0066bb; font-weight: bold;\">CreateOrderCommand<\/span> (\r\n        @TargetAggregateIdentifier\r\n        <span style=\"color: #008800; font-weight: bold;\">val<\/span> orderId: String,\r\n        <span style=\"color: #008800; font-weight: bold;\">val<\/span> price: Double,\r\n        <span style=\"color: #008800; font-weight: bold;\">val<\/span> number:Int,\r\n        <span style=\"color: #008800; font-weight: bold;\">val<\/span> productId:String\r\n)\r\n\r\ndata <span style=\"color: #008800; font-weight: bold;\">class<\/span> <span style=\"color: #0066bb; font-weight: bold;\">AddProductCommand<\/span> (\r\n        @TargetAggregateIdentifier\r\n        <span style=\"color: #008800; font-weight: bold;\">val<\/span> id: String,\r\n        <span style=\"color: #008800; font-weight: bold;\">val<\/span> price: Double,\r\n        <span style=\"color: #008800; font-weight: bold;\">val<\/span> stock:Int,\r\n        <span style=\"color: #008800; font-weight: bold;\">val<\/span> description: String\r\n)\r\n\r\ndata <span style=\"color: #008800; font-weight: bold;\">class<\/span>  <span style=\"color: #0066bb; font-weight: bold;\">UpdateStockCommand<\/span>(\r\n        @TargetAggregateIdentifier\r\n        <span style=\"color: #008800; font-weight: bold;\">val<\/span> id: String,\r\n        <span style=\"color: #008800; font-weight: bold;\">val<\/span> stock: Int\r\n)\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>The events are given below:<\/p>\n<pre style=\"margin: 0; line-height: 125%;\">data <span style=\"color: #008800; font-weight: bold;\">class<\/span> <span style=\"color: #0066bb; font-weight: bold;\">OrderCreatedEvent<\/span> (\r\n        <span style=\"color: #008800; font-weight: bold;\">val<\/span> orderId: String,\r\n        <span style=\"color: #008800; font-weight: bold;\">val<\/span> price: Double,\r\n        <span style=\"color: #008800; font-weight: bold;\">val<\/span> number:Int,\r\n        <span style=\"color: #008800; font-weight: bold;\">val<\/span> productId:String\r\n)\r\n\r\ndata <span style=\"color: #008800; font-weight: bold;\">class<\/span> <span style=\"color: #0066bb; font-weight: bold;\">ProductAddedEvent<\/span> (\r\n        <span style=\"color: #008800; font-weight: bold;\">val<\/span> id: String,\r\n        <span style=\"color: #008800; font-weight: bold;\">val<\/span> price: Double,\r\n        <span style=\"color: #008800; font-weight: bold;\">val<\/span> stock:Int,\r\n        <span style=\"color: #008800; font-weight: bold;\">val<\/span> description: String\r\n)\r\n\r\ndata <span style=\"color: #008800; font-weight: bold;\">class<\/span> <span style=\"color: #0066bb; font-weight: bold;\">StockUpdatedEvent<\/span>(\r\n        <span style=\"color: #008800; font-weight: bold;\">val<\/span> id:String,\r\n        <span style=\"color: #008800; font-weight: bold;\">val<\/span> stock: Int\r\n)\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p><strong>What&#8217;s Left?<\/strong><\/p>\n<p>So next we would have to define the event handlers. Then we also create the controller file that receives request from the client. This is covered in the next part!<\/p>\n<p><iframe loading=\"lazy\" src=\"https:\/\/www.youtube.com\/embed\/dUl13dgPky0\" width=\"100%\" height=\"315\" frameborder=\"0\" allowfullscreen=\"allowfullscreen\"><\/iframe><\/p>\n","protected":false},"excerpt":{"rendered":"<p>We would build a complete CQRS application with Axon Framework. I would help you understand the various components that make up a CQRS application. This &hellip; <\/p>\n","protected":false},"author":1,"featured_media":199,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[12,27],"tags":[6,8],"class_list":["post-197","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-axon","category-axonframework","tag-cqrs","tag-event-sourcing"],"_links":{"self":[{"href":"https:\/\/www.kindsonthegenius.com\/microservices\/wp-json\/wp\/v2\/posts\/197","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.kindsonthegenius.com\/microservices\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.kindsonthegenius.com\/microservices\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.kindsonthegenius.com\/microservices\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.kindsonthegenius.com\/microservices\/wp-json\/wp\/v2\/comments?post=197"}],"version-history":[{"count":6,"href":"https:\/\/www.kindsonthegenius.com\/microservices\/wp-json\/wp\/v2\/posts\/197\/revisions"}],"predecessor-version":[{"id":366,"href":"https:\/\/www.kindsonthegenius.com\/microservices\/wp-json\/wp\/v2\/posts\/197\/revisions\/366"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.kindsonthegenius.com\/microservices\/wp-json\/wp\/v2\/media\/199"}],"wp:attachment":[{"href":"https:\/\/www.kindsonthegenius.com\/microservices\/wp-json\/wp\/v2\/media?parent=197"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.kindsonthegenius.com\/microservices\/wp-json\/wp\/v2\/categories?post=197"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.kindsonthegenius.com\/microservices\/wp-json\/wp\/v2\/tags?post=197"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}