{"id":174,"date":"2020-02-25T00:11:07","date_gmt":"2020-02-25T00:11:07","guid":{"rendered":"https:\/\/www.kindsonthegenius.com\/microservices\/?p=174"},"modified":"2020-07-26T11:15:23","modified_gmt":"2020-07-26T11:15:23","slug":"cqrs-tutorial-with-axon-framework-step-by-step-project-for-beginners","status":"publish","type":"post","link":"https:\/\/www.kindsonthegenius.com\/microservices\/cqrs-tutorial-with-axon-framework-step-by-step-project-for-beginners\/","title":{"rendered":"CQRS Tutorial With Axon Framework (Step by Step FoodCart Project for Beginners)"},"content":{"rendered":"<p>This is a complete tutorial on CQRS and Event Sourcing based application using Axon Framework(Food Cart). For best learning experience, this step by step guide should go along with the video explanation<\/p>\n<p>We would cover the following:<\/p>\n<ol>\n<li><a href=\"#t1\">The application we would build(FoodCart)<\/a><\/li>\n<li><a href=\"#t2\">Setup the project in IntelliJ<\/a><\/li>\n<li><a href=\"#t3\">Build the Core API<\/a><\/li>\n<li><a href=\"#t4\">Develop the Command Model<\/a><\/li>\n<li><a href=\"#t5\">Develop the Query Model<\/a><\/li>\n<li><a href=\"#t6\">Connect to the UI<\/a><\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<h5><strong id=\"t1\">1. The application we would build<\/strong><\/h5>\n<p>As you follow the video lesson, ensure you understand the following concepts. I would be explaining them as I go<\/p>\n<ul>\n<li style=\"list-style-type: none;\">\n<ul>\n<li>The Structure of the Axon Application<\/li>\n<li>What is CQRS(Command Query Responsibility Segregation)<\/li>\n<li>What are Commands, Events and Queries<\/li>\n<li>DDD (Domain Driven Design)<\/li>\n<li>Event Sourcing<\/li>\n<li>Evolutionary Microservices<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>The Structure of a CQRS based application is shown below. The architecture explained in <a href=\"https:\/\/youtu.be\/BEYF1x48npw\" target=\"_blank\" rel=\"noopener noreferrer\">this video<\/a><\/p>\n<figure id=\"attachment_178\" aria-describedby=\"caption-attachment-178\" style=\"width: 513px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/www.kindsonthegenius.com\/microservices\/wp-content\/uploads\/sites\/18\/2020\/02\/Structure-of-a-CQRS-based-application-with-Axon-Framework.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-178\" src=\"https:\/\/www.kindsonthegenius.com\/microservices\/wp-content\/uploads\/sites\/18\/2020\/02\/Structure-of-a-CQRS-based-application-with-Axon-Framework.jpg\" alt=\"Structure of a CQRS based application with Axon Framework\" width=\"513\" height=\"289\" srcset=\"https:\/\/www.kindsonthegenius.com\/microservices\/wp-content\/uploads\/sites\/18\/2020\/02\/Structure-of-a-CQRS-based-application-with-Axon-Framework.jpg 995w, https:\/\/www.kindsonthegenius.com\/microservices\/wp-content\/uploads\/sites\/18\/2020\/02\/Structure-of-a-CQRS-based-application-with-Axon-Framework-300x169.jpg 300w, https:\/\/www.kindsonthegenius.com\/microservices\/wp-content\/uploads\/sites\/18\/2020\/02\/Structure-of-a-CQRS-based-application-with-Axon-Framework-768x432.jpg 768w\" sizes=\"auto, (max-width: 513px) 100vw, 513px\" \/><\/a><figcaption id=\"caption-attachment-178\" class=\"wp-caption-text\"><a href=\"https:\/\/youtu.be\/BEYF1x48npw\" target=\"_blank\" rel=\"noopener noreferrer\">Structure of a CQRS based application with Axon Framework<\/a><\/figcaption><\/figure>\n<h5><strong id=\"t2\">2. Setup the Project in IntelliJ<\/strong><\/h5>\n<p>Create a new project in IntelliJ.<\/p>\n<p>Add the dependencies:<\/p>\n<ul>\n<li>spring-boot-starter-data-jpa<\/li>\n<li>sprint-boot-starter-web<\/li>\n<li>h2-database (or another db)<\/li>\n<\/ul>\n<p>In the pom.xml, add the axon-springboot-starter dependency.<\/p>\n<p>This is shown below.<\/p>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #007700;\">&lt;dependency&gt;<\/span>\r\n    <span style=\"color: #007700;\">&lt;groupId&gt;<\/span>org.axonframework<span style=\"color: #007700;\">&lt;\/groupId&gt;<\/span>\r\n    <span style=\"color: #007700;\">&lt;artifactId&gt;<\/span>axon-spring-boot-starter<span style=\"color: #007700;\">&lt;\/artifactId&gt;<\/span>\r\n    <span style=\"color: #007700;\">&lt;version&gt;<\/span>4.3<span style=\"color: #007700;\">&lt;\/version&gt;<\/span>\r\n<span style=\"color: #007700;\">&lt;\/dependency&gt;<\/span>\r\n<\/pre>\n<p>The axon version should be 4.3!<\/p>\n<p>Create three packages:<\/p>\n<ul>\n<li><strong>command<\/strong>: expression of intent to perform some operation<\/li>\n<li><strong>query<\/strong>: notification that some operation have occurred<\/li>\n<li><strong>coreapi<\/strong>: request for data<\/li>\n<\/ul>\n<p>These three are different types of messages.<\/p>\n<p>Add the h2 database configuration in the application.properties file (<a href=\"https:\/\/www.kindsonthegenius.com\/h2-in-memory-database-step-by-step-tutorial\/\" target=\"_blank\" rel=\"noopener noreferrer\">get it from here<\/a>)<\/p>\n<p>&nbsp;<\/p>\n<h5><strong id=\"t3\">3. Build the Core\u00a0 API (an event-driven API)<\/strong><\/h5>\n<p>In this part, we are going to build the core api which is made up of commands, events and queries.<\/p>\n<p><strong>Commands:<\/strong> Create a kotlin file named commands in the commands package. Write the data class for <em>CreateFoodCartCommand<\/em>,\u00a0 <em>SelectProductCommand<\/em>, <em>DeselectProductCommand<\/em> and <em>ConfirmOrderCommand<\/em><\/p>\n<p>The codes for these four commands is given below:<br \/>\n<!-- HTML generated using hilite.me --><\/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;\">CreateFoodCartCommand<\/span>(\r\n        @TargetAggregateIdentifier\r\n        <span style=\"color: #008800; font-weight: bold;\">val<\/span> foodCartId: UUID\r\n)\r\n\r\ndata <span style=\"color: #008800; font-weight: bold;\">class<\/span> <span style=\"color: #0066bb; font-weight: bold;\">SelectProductCommand<\/span>(\r\n        @TargetAggregateIdentifier\r\n        <span style=\"color: #008800; font-weight: bold;\">val<\/span> foodCartId: UUID,\r\n        <span style=\"color: #008800; font-weight: bold;\">val<\/span> productId: UUID,\r\n        <span style=\"color: #008800; font-weight: bold;\">val<\/span> quantity: Int\r\n)\r\n\r\ndata <span style=\"color: #008800; font-weight: bold;\">class<\/span> <span style=\"color: #0066bb; font-weight: bold;\">DeselectProductCommand<\/span>(\r\n        @TargetAggregateIdentifier\r\n        <span style=\"color: #008800; font-weight: bold;\">val<\/span> foodCartId: UUID,\r\n        <span style=\"color: #008800; font-weight: bold;\">val<\/span> productId: UUID,\r\n        <span style=\"color: #008800; font-weight: bold;\">val<\/span> quantity: Int\r\n)\r\n\r\ndata <span style=\"color: #008800; font-weight: bold;\">class<\/span> <span style=\"color: #0066bb; font-weight: bold;\">ConfirmOrderCommand<\/span>(\r\n        @TargetAggregateIdentifier\r\n        <span style=\"color: #008800; font-weight: bold;\">val<\/span> foodCartId: UUID\r\n)\r\n<\/pre>\n<p>The <em>val<\/em> specification ensures that the fields are final fields.<\/p>\n<p><em>data class<\/em> provide equal and hash code and ToString() methods<\/p>\n<p>&nbsp;<\/p>\n<p><strong>Events:<\/strong> Create a kotlin file named events in the coreapi package.<\/p>\n<p>Write the data classes for the events corresponding to each command you wrote previously. This are shown in the code 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;\">FoodCardCreatedEvent<\/span>(\r\n        <span style=\"color: #008800; font-weight: bold;\">val<\/span> foodCardId: UUID\r\n)\r\n\r\ndata <span style=\"color: #008800; font-weight: bold;\">class<\/span> <span style=\"color: #0066bb; font-weight: bold;\">ProductSelectedEvent<\/span>(\r\n        <span style=\"color: #008800; font-weight: bold;\">val<\/span> foodCardId: UUID,\r\n        <span style=\"color: #008800; font-weight: bold;\">val<\/span> productId: UUID,\r\n        <span style=\"color: #008800; font-weight: bold;\">val<\/span> quantity: Int\r\n)\r\n\r\ndata <span style=\"color: #008800; font-weight: bold;\">class<\/span> <span style=\"color: #0066bb; font-weight: bold;\">ProductDeselectedEvent<\/span>(\r\n        <span style=\"color: #008800; font-weight: bold;\">val<\/span> foodCardId: UUID,\r\n        <span style=\"color: #008800; font-weight: bold;\">val<\/span> productId: UUID,\r\n        <span style=\"color: #008800; font-weight: bold;\">val<\/span> quantity: Int\r\n)\r\n\r\ndata <span style=\"color: #008800; font-weight: bold;\">class<\/span> <span style=\"color: #0066bb; font-weight: bold;\">OrderConfirmedEvent<\/span>(\r\n        <span style=\"color: #008800; font-weight: bold;\">val<\/span> foodCardId: UUID\r\n)\r\n<\/pre>\n<p>Note that for the events, an id is specified for the foodCardCreatedEvent. This is because, an event indicated that the foodCart has been created and therefore exists.<\/p>\n<p>&nbsp;<\/p>\n<p><strong>Queries:<\/strong> Create a kotlin class named queries. In it, write a data class for FindFoodCartQuery and another class for RetrieveProductOptions. 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;\">FindFoodCartQuery<\/span>(\r\n        <span style=\"color: #008800; font-weight: bold;\">val<\/span> foodCartId: UUID\r\n)\r\n\r\n<span style=\"color: #888888;\">\/\/Which products can be selected<\/span>\r\n<span style=\"color: #008800; font-weight: bold;\">class<\/span> <span style=\"color: #bb0066; font-weight: bold;\">RetrieveProductOptionsQuery<\/span>\r\n<\/pre>\n<p>&nbsp;<\/p>\n<h5><strong id=\"t4\">4. Develop the Command Model (Build the Aggregate)<\/strong><\/h5>\n<p><strong>Building the Aggregate:<\/strong> You need to create the FoodCart aggregate class in the commands package, create an empty constructor. Then annotate this class with the @Aggregate annotation.<\/p>\n<p>The @Aggregate annotation serves the following purpose:<\/p>\n<ul>\n<li>makes the framework creates an aggregate factory for us<\/li>\n<li>make the framework know that this class would contain commandhandler that would be subscribed to<\/li>\n<li>that this class would publish events and therefore provides the repository<\/li>\n<\/ul>\n<p>This aggregate should have two fields: the foodCardId and the selectedProducts<\/p>\n<p><strong>Handling Commands<\/strong>: Then you need to create a command handler for the constructor for FoodCart. Next, create two more command handlers for SelectProduct and DeselectProduct commands<\/p>\n<p>The three commandhandlers are shown below with an empty constructor as well<\/p>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #008800; font-weight: bold;\">public<\/span> <span style=\"color: #0066bb; font-weight: bold;\">FoodCart<\/span><span style=\"color: #333333;\">(){<\/span>\r\n\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;\">FoodCart<\/span><span style=\"color: #333333;\">(<\/span>CreateFoodCartCommand cmd<span style=\"color: #333333;\">){<\/span>\r\n    apply<span style=\"color: #333333;\">(<\/span><span style=\"color: #008800; font-weight: bold;\">new<\/span> FoodCartCreatedEvent<span style=\"color: #333333;\">(<\/span>cmd<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">getFoodCartId<\/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: #333399; font-weight: bold;\">void<\/span> <span style=\"color: #0066bb; font-weight: bold;\">handle<\/span><span style=\"color: #333333;\">(<\/span>SelectProductCommand cmd<span style=\"color: #333333;\">){<\/span>\r\n    apply<span style=\"color: #333333;\">(<\/span><span style=\"color: #008800; font-weight: bold;\">new<\/span> ProductSelectedEvent<span style=\"color: #333333;\">(<\/span>\r\n            foodCartId<span style=\"color: #333333;\">,<\/span>\r\n            cmd<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">getProductId<\/span><span style=\"color: #333333;\">(),<\/span>\r\n            cmd<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">getQuantity<\/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;\">@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>DeselectProductCommand cmd<span style=\"color: #333333;\">)<\/span>\r\n        <span style=\"color: #008800; font-weight: bold;\">throws<\/span> ProductDeselectedException <span style=\"color: #333333;\">{<\/span>\r\n    UUID productId <span style=\"color: #333333;\">=<\/span> cmd<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">getProductId<\/span><span style=\"color: #333333;\">();<\/span>\r\n    <span style=\"color: #008800; font-weight: bold;\">if<\/span><span style=\"color: #333333;\">(!<\/span>selectedProducts<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">containsKey<\/span><span style=\"color: #333333;\">(<\/span>productId<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;\">ProductDeselectedException<\/span><span style=\"color: #333333;\">();<\/span>\r\n    <span style=\"color: #333333;\">}<\/span>\r\n    apply<span style=\"color: #333333;\">(<\/span><span style=\"color: #008800; font-weight: bold;\">new<\/span> ProductDeselectedEvent<span style=\"color: #333333;\">(<\/span>\r\n            foodCartId<span style=\"color: #333333;\">,<\/span>\r\n            cmd<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">getProductId<\/span><span style=\"color: #333333;\">(),<\/span>\r\n            cmd<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">getQuantity<\/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>The @CommandHandler annotation tells the framework that this is a commandhandling function. So the method is registered to the command bus as capable of handling a particular command.<\/p>\n<p>&nbsp;<\/p>\n<p><strong>Event Sourcing the Aggregate:<\/strong> Here, you need to write the event sourcing handlers for FoodcartCreated, ProductSelected and ProductDeselected events.<\/p>\n<p>The methods are shown below<\/p>\n<pre style=\"margin: 0; line-height: 125%;\">@EventSourcingHandler\r\n<span style=\"color: #008800; font-weight: bold;\">public<\/span> <span style=\"color: #008800; font-weight: bold;\">void<\/span> <span style=\"color: #0066bb; font-weight: bold;\">on<\/span>(FoodCardCreatedEvent evt){\r\n    foodCardId = evt.getFoodCardId();\r\n    <span style=\"color: #888888;\">\/\/Instantiate the selected product<\/span>\r\n    <span style=\"color: #888888;\">\/\/once the foodcart is created<\/span>\r\n    selectedProducts = <span style=\"color: #008800; font-weight: bold;\">new<\/span> HashMap&lt;&gt;();\r\n}\r\n\r\n@EventSourcingHandler\r\n<span style=\"color: #008800; font-weight: bold;\">public<\/span> <span style=\"color: #008800; font-weight: bold;\">void<\/span> <span style=\"color: #0066bb; font-weight: bold;\">on<\/span>(ProductSelectedEvent evt){\r\n    selectedProducts.merge(evt.getProductId(), evt.getQuantity(), Integer::sum);\r\n}\r\n<span style=\"color: #888888;\">\/\/The merge() function is used to combine<\/span>\r\n<span style=\"color: #888888;\">\/\/ multiple mapped values for a key<\/span>\r\n<span style=\"color: #888888;\">\/\/ using the mapping function<\/span>\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p><strong>Validate the DeselectProduct command<\/strong><\/p>\n<p>You need to modify the DeleteProduct command to make sure the product being deselected actually exists. To do this, you need to check if the hashmap actually contains the given key.<\/p>\n<p>I also choose to create an exceptions kotlin file to place the ProductDeselectionException<\/p>\n<p>Now the modified DeselectProductCommand is shown below:<\/p>\n<pre style=\"margin: 0; line-height: 125%;\">@CommandHandler\r\n<span style=\"color: #008800; font-weight: bold;\">public<\/span> <span style=\"color: #008800; font-weight: bold;\">void<\/span> <span style=\"color: #0066bb; font-weight: bold;\">handle<\/span>(DeselectProductCommand cmd)\r\n        throws ProductDeselectedException {\r\n    UUID productId = cmd.getProductId();\r\n    <span style=\"color: #008800; font-weight: bold;\">if<\/span>(!selectedProducts.containsKey(productId)){\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;\">ProductDeselectedException<\/span>(); \r\n    }\r\n<span style=\"color: #888888;\">\/\/ apply() omitted<\/span>\r\n}\r\n<\/pre>\n<p><strong>Note<\/strong>: You need to create the ProductDeletedException() class in the coreapi package. It should inherit Exception (see video)<\/p>\n<p>&nbsp;<\/p>\n<h5><strong id=\"t5\">5. Develop the Query Model<\/strong><\/h5>\n<p>We would now build the query model, to handle events and queries.<\/p>\n<p>Create a file in the query package and name it FoodCartView.<\/p>\n<p>Create class with same name and annotate this class with @Entity annotation. This class should contain two fields:<\/p>\n<p>foodCartId and products<\/p>\n<p>Inside this class, create an interface FoodCartViewRepository that inherits JpaRepository. The code is given below:<\/p>\n<pre style=\"margin: 0; line-height: 125%;\">@Entity\r\ndata <span style=\"color: #008800; font-weight: bold;\">class<\/span> <span style=\"color: #0066bb; font-weight: bold;\">FoodCartView<\/span>(\r\n        @Id\r\n        <span style=\"color: #008800; font-weight: bold;\">val<\/span> foodCartId: UUID,\r\n        @ElementCollection\r\n        <span style=\"color: #008800; font-weight: bold;\">val<\/span> products: Map&lt;UUID, Int&gt;\r\n)\r\n\r\n<span style=\"color: #008800; font-weight: bold;\">interface<\/span> FoodCartViewRepository:JpaRepository&lt;FoodCartView, UUID&gt;\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>We need a component to handle the events and queries.<\/p>\n<p>So create a java class in the query package and call it FoodCartProjector. This would be in charge of projecting the FoodCartView as well as updating the FoodCardView.<\/p>\n<p>Annotate this class with @Component annotation<\/p>\n<p>In this class, create the repository variable and then the constructor.<\/p>\n<p>Create an EventHandler for FoodCartCreated event. This would simply create a new foodCart and persist it using the repository save() method.<\/p>\n<p>Create a QueryHandler to return find a FoodCart by Id<\/p>\n<p>The content of the FoodCartProjector is given below<\/p>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #008800; font-weight: bold;\">private<\/span> final FoodCartViewRepository repository;\r\n\r\n<span style=\"color: #008800; font-weight: bold;\">public<\/span> <span style=\"color: #0066bb; font-weight: bold;\">FoodCartProjector<\/span>(FoodCartViewRepository repository) {\r\n    <span style=\"color: #008800; font-weight: bold;\">this<\/span>.repository = repository;\r\n}\r\n\r\n@EventHandler\r\n<span style=\"color: #008800; font-weight: bold;\">public<\/span> <span style=\"color: #008800; font-weight: bold;\">void<\/span> <span style=\"color: #0066bb; font-weight: bold;\">on<\/span>(FoodCartCreatedEvent evt){\r\n    FoodCartView foodCartView = <span style=\"color: #008800; font-weight: bold;\">new<\/span> FoodCartView(\r\n            evt.getFoodCartId(), \r\n            Collections.emptyMap()\r\n    );\r\n}\r\n\r\n@QueryHandler\r\n<span style=\"color: #008800; font-weight: bold;\">public<\/span> FoodCartView <span style=\"color: #0066bb; font-weight: bold;\">handle<\/span>(FindFoodCartQuery query) {\r\n    <span style=\"color: #008800; font-weight: bold;\">return<\/span> repository.findById(\r\n            query.getFoodCartId())\r\n            .orElse(<span style=\"color: #008800; font-weight: bold;\">null<\/span>);\r\n}\r\n<\/pre>\n<p>&nbsp;<\/p>\n<h5><strong id=\"t6\">6. Connection to the UI<\/strong><\/h5>\n<p>Here we would introduce a component that we can invoke with regular REST operation. This UI component would us CommandGateway to dispatch command and query messages to the Framework<\/p>\n<p>Create a new package called the gui.<\/p>\n<p>In this\u00a0 FoodOrderingController in the gui package and annotate with with @RestController<\/p>\n<p>The content of the FoodOrderingController is given below:<\/p>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #008800; font-weight: bold;\">private<\/span> final CommandGateway commandGateway;\r\n<span style=\"color: #008800; font-weight: bold;\">private<\/span> final QueryGateway queryGateway;\r\n\r\n<span style=\"color: #008800; font-weight: bold;\">public<\/span> <span style=\"color: #0066bb; font-weight: bold;\">FoodOrderingController<\/span>(CommandGateway commandGateway, QueryGateway queryGateway) {\r\n    <span style=\"color: #008800; font-weight: bold;\">this<\/span>.commandGateway = commandGateway;\r\n    <span style=\"color: #008800; font-weight: bold;\">this<\/span>.queryGateway = queryGateway;\r\n}\r\n\r\n@PostMapping(<span style=\"background-color: #fff0f0;\">\"\/create\"<\/span>)\r\n<span style=\"color: #008800; font-weight: bold;\">public<\/span> <span style=\"color: #008800; font-weight: bold;\">void<\/span> <span style=\"color: #0066bb; font-weight: bold;\">handle<\/span>(){\r\n    commandGateway.send(<span style=\"color: #008800; font-weight: bold;\">new<\/span> CreateFoodCartCommand());\r\n}\r\n\r\n@GetMapping(<span style=\"background-color: #fff0f0;\">\"\/footcart\/{foodCartId\"<\/span>)\r\n<span style=\"color: #008800; font-weight: bold;\">public<\/span> CompletableFuture&lt;FoodCartView&gt; handle(@PathVariable(<span style=\"background-color: #fff0f0;\">\"foodCartId\"<\/span>) String foodCartId){\r\n    <span style=\"color: #008800; font-weight: bold;\">return<\/span> queryGateway.query(<span style=\"color: #008800; font-weight: bold;\">new<\/span> FindFoodCartQuery(UUID.fromString(foodCartId)),\r\n            ResponseTypes.instanceOf(FoodCartView.class));\r\n}\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>This is a complete tutorial on CQRS and Event Sourcing based application using Axon Framework(Food Cart). For best learning experience, this step by step guide &hellip; <\/p>\n","protected":false},"author":1,"featured_media":179,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[12,27],"tags":[26,55,6],"class_list":["post-174","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-axon","category-axonframework","tag-axon-framework","tag-coding","tag-cqrs"],"_links":{"self":[{"href":"https:\/\/www.kindsonthegenius.com\/microservices\/wp-json\/wp\/v2\/posts\/174","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=174"}],"version-history":[{"count":9,"href":"https:\/\/www.kindsonthegenius.com\/microservices\/wp-json\/wp\/v2\/posts\/174\/revisions"}],"predecessor-version":[{"id":240,"href":"https:\/\/www.kindsonthegenius.com\/microservices\/wp-json\/wp\/v2\/posts\/174\/revisions\/240"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.kindsonthegenius.com\/microservices\/wp-json\/wp\/v2\/media\/179"}],"wp:attachment":[{"href":"https:\/\/www.kindsonthegenius.com\/microservices\/wp-json\/wp\/v2\/media?parent=174"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.kindsonthegenius.com\/microservices\/wp-json\/wp\/v2\/categories?post=174"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.kindsonthegenius.com\/microservices\/wp-json\/wp\/v2\/tags?post=174"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}