{"id":90,"date":"2019-11-15T23:05:07","date_gmt":"2019-11-15T23:05:07","guid":{"rendered":"https:\/\/www.kindsonthegenius.com\/microservices\/?p=90"},"modified":"2019-11-15T23:05:07","modified_gmt":"2019-11-15T23:05:07","slug":"cqrs-with-axon-tutorial-part-5-build-the-query-module","status":"publish","type":"post","link":"https:\/\/www.kindsonthegenius.com\/microservices\/cqrs-with-axon-tutorial-part-5-build-the-query-module\/","title":{"rendered":"CQRS With Axon Tutorial: Part 5 \u2013 Build the Query Module"},"content":{"rendered":"<p>In this part, we would build the query module. This is in line with the CQRS principle: we separate the commands from the query.<\/p>\n<p>We would cover the following:<\/p>\n<ol>\n<li><a href=\"#t1\">Build the API<\/a><\/li>\n<li><a href=\"#t2\">Create the DataProvider<\/a><\/li>\n<li><a href=\"#t3\">A Brief Review<\/a><\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<h5><strong id=\"t1\">1. Build the Query API<\/strong><\/h5>\n<p>Follow the steps below:<\/p>\n<p><strong>Step 1<\/strong>: Add a kotlin file in the query package. Name it api. This file would hold the entity that would be stored in the database<\/p>\n<p><strong>Step 2<\/strong>: Annotate this class with the @Entity annotation<\/p>\n<p><strong>Step 3<\/strong>: Inside this file, create a data class with name CardSummary. The class will have the following parameters:<\/p>\n<ul>\n<li>id of string? intialized to null<\/li>\n<li>initialBalance of int? initialized to 0<\/li>\n<li>remainingBalance also int? initialized to 0<\/li>\n<\/ul>\n<p><strong>Step 4<\/strong>: Add the @id annotation to the id variable<\/p>\n<p>The content of the api.kt file is as given in the listing below:<\/p>\n<p>&nbsp;<\/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;\">CardSummary<\/span>(\r\n        @Id <span style=\"color: #008800; font-weight: bold;\">var<\/span> id: String? = <span style=\"color: #008800; font-weight: bold;\">null<\/span>,\r\n        <span style=\"color: #008800; font-weight: bold;\">var<\/span> initialBalance: Int? = <span style=\"color: #6600ee; font-weight: bold;\">0<\/span>,\r\n        <span style=\"color: #008800; font-weight: bold;\">var<\/span> remainingBalance: Int? =<span style=\"color: #6600ee; font-weight: bold;\">0<\/span>\r\n)\r\n<\/pre>\n<p>&nbsp;<\/p>\n<h5><strong id=\"t2\">2. Create the DataProvider<\/strong><\/h5>\n<p>We would have to create a dataProvider in the GiftCardGUI class.This is required to create a projection that would be used in the grid.<\/p>\n<p><strong>Step 1<\/strong>: In the GiftCardGUI, create a final private variable of DataProvider (see code below)<\/p>\n<p><strong>Step 2<\/strong>: Do a constructor injection of a QueryGateway<\/p>\n<p>At this point, the initial part of your GiftCardGUI would be the code listing below:<\/p>\n<p>&nbsp;<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #008800; font-weight: bold;\">private<\/span> <span style=\"color: #008800; font-weight: bold;\">final<\/span> CommandGateway commandGateway<span style=\"color: #333333;\">;<\/span>\r\n<span style=\"color: #008800; font-weight: bold;\">private<\/span> <span style=\"color: #008800; font-weight: bold;\">final<\/span> DataProvider<span style=\"color: #333333;\">&lt;<\/span>CardSummary<span style=\"color: #333333;\">,<\/span> Void<span style=\"color: #333333;\">&gt;<\/span> dataProvider<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;\">GiftCardGUI<\/span><span style=\"color: #333333;\">(<\/span>CommandGateway commandGateway<span style=\"color: #333333;\">,<\/span> QueryGateway queryGateway<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;\">commandGateway<\/span> <span style=\"color: #333333;\">=<\/span> commandGateway<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;\">dataProvider<\/span> <span style=\"color: #333333;\">=<\/span> dataProvider<span style=\"color: #333333;\">(<\/span>queryGateway<span style=\"color: #333333;\">);<\/span>\r\n<span style=\"color: #333333;\">}<\/span>\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p><strong>Step 3:<\/strong> Place your cursor on the dataProvider(queryGateway) code which underlined with red squiggly lines.<\/p>\n<p><strong>Step 4:<\/strong> Choose &#8216;Create method dataProvider in GiftCardGUI&#8217;.<\/p>\n<p>The method is create for you.<\/p>\n<p><strong>Step 5:<\/strong> Make this method return &#8216;new AbstractBackEndDataProvider. Make sure to use the intellisense to complete this statement.<\/p>\n<p>You will see that two additional methods are added: fetchFromBackEnd() and sizeInBackEnd. We now need to implement these methods. Before write implement these method, we need to create a DataQuery and SizeQuery in the api.kt file<\/p>\n<p><strong>Step 6<\/strong>: Open the api.kt file (in the query module)<\/p>\n<p><strong>Step 7<\/strong>: Create a data class named DataQuery. This class should have two integer attributes offset and limit (see code below)<\/p>\n<p><strong>Step 8:<\/strong> Create another class (not data class) with name SizeQuery with no attributes.<\/p>\n<p>The code for the two classes is shown below<\/p>\n<p>&nbsp;<\/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;\">DataQuery<\/span>(<span style=\"color: #008800; font-weight: bold;\">val<\/span> offset: Int, <span style=\"color: #008800; font-weight: bold;\">val<\/span> limit: Int)\r\n<span style=\"color: #008800; font-weight: bold;\">class<\/span> <span style=\"color: #bb0066; font-weight: bold;\">SizeQuery<\/span>\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>Now back to the GiftCardGUI<\/p>\n<p><strong>Step 9<\/strong>: Now implement the two methods. The complete implementation is given below:<br \/>\n<!-- HTML generated using hilite.me --><\/p>\n<p>&nbsp;<\/p>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #008800; font-weight: bold;\">private<\/span> DataProvider<span style=\"color: #333333;\">&lt;<\/span>CardSummary<span style=\"color: #333333;\">,<\/span> Void<span style=\"color: #333333;\">&gt;<\/span> dataProvider<span style=\"color: #333333;\">(<\/span>QueryGateway queryGateway<span style=\"color: #333333;\">)<\/span> <span style=\"color: #333333;\">{<\/span>\r\n    <span style=\"color: #008800; font-weight: bold;\">return<\/span> <span style=\"color: #008800; font-weight: bold;\">new<\/span> AbstractBackEndDataProvider<span style=\"color: #333333;\">&lt;<\/span>CardSummary<span style=\"color: #333333;\">,<\/span> Void<span style=\"color: #333333;\">&gt;()<\/span> <span style=\"color: #333333;\">{<\/span>\r\n        <span style=\"color: #555555; font-weight: bold;\">@Override<\/span>\r\n        <span style=\"color: #008800; font-weight: bold;\">protected<\/span> Stream<span style=\"color: #333333;\">&lt;<\/span>CardSummary<span style=\"color: #333333;\">&gt;<\/span> <span style=\"color: #0066bb; font-weight: bold;\">fetchFromBackEnd<\/span><span style=\"color: #333333;\">(<\/span>Query<span style=\"color: #333333;\">&lt;<\/span>CardSummary<span style=\"color: #333333;\">,<\/span> Void<span style=\"color: #333333;\">&gt;<\/span> query<span style=\"color: #333333;\">)<\/span> <span style=\"color: #333333;\">{<\/span>\r\n            <span style=\"color: #008800; font-weight: bold;\">return<\/span> queryGateway<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">query<\/span><span style=\"color: #333333;\">(<\/span><span style=\"color: #008800; font-weight: bold;\">new<\/span> DataQuery<span style=\"color: #333333;\">(<\/span>query<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">getOffset<\/span><span style=\"color: #333333;\">(),<\/span> query<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">getLimit<\/span><span style=\"color: #333333;\">()),<\/span>\r\n                    ResponseTypes<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">multipleInstancesOf<\/span><span style=\"color: #333333;\">(<\/span>CardSummary<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">class<\/span><span style=\"color: #333333;\">)<\/span>\r\n            <span style=\"color: #333333;\">).<\/span><span style=\"color: #0000cc;\">join<\/span><span style=\"color: #333333;\">()<\/span>\r\n             <span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">stream<\/span><span style=\"color: #333333;\">();<\/span>\r\n        <span style=\"color: #333333;\">}<\/span>\r\n\r\n        <span style=\"color: #555555; font-weight: bold;\">@Override<\/span>\r\n        <span style=\"color: #008800; font-weight: bold;\">protected<\/span> <span style=\"color: #333399; font-weight: bold;\">int<\/span> <span style=\"color: #0066bb; font-weight: bold;\">sizeInBackEnd<\/span><span style=\"color: #333333;\">(<\/span>Query<span style=\"color: #333333;\">&lt;<\/span>CardSummary<span style=\"color: #333333;\">,<\/span> Void<span style=\"color: #333333;\">&gt;<\/span> query<span style=\"color: #333333;\">)<\/span> <span style=\"color: #333333;\">{<\/span>\r\n            <span style=\"color: #008800; font-weight: bold;\">return<\/span> queryGateway<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">query<\/span><span style=\"color: #333333;\">(<\/span><span style=\"color: #008800; font-weight: bold;\">new<\/span> SizeQuery<span style=\"color: #333333;\">(),<\/span>\r\n                    ResponseTypes<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">instanceOf<\/span><span style=\"color: #333333;\">(<\/span>Integer<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">class<\/span><span style=\"color: #333333;\">))<\/span>\r\n                    <span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">join<\/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<\/pre>\n<p>&nbsp;<\/p>\n<h5><strong id=\"t3\">3. A Brief Review<\/strong><\/h5>\n<p>We started by creating the entity class that would represent\u00a0 the data model (GiftCard)<\/p>\n<p>Then we added a DataProvider variable to the GiftCardGUI<\/p>\n<p>Then we did a construction injection of the DataProvider into the class<\/p>\n<p>We then went to the api file and added DataQuery data class and a SizeQuery class<\/p>\n<p>Finally we implemented the dataProvider method which returns a AbstractBackEndDataProvider object in which implemented the two required methods FetchFromBackEnd() and SizeInBackEnd().<\/p>\n<p>&nbsp;<\/p>\n<p>In the next part, we would then create the summaryProjection.<\/p>\n<p>Remember you can download the complete code from my <a href=\"https:\/\/github.com\/KindsonTheGenius\/gc-webinar\">github repository.<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this part, we would build the query module. This is in line with the CQRS principle: we separate the commands from the query. We &hellip; <\/p>\n","protected":false},"author":1,"featured_media":91,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[12,27,2],"tags":[],"class_list":["post-90","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-axon","category-axonframework","category-microservices"],"_links":{"self":[{"href":"https:\/\/www.kindsonthegenius.com\/microservices\/wp-json\/wp\/v2\/posts\/90","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=90"}],"version-history":[{"count":1,"href":"https:\/\/www.kindsonthegenius.com\/microservices\/wp-json\/wp\/v2\/posts\/90\/revisions"}],"predecessor-version":[{"id":92,"href":"https:\/\/www.kindsonthegenius.com\/microservices\/wp-json\/wp\/v2\/posts\/90\/revisions\/92"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.kindsonthegenius.com\/microservices\/wp-json\/wp\/v2\/media\/91"}],"wp:attachment":[{"href":"https:\/\/www.kindsonthegenius.com\/microservices\/wp-json\/wp\/v2\/media?parent=90"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.kindsonthegenius.com\/microservices\/wp-json\/wp\/v2\/categories?post=90"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.kindsonthegenius.com\/microservices\/wp-json\/wp\/v2\/tags?post=90"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}