{"id":15298,"date":"2018-04-13T16:02:13","date_gmt":"2018-04-13T14:02:13","guid":{"rendered":"https:\/\/blog.trifork.com\/?p=15298"},"modified":"2018-04-13T16:02:13","modified_gmt":"2018-04-13T14:02:13","slug":"exposing-asynchronous-communication-through-a-synchronous-rest-api-with-spring-5","status":"publish","type":"post","link":"https:\/\/trifork.nl\/blog\/exposing-asynchronous-communication-through-a-synchronous-rest-api-with-spring-5\/","title":{"rendered":"Exposing asynchronous communication through a synchronous REST API with Spring 5"},"content":{"rendered":"<p>On my current project, we opted not to use REST for the communication between our services. Instead we make use of AxonIQ&#8217;s <a href=\"https:\/\/axoniq.io\/products\/axonhub.html\" target=\"_blank\" rel=\"noopener\">AxonHub<\/a>, which acts as a specialized message broker. Messages can be of three types:<\/p>\n<ul>\n<li>Command &#8211; You want to change something<\/li>\n<li>Event &#8211; You want to inform others of something that happened<\/li>\n<li>Query &#8211; You want to know something<\/li>\n<\/ul>\n<p>The communication is asynchronous and we also have to deal with eventual consistency. If we would create an order by sending a CreateOrderCommand,&nbsp;this order would result in various events which update the state of the Order. We then need to send a query, of which we also receive the&nbsp;result&nbsp;asynchronous.<\/p>\n<p>Our web and mobile frontend communicate with a microservices backend through a REST API. When the user creates an order (clicks the &#8216;buy&#8217; button), they expect a result immediately. For both frontends, an API which models this user experience closely makes the most sense. This means that we want a more synchronous API, where we send a &#8216;create order&#8217; request and immediately receive a response.<\/p>\n<p>We implemented this using a small REST facade which translates our asynchronous communication in the backend to the synchronous communication for the frontend. This is&nbsp;a good use case for Spring 5&#8217;s reactive <a href=\"https:\/\/docs.spring.io\/spring\/docs\/5.0.5.RELEASE\/spring-framework-reference\/web-reactive.html#spring-webflux\" target=\"_blank\" rel=\"noopener\">Webflux<\/a> and <a href=\"https:\/\/projectreactor.io\/\" target=\"_blank\" rel=\"noopener\">Project Reactor<\/a>. Using Project Reactor&#8217;s reactive API makes it possible to combine multiple asynchronous calls and operate on their result. Webflux handles the conversion of the reactive types (Mono, Flux) to REST responses. It optimizes the use&nbsp;of threads; by writing non-blocking code, we can reuse threads between asynchronous calls for handling other requests.<\/p>\n<p>Diagram 1 gives us an overview of this approach.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-15299\" src=\"https:\/\/trifork.nl\/articles\/wp-content\/uploads\/sites\/3\/2018\/04\/architecture-300x103.jpg\" alt=\"\" width=\"468\" height=\"161\" srcset=\"https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2018\/04\/architecture-300x103.jpg 300w, https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2018\/04\/architecture.jpg 640w\" sizes=\"auto, (max-width: 468px) 100vw, 468px\" \/><\/p>\n<p>Diagram 1<\/p>\n<p>&nbsp;<\/p>\n<p><strong>Implementation<\/strong><\/p>\n<p>Let&#8217;s have a more detailed look at the code for the create order example. Listing 1 shows the (slightly) simplified implementation of our REST controller method.<!--more--><\/p>\n<p><pre class=\"brush: java; light: true; title: ; notranslate\" title=\"\">&lt;br&gt;\n@PostMapping&lt;br&gt;\npublic Mono&amp;amp;amp;lt;ResponseEntity&amp;amp;amp;lt;OrderResponse&amp;amp;amp;gt;&amp;amp;amp;gt; createOrder(CreateOrderRequest request)&lt;br&gt;\n{&lt;br&gt;\n CreateOrderCommand command = CreateOrderCommand.fromRequest(request); \/\/1&lt;\/p&gt;\n&lt;p&gt; return this.commandGateway.send(command) \/\/2&lt;br&gt;\n  .flatMap(id -&amp;amp;amp;gt; queryGateway.send(new FindOrderSummaryQuery(id))) \/\/3&lt;br&gt;\n  .retryWhen(errors -&amp;amp;amp;gt; errors.delayElements(Duration.of(100, MILLIS)) \/\/4&lt;br&gt;\n  .take(10)).concatWith(Mono.error(new RuntimeException())).next() \/\/5&lt;br&gt;\n  .onErrorReturn(new OrderResponse(orderID, OrderStatus.CREATED)) \/\/6&lt;br&gt;\n  .map(orderResponse -&amp;amp;amp;gt; ResponseEntity.ok().body(orderResponse)); \/\/7&lt;br&gt;\n}&lt;br&gt;\n<\/pre><\/p>\n<p>Listing 1<\/p>\n<p>We first create a command out of the REST request (line 1). A command is a message with the specific intent to change something in our domain. In this specific case, we want to create a new order.<\/p>\n<p>After creating the command, the two asynchronous calls we make are:<\/p>\n<p><pre class=\"brush: java; light: true; title: ; notranslate\" title=\"\">&lt;br&gt;\nMono&amp;amp;amp;lt;String&amp;amp;amp;gt; id = this.commandGateway.send(command);&lt;br&gt;\n<\/pre><\/p>\n<p>and:<\/p>\n<p><pre class=\"brush: java; light: true; title: ; notranslate\" title=\"\">&lt;br&gt;\nMono&amp;amp;amp;lt;OrderResponse&amp;amp;amp;gt; orderResponse = queryGateway.send(new FindOrderSummaryQuery(id));&lt;br&gt;\n<\/pre><\/p>\n<p>Both calls return a single value by using a Mono. A Mono is a reactive type, comparable to the Java&#8217;s CompletableFuture. It has zero or one element and can represent an error. As with all reactive types, the value (or error) is delivered over time.<\/p>\n<p>The second call takes the result of the first call as its input. We need the returned id of the command to query for the order. We use the flatMap operator to achieve this (line 3). The flatMap takes the asynchronous result of call 1 and passes this as a parameter to the lambda of call 2. The callback version can be seen in Listing 2: notice the nested lambda, which makes the code complex and less readable.<\/p>\n<p><pre class=\"brush: java; light: true; title: ; notranslate\" title=\"\">&lt;br&gt;\nthis.commandGateway.send(command, id -&amp;amp;amp;gt; {&lt;br&gt;\n  queryGateway.send(new FindOrderSummaryQuery(id));&lt;br&gt;\n});&lt;br&gt;\n<\/pre><\/p>\n<p>Listing 2<\/p>\n<p>There is a delay between sending the command and being able to query the result. When the created order cannot be found (e.g. it isn&#8217;t create yet or something has gone wrong), an exception is thrown. In this chain, this is represented as a Mono.error(throwable). We use the retryWhen method to retry the query (line 4). We do this 10 times with a delay of 100 ms. When we still don&#8217;t get a result, we throw an error (line 5). We don&#8217;t expose the error to the client, but pass an OrderResponse with the id and status CREATED (line 6). The client can then query the status of the order later by using this id. This is a form of graceful degradation.<\/p>\n<p>Finally we map the order response from the query to a response entity which can be returned by Spring. Spring actually subscribes to this whole chain and sends out the REST response for us.<\/p>\n<p><strong>Conclusion<\/strong><\/p>\n<p>Spring 5 and Project Reactor allow us to handle asynchronous communication with concise and readable code. We can do retries, error handling and the combination of multiple asynchronous calls in just a few lines.<br \/>\nThe integration of Webflux with Project Reactor allows the use of reactive paradigms in a REST controller. Webflux uses an asynchronous approach. While we wait for a backend query to return, we don&#8217;t block the main thread. this allows it to be used for other requests.<br \/>\nOur specific use case is a good example of one of the applications of Spring 5 Webflux and Project Reactor.<\/p>\n\n\n<figure class=\"wp-block-image\"><a href=\"https:\/\/bit.ly\/3BAo305\" target=\"_blank\" rel=\"noreferrer noopener\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"256\" src=\"https:\/\/trifork.nl\/articles\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-1024x256.png\" alt=\"\" class=\"wp-image-20303\" srcset=\"https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-1024x256.png 1024w, https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-300x75.png 300w, https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-768x192.png 768w, https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-1536x384.png 1536w, https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-2048x512.png 2048w, https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-1920x480.png 1920w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n","protected":false},"excerpt":{"rendered":"<p>On my current project, we opted not to use REST for the communication between our services. Instead we make use of AxonIQ&#8217;s AxonHub, which acts as a specialized message broker. Messages can be of three types: Command &#8211; You want to change something Event &#8211; You want to inform others of something that happened Query [&hellip;]<\/p>\n","protected":false},"author":43,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"content-type":"","footnotes":""},"categories":[113,81,10,94],"tags":[80,458,459,460,70,461],"class_list":["post-15298","post","type-post","status-publish","format-standard","hentry","category-axon","category-axon-framework","category-development","category-spring","tag-axon-framework","tag-axonhub","tag-reactive","tag-reactor","tag-spring","tag-webflux"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v24.4 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Exposing asynchronous communication through a synchronous REST API with Spring 5 - Trifork Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/trifork.nl\/blog\/exposing-asynchronous-communication-through-a-synchronous-rest-api-with-spring-5\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Exposing asynchronous communication through a synchronous REST API with Spring 5 - Trifork Blog\" \/>\n<meta property=\"og:description\" content=\"On my current project, we opted not to use REST for the communication between our services. Instead we make use of AxonIQ&#8217;s AxonHub, which acts as a specialized message broker. Messages can be of three types: Command &#8211; You want to change something Event &#8211; You want to inform others of something that happened Query [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/trifork.nl\/blog\/exposing-asynchronous-communication-through-a-synchronous-rest-api-with-spring-5\/\" \/>\n<meta property=\"og:site_name\" content=\"Trifork Blog\" \/>\n<meta property=\"article:published_time\" content=\"2018-04-13T14:02:13+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/trifork.nl\/articles\/wp-content\/uploads\/sites\/3\/2018\/04\/architecture-300x103.jpg\" \/>\n<meta name=\"author\" content=\"Erwin de Gier\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Erwin de Gier\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"5 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/trifork.nl\/blog\/exposing-asynchronous-communication-through-a-synchronous-rest-api-with-spring-5\/\",\"url\":\"https:\/\/trifork.nl\/blog\/exposing-asynchronous-communication-through-a-synchronous-rest-api-with-spring-5\/\",\"name\":\"Exposing asynchronous communication through a synchronous REST API with Spring 5 - Trifork Blog\",\"isPartOf\":{\"@id\":\"https:\/\/trifork.nl\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/trifork.nl\/blog\/exposing-asynchronous-communication-through-a-synchronous-rest-api-with-spring-5\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/trifork.nl\/blog\/exposing-asynchronous-communication-through-a-synchronous-rest-api-with-spring-5\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/trifork.nl\/articles\/wp-content\/uploads\/sites\/3\/2018\/04\/architecture-300x103.jpg\",\"datePublished\":\"2018-04-13T14:02:13+00:00\",\"author\":{\"@id\":\"https:\/\/trifork.nl\/blog\/#\/schema\/person\/b1c52cf70084428baf0f1711c37b3fc2\"},\"breadcrumb\":{\"@id\":\"https:\/\/trifork.nl\/blog\/exposing-asynchronous-communication-through-a-synchronous-rest-api-with-spring-5\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/trifork.nl\/blog\/exposing-asynchronous-communication-through-a-synchronous-rest-api-with-spring-5\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/trifork.nl\/blog\/exposing-asynchronous-communication-through-a-synchronous-rest-api-with-spring-5\/#primaryimage\",\"url\":\"https:\/\/trifork.nl\/articles\/wp-content\/uploads\/sites\/3\/2018\/04\/architecture-300x103.jpg\",\"contentUrl\":\"https:\/\/trifork.nl\/articles\/wp-content\/uploads\/sites\/3\/2018\/04\/architecture-300x103.jpg\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/trifork.nl\/blog\/exposing-asynchronous-communication-through-a-synchronous-rest-api-with-spring-5\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/trifork.nl\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Exposing asynchronous communication through a synchronous REST API with Spring 5\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/trifork.nl\/blog\/#website\",\"url\":\"https:\/\/trifork.nl\/blog\/\",\"name\":\"Trifork Blog\",\"description\":\"Keep updated on the technical solutions Trifork is working on!\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/trifork.nl\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/trifork.nl\/blog\/#\/schema\/person\/b1c52cf70084428baf0f1711c37b3fc2\",\"name\":\"Erwin de Gier\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/trifork.nl\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/7f8993fecf1561ed8bb0264270e42e73?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/7f8993fecf1561ed8bb0264270e42e73?s=96&d=mm&r=g\",\"caption\":\"Erwin de Gier\"},\"url\":\"https:\/\/trifork.nl\/blog\/author\/erwindeg\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Exposing asynchronous communication through a synchronous REST API with Spring 5 - Trifork Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/trifork.nl\/blog\/exposing-asynchronous-communication-through-a-synchronous-rest-api-with-spring-5\/","og_locale":"en_US","og_type":"article","og_title":"Exposing asynchronous communication through a synchronous REST API with Spring 5 - Trifork Blog","og_description":"On my current project, we opted not to use REST for the communication between our services. Instead we make use of AxonIQ&#8217;s AxonHub, which acts as a specialized message broker. Messages can be of three types: Command &#8211; You want to change something Event &#8211; You want to inform others of something that happened Query [&hellip;]","og_url":"https:\/\/trifork.nl\/blog\/exposing-asynchronous-communication-through-a-synchronous-rest-api-with-spring-5\/","og_site_name":"Trifork Blog","article_published_time":"2018-04-13T14:02:13+00:00","og_image":[{"url":"https:\/\/trifork.nl\/articles\/wp-content\/uploads\/sites\/3\/2018\/04\/architecture-300x103.jpg","type":"","width":"","height":""}],"author":"Erwin de Gier","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Erwin de Gier","Est. reading time":"5 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/trifork.nl\/blog\/exposing-asynchronous-communication-through-a-synchronous-rest-api-with-spring-5\/","url":"https:\/\/trifork.nl\/blog\/exposing-asynchronous-communication-through-a-synchronous-rest-api-with-spring-5\/","name":"Exposing asynchronous communication through a synchronous REST API with Spring 5 - Trifork Blog","isPartOf":{"@id":"https:\/\/trifork.nl\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/trifork.nl\/blog\/exposing-asynchronous-communication-through-a-synchronous-rest-api-with-spring-5\/#primaryimage"},"image":{"@id":"https:\/\/trifork.nl\/blog\/exposing-asynchronous-communication-through-a-synchronous-rest-api-with-spring-5\/#primaryimage"},"thumbnailUrl":"https:\/\/trifork.nl\/articles\/wp-content\/uploads\/sites\/3\/2018\/04\/architecture-300x103.jpg","datePublished":"2018-04-13T14:02:13+00:00","author":{"@id":"https:\/\/trifork.nl\/blog\/#\/schema\/person\/b1c52cf70084428baf0f1711c37b3fc2"},"breadcrumb":{"@id":"https:\/\/trifork.nl\/blog\/exposing-asynchronous-communication-through-a-synchronous-rest-api-with-spring-5\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/trifork.nl\/blog\/exposing-asynchronous-communication-through-a-synchronous-rest-api-with-spring-5\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/trifork.nl\/blog\/exposing-asynchronous-communication-through-a-synchronous-rest-api-with-spring-5\/#primaryimage","url":"https:\/\/trifork.nl\/articles\/wp-content\/uploads\/sites\/3\/2018\/04\/architecture-300x103.jpg","contentUrl":"https:\/\/trifork.nl\/articles\/wp-content\/uploads\/sites\/3\/2018\/04\/architecture-300x103.jpg"},{"@type":"BreadcrumbList","@id":"https:\/\/trifork.nl\/blog\/exposing-asynchronous-communication-through-a-synchronous-rest-api-with-spring-5\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/trifork.nl\/blog\/"},{"@type":"ListItem","position":2,"name":"Exposing asynchronous communication through a synchronous REST API with Spring 5"}]},{"@type":"WebSite","@id":"https:\/\/trifork.nl\/blog\/#website","url":"https:\/\/trifork.nl\/blog\/","name":"Trifork Blog","description":"Keep updated on the technical solutions Trifork is working on!","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/trifork.nl\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/trifork.nl\/blog\/#\/schema\/person\/b1c52cf70084428baf0f1711c37b3fc2","name":"Erwin de Gier","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/trifork.nl\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/7f8993fecf1561ed8bb0264270e42e73?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/7f8993fecf1561ed8bb0264270e42e73?s=96&d=mm&r=g","caption":"Erwin de Gier"},"url":"https:\/\/trifork.nl\/blog\/author\/erwindeg\/"}]}},"_links":{"self":[{"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/posts\/15298","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/users\/43"}],"replies":[{"embeddable":true,"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/comments?post=15298"}],"version-history":[{"count":0,"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/posts\/15298\/revisions"}],"wp:attachment":[{"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/media?parent=15298"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/categories?post=15298"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/tags?post=15298"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}