{"id":93,"date":"2019-11-16T23:12:08","date_gmt":"2019-11-16T23:12:08","guid":{"rendered":"https:\/\/www.kindsonthegenius.com\/microservices\/?p=93"},"modified":"2019-11-17T16:39:48","modified_gmt":"2019-11-17T16:39:48","slug":"cqrs-with-axon-tutorial-part-6-build-the-summary-projection","status":"publish","type":"post","link":"https:\/\/www.kindsonthegenius.com\/microservices\/cqrs-with-axon-tutorial-part-6-build-the-summary-projection\/","title":{"rendered":"CQRS With Axon Tutorial: Part 6 \u2013 Build the Summary Projection"},"content":{"rendered":"<p>In this part we would create the summary projection class.This class would be part of the query package.<\/p>\n<p>This is would be a spring bean (annotated with @Component annotation) and would be responsible for handle persistence. So it would be able to saved data. Also, it should retrieve data from the database to be displayed on the grid in the GUI.<\/p>\n<p>&nbsp;<\/p>\n<p>Follow the 14 steps given below:<\/p>\n<p><strong>Step 1:<\/strong> Create a java class in the query package. Name it SummaryProjection<\/p>\n<p><strong>Step 2:<\/strong> Annotate the class with the @Component annotation<\/p>\n<p><strong>Step 3:<\/strong> Add a final private variable of type EntityManager<\/p>\n<p><strong>Step 4:<\/strong> Add a constructor and inject the EntityManager variable<\/p>\n<p>The code for step 3 and 4 is shown below<\/p>\n<p>&nbsp;<\/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> EntityManager entityManager<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;\">SummaryProjection<\/span><span style=\"color: #333333;\">(<\/span>EntityManager entityManager<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;\">entityManager<\/span> <span style=\"color: #333333;\">=<\/span> entityManager<span style=\"color: #333333;\">;<\/span>\r\n<span style=\"color: #333333;\">}<\/span>\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p><strong>Step 5:<\/strong> Create event handlers for the IssuedEvent() and RedeemedEvent()<\/p>\n<p><strong>Step 6<\/strong>: Create Query handler to return a list of card summaries<\/p>\n<p><strong>Step 7:<\/strong> Create a Query handler for handling the SizeQuery<\/p>\n<p>&nbsp;<\/p>\n<p>At this point, the four methods will be as shown below:<\/p>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #555555; font-weight: bold;\">@EventHandler<\/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>IssuedEvent evt<span style=\"color: #333333;\">)<\/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;\">@EventHandler<\/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>RedeemedEvent evt<span style=\"color: #333333;\">)<\/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;\">@QueryHandler<\/span>\r\n<span style=\"color: #008800; font-weight: bold;\">public<\/span> List<span style=\"color: #333333;\">&lt;<\/span>CardSummary<span style=\"color: #333333;\">&gt;<\/span> <span style=\"color: #0066bb; font-weight: bold;\">handle<\/span><span style=\"color: #333333;\">(<\/span>DataQuery query<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;\">@QueryHandler<\/span>\r\n<span style=\"color: #008800; font-weight: bold;\">public<\/span> Integer <span style=\"color: #0066bb; font-weight: bold;\">handle<\/span><span style=\"color: #333333;\">(<\/span>SizeQuery query<span style=\"color: #333333;\">)<\/span> <span style=\"color: #333333;\">{<\/span>\r\n\r\n<span style=\"color: #333333;\">}<\/span>\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p><strong>Step 8:<\/strong> For the IssuedEvent, you need to create and persist a new entity. The code is shown below:<\/p>\n<pre style=\"margin: 0; line-height: 125%;\">entityManager<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">persist<\/span><span style=\"color: #333333;\">(<\/span><span style=\"color: #008800; font-weight: bold;\">new<\/span> CardSummary<span style=\"color: #333333;\">(<\/span>\r\n        evt<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">getId<\/span><span style=\"color: #333333;\">(),<\/span>\r\n        evt<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">getAmount<\/span><span style=\"color: #333333;\">(),<\/span>\r\n        evt<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">getAmount<\/span><span style=\"color: #333333;\">()<\/span>\r\n<span style=\"color: #333333;\">));<\/span>\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p><strong>Step 9:<\/strong> For the RedeemedEvent, you need to first find the CardSummary and then update it&#8217;s balance. The code is shown below<\/p>\n<pre style=\"margin: 0; line-height: 125%;\">CardSummary summary <span style=\"color: #333333;\">=<\/span> entityManager<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">find<\/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        evt<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">getId<\/span><span style=\"color: #333333;\">());<\/span>\r\nsummary<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">setRemainingBalance<\/span><span style=\"color: #333333;\">(<\/span>summary<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">getRemainingBalance<\/span><span style=\"color: #333333;\">()<\/span>\r\n<span style=\"color: #333333;\">-<\/span>evt<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">getAmount<\/span><span style=\"color: #333333;\">());<\/span>\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p><strong>Step 10:<\/strong> Configure TrackingEventProcessor. You do this by creating an empty config method. It takes EventProcessingConfiguration as parameter.<\/p>\n<p><strong>Step 11:<\/strong> Annotate this method with @Autowired annotation<\/p>\n<p>The code is given below:<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #888888;\">\/\/Configure Tracking Event<\/span>\r\n<span style=\"color: #555555; font-weight: bold;\">@Autowired<\/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;\">config<\/span><span style=\"color: #333333;\">(<\/span>EventProcessingConfiguration config<span style=\"color: #333333;\">)<\/span> <span style=\"color: #333333;\">{<\/span>\r\n    \r\n<span style=\"color: #333333;\">}<\/span>\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p><strong>Step 12:<\/strong> For the List QueryHandler, you need to create a query that returns a List&lt;CardSummary&gt; using the create() query method of the entityManager. The code is given below:<\/p>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #008800; font-weight: bold;\">return<\/span> entityManager\r\n       <span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">createQuery<\/span><span style=\"color: #333333;\">(<\/span><span style=\"background-color: #fff0f0;\">\"SELECT c FROM CardSummary c ORDER BY c.id\"<\/span><span style=\"color: #333333;\">,<\/span>\r\n               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;\">getResultList<\/span><span style=\"color: #333333;\">();<\/span>\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p><strong>Step 13:<\/strong> For the QueryHandler for SizeQuery,\u00a0 it would be similar to step 12. But this time write a query to return count..See code below<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #008800; font-weight: bold;\">return<\/span> entityManager\r\n        <span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">createQuery<\/span><span style=\"color: #333333;\">(<\/span><span style=\"background-color: #fff0f0;\">\"SELECT COUNT(c) FROM CardSummary c\"<\/span><span style=\"color: #333333;\">,<\/span>\r\n                Long<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;\">getSingleResult<\/span><span style=\"color: #333333;\">()<\/span>\r\n        <span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">intValue<\/span><span style=\"color: #333333;\">();<\/span>\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>At this point we are done with the summary projection and now we need to worry about getting the data into the grid in the GUI.<\/p>\n<p><strong>Step 14:<\/strong> Run the application. Also start the axonserver. Test to make sure everything works fine.<\/p>\n<p>&nbsp;<\/p>\n<p>Just for review, I&#8217;m putting the complete code for the SummaryProjection class below. However, I recommend you type it out by yourself. In that way you improve your skills in CQRS with AxonFramework.<\/p>\n<p>&nbsp;<\/p>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #555555; font-weight: bold;\">@Component<\/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;\">SummaryProjection<\/span> <span style=\"color: #333333;\">{<\/span>\r\n\r\n    <span style=\"color: #008800; font-weight: bold;\">private<\/span> <span style=\"color: #008800; font-weight: bold;\">final<\/span> EntityManager entityManager<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;\">SummaryProjection<\/span><span style=\"color: #333333;\">(<\/span>EntityManager entityManager<span style=\"color: #333333;\">)<\/span> <span style=\"color: #333333;\">{<\/span>\r\n\r\n        <span style=\"color: #008800; font-weight: bold;\">this<\/span><span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">entityManager<\/span> <span style=\"color: #333333;\">=<\/span> entityManager<span style=\"color: #333333;\">;<\/span>\r\n    <span style=\"color: #333333;\">}<\/span>\r\n\r\n    <span style=\"color: #555555; font-weight: bold;\">@EventHandler<\/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>IssuedEvt evt<span style=\"color: #333333;\">)<\/span> <span style=\"color: #333333;\">{<\/span>\r\n        entityManager<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">persist<\/span><span style=\"color: #333333;\">(<\/span><span style=\"color: #008800; font-weight: bold;\">new<\/span> CardSummary<span style=\"color: #333333;\">(<\/span>\r\n                evt<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">getId<\/span><span style=\"color: #333333;\">(),<\/span>\r\n                evt<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">getAmount<\/span><span style=\"color: #333333;\">(),<\/span>\r\n                evt<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">getAmount<\/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;\">@EventHandler<\/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>RedeemedEvt evt<span style=\"color: #333333;\">)<\/span> <span style=\"color: #333333;\">{<\/span>\r\n        CardSummary summary <span style=\"color: #333333;\">=<\/span> entityManager<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">find<\/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                evt<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">getId<\/span><span style=\"color: #333333;\">());<\/span>\r\n        summary<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">setRemainingBalance<\/span><span style=\"color: #333333;\">(<\/span>summary<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">getRemainingBalance<\/span><span style=\"color: #333333;\">()<\/span>\r\n        <span style=\"color: #333333;\">-<\/span> evt<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">getAmount<\/span><span style=\"color: #333333;\">());<\/span>\r\n    <span style=\"color: #333333;\">}<\/span>\r\n\r\n    <span style=\"color: #888888;\">\/\/Configuring tracking event processor<\/span>\r\n    <span style=\"color: #555555; font-weight: bold;\">@Autowired<\/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;\">config<\/span><span style=\"color: #333333;\">(<\/span>EventProcessingConfiguration config<span style=\"color: #333333;\">)<\/span> <span style=\"color: #333333;\">{<\/span>\r\n       <span style=\"color: #888888;\">\/\/ config.eventProcessor(getClass().getPackage().getName());<\/span>\r\n    <span style=\"color: #333333;\">}<\/span>\r\n\r\n    <span style=\"color: #555555; font-weight: bold;\">@QueryHandler<\/span>\r\n    <span style=\"color: #008800; font-weight: bold;\">public<\/span> List<span style=\"color: #333333;\">&lt;<\/span>CardSummary<span style=\"color: #333333;\">&gt;<\/span> <span style=\"color: #0066bb; font-weight: bold;\">handle<\/span><span style=\"color: #333333;\">(<\/span>DataQuery query<span style=\"color: #333333;\">)<\/span> <span style=\"color: #333333;\">{<\/span>\r\n        <span style=\"color: #008800; font-weight: bold;\">return<\/span> entityManager\r\n                <span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">createQuery<\/span><span style=\"color: #333333;\">(<\/span><span style=\"background-color: #fff0f0;\">\"SELECT c FROM CardSummary c ORDER BY c.id\"<\/span><span style=\"color: #333333;\">,<\/span>\r\n                        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;\">getResultList<\/span><span style=\"color: #333333;\">();<\/span>\r\n    <span style=\"color: #333333;\">}<\/span>\r\n\r\n    <span style=\"color: #555555; font-weight: bold;\">@QueryHandler<\/span>\r\n    <span style=\"color: #008800; font-weight: bold;\">public<\/span> Integer <span style=\"color: #0066bb; font-weight: bold;\">handle<\/span><span style=\"color: #333333;\">(<\/span>SizeQuery query<span style=\"color: #333333;\">)<\/span> <span style=\"color: #333333;\">{<\/span>\r\n        <span style=\"color: #008800; font-weight: bold;\">return<\/span> entityManager\r\n                <span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">createQuery<\/span><span style=\"color: #333333;\">(<\/span><span style=\"background-color: #fff0f0;\">\"SELECT COUNT(c) FROM CardSummary c\"<\/span><span style=\"color: #333333;\">,<\/span>\r\n                        Long<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;\">getSingleResult<\/span><span style=\"color: #333333;\">()<\/span>\r\n                <span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">intValue<\/span><span style=\"color: #333333;\">();<\/span>\r\n    <span style=\"color: #333333;\">}<\/span>\r\n<span style=\"color: #333333;\">}<\/span>\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>In this part we would create the summary projection class.This class would be part of the query package. This is would be a spring bean &hellip; <\/p>\n","protected":false},"author":1,"featured_media":94,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[12,27],"tags":[34,35],"class_list":["post-93","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-axon","category-axonframework","tag-summaryprojection","tag-trackingeventprocessor"],"_links":{"self":[{"href":"https:\/\/www.kindsonthegenius.com\/microservices\/wp-json\/wp\/v2\/posts\/93","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=93"}],"version-history":[{"count":3,"href":"https:\/\/www.kindsonthegenius.com\/microservices\/wp-json\/wp\/v2\/posts\/93\/revisions"}],"predecessor-version":[{"id":98,"href":"https:\/\/www.kindsonthegenius.com\/microservices\/wp-json\/wp\/v2\/posts\/93\/revisions\/98"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.kindsonthegenius.com\/microservices\/wp-json\/wp\/v2\/media\/94"}],"wp:attachment":[{"href":"https:\/\/www.kindsonthegenius.com\/microservices\/wp-json\/wp\/v2\/media?parent=93"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.kindsonthegenius.com\/microservices\/wp-json\/wp\/v2\/categories?post=93"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.kindsonthegenius.com\/microservices\/wp-json\/wp\/v2\/tags?post=93"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}