{"data":{"allMarkdownRemark":{"edges":[{"node":{"id":"cb45e6dc-ba61-576d-adc2-ba609b0e722a","frontmatter":{"category":"Engineering","title":"Go 1.23: the new Pattern property in http.Request","date":"2024-11-26","summary":"A short review of the new Pattern property in net/http.Request","thumbnail":null,"authorName":"Andrei Gusev","authorDescription":"Senior Software Engineer at AUTO1 Group","authorAvatar":{"relativePath":"pages/go-123-the-new-pattern-property-in-http-request/avatar_Andrei.jpg","childImageSharp":{"resolutions":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAUABQDASIAAhEBAxEB/8QAGAABAQEBAQAAAAAAAAAAAAAAAAUBBgT/xAAWAQEBAQAAAAAAAAAAAAAAAAAAAQL/2gAMAwEAAhADEAAAAaeTsi2mDmfWV0wzf//EAB0QAAICAQUAAAAAAAAAAAAAAAECAAMEEBESEyH/2gAIAQEAAQUCtYiUvyE71ZkuQNuzaYvuQTP/xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAEDAQE/AR//xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAECAQE/AR//xAAcEAACAgIDAAAAAAAAAAAAAAABEQACEBIhMTL/2gAIAQEABj8C4KnprGnRhqdnHWpWKPH/xAAdEAACAgMAAwAAAAAAAAAAAAABEQAhEEFRMXGB/9oACAEBAAE/IRoFjyQHGILdksEYAYLXeSuANz4mvAhI736hHP/aAAwDAQACAAMAAAAQNBc+/8QAFhEAAwAAAAAAAAAAAAAAAAAAABAR/9oACAEDAQE/ECv/xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAECAQE/EB//xAAcEAEBAAMBAAMAAAAAAAAAAAABEQAhUTEQYaH/2gAIAQEAAT8Q0H5agDhjJzCu2+nxvKetJ9/fd9x0k6GIzjdTPf69KX9xcAAKlBR2wEDDmf/Z","width":50,"height":50,"src":"/static/479e481648d69b84a342bd2575a225d4/d2d31/avatar_Andrei.jpg","srcSet":"/static/479e481648d69b84a342bd2575a225d4/d2d31/avatar_Andrei.jpg 1x,\n/static/479e481648d69b84a342bd2575a225d4/0b804/avatar_Andrei.jpg 1.5x,\n/static/479e481648d69b84a342bd2575a225d4/753c3/avatar_Andrei.jpg 2x,\n/static/479e481648d69b84a342bd2575a225d4/31ca8/avatar_Andrei.jpg 3x"}}},"headerImage":null},"html":"<h1>Go 1.23: the new Pattern property in http.Request</h1>\n<p>In Go 1.23, a new <code class=\"language-text\">Pattern</code> property in <code class=\"language-text\">net/http.Request</code> was added.\nIt contains the route pattern used to handle the request. This improvement may have gone unnoticed by many, but it can\nsimplify request processing and improve performance in cases where we need to obtain the matched routing pattern\nfor the current request. Let’s see how we can use this feature.</p>\n<p>At AUTO1, we have more than 200 microservices, some of which are written in Go and include an HTTP server.\nIt is critically important for us to collect metrics from these services in order to quickly respond to incidents,\nmake data-driven decisions, and optimize system performance.\nFor example, we collect <code class=\"language-text\">http_requests_total</code> metric:</p>\n<div class=\"gatsby-highlight\" data-language=\"go\"><pre class=\"language-go\"><code class=\"language-go\">requestsTotal <span class=\"token operator\">=</span> promauto<span class=\"token punctuation\">.</span><span class=\"token function\">NewCounterVec</span><span class=\"token punctuation\">(</span>prometheus<span class=\"token punctuation\">.</span>CounterOpts<span class=\"token punctuation\">{</span>\n\t\tName<span class=\"token punctuation\">:</span> <span class=\"token string\">\"http_requests_total\"</span><span class=\"token punctuation\">,</span>\n\t\tHelp<span class=\"token punctuation\">:</span> <span class=\"token string\">\"total request count\"</span><span class=\"token punctuation\">,</span>\n\t<span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token builtin\">string</span><span class=\"token punctuation\">{</span><span class=\"token string\">\"path\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"method\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"code\"</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>Obviously, for the <code class=\"language-text\">path</code> label, we should store the path template, not the specific value, for example, <code class=\"language-text\">/test/{id}</code> instead of <code class=\"language-text\">/test/123</code>.\nOtherwise, we risk a cardinality explosion, which can significantly increase the amount of stored data. You can read how to choose labels properly in <a href=\"https://prometheus.io/docs/practices/naming/#labels\">\"Prometheus best practices\"</a>.</p>\n<h2>Before v1.23</h2>\n<p>Previously, to extract the route pattern, we had to pass the multiplexer to a middleware function:</p>\n<div class=\"gatsby-highlight\" data-language=\"go\"><pre class=\"language-go\"><code class=\"language-go\"><span class=\"token keyword\">func</span> <span class=\"token function\">metricsMiddleware</span><span class=\"token punctuation\">(</span>next http<span class=\"token punctuation\">.</span>Handler<span class=\"token punctuation\">,</span> mux <span class=\"token operator\">*</span>http<span class=\"token punctuation\">.</span>ServeMux<span class=\"token punctuation\">)</span> http<span class=\"token punctuation\">.</span>Handler <span class=\"token punctuation\">{</span>\n\t<span class=\"token keyword\">return</span> http<span class=\"token punctuation\">.</span><span class=\"token function\">HandlerFunc</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">func</span><span class=\"token punctuation\">(</span>w http<span class=\"token punctuation\">.</span>ResponseWriter<span class=\"token punctuation\">,</span> r <span class=\"token operator\">*</span>http<span class=\"token punctuation\">.</span>Request<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n\t\t<span class=\"token boolean\">_</span><span class=\"token punctuation\">,</span> pattern <span class=\"token operator\">:=</span> mux<span class=\"token punctuation\">.</span><span class=\"token function\">Handler</span><span class=\"token punctuation\">(</span>r<span class=\"token punctuation\">)</span>\n\t\t\n\t\t<span class=\"token operator\">...</span>\n\t\trequestsTotal<span class=\"token punctuation\">.</span><span class=\"token function\">WithLabelValues</span><span class=\"token punctuation\">(</span>pattern<span class=\"token punctuation\">,</span> method<span class=\"token punctuation\">,</span> statusCode<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">Inc</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n\t<span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>In this approach, we matched the request to the route a second time, and that negatively affected performance.</p>\n<h2>Since 1.23</h2>\n<p>Starting with Go 1.23, we can get the route pattern directly from the request, without passing the multiplexer to the middleware:</p>\n<div class=\"gatsby-highlight\" data-language=\"go\"><pre class=\"language-go\"><code class=\"language-go\"><span class=\"token keyword\">func</span> <span class=\"token function\">middleware</span><span class=\"token punctuation\">(</span>f http<span class=\"token punctuation\">.</span>Handler<span class=\"token punctuation\">)</span> http<span class=\"token punctuation\">.</span>Handler <span class=\"token punctuation\">{</span>\n\t<span class=\"token keyword\">return</span> http<span class=\"token punctuation\">.</span><span class=\"token function\">HandlerFunc</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">func</span><span class=\"token punctuation\">(</span>w http<span class=\"token punctuation\">.</span>ResponseWriter<span class=\"token punctuation\">,</span> r <span class=\"token operator\">*</span>http<span class=\"token punctuation\">.</span>Request<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n\t\tpattern <span class=\"token operator\">:=</span> r<span class=\"token punctuation\">.</span>Pattern\n\t\t\n\t\t<span class=\"token operator\">...</span>\n\t\trequestsTotal<span class=\"token punctuation\">.</span><span class=\"token function\">WithLabelValues</span><span class=\"token punctuation\">(</span>pattern<span class=\"token punctuation\">,</span> method<span class=\"token punctuation\">,</span> statusCode<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">Inc</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n\t<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>This significantly simplifies the middleware, making the code cleaner and more readable. We are no longer dependent on <code class=\"language-text\">ServeMux</code> and no longer need to re-match the request.</p>\n<h2>Limitations</h2>\n<p>It is important to remember that <code class=\"language-text\">Request.Pattern</code> is only available after the request has been matched to a route. For example:</p>\n<div class=\"gatsby-highlight\" data-language=\"go\"><pre class=\"language-go\"><code class=\"language-go\"><span class=\"token keyword\">func</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n\tmux <span class=\"token operator\">:=</span> http<span class=\"token punctuation\">.</span><span class=\"token function\">NewServeMux</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n\tmux<span class=\"token punctuation\">.</span><span class=\"token function\">Handle</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"/test/{id}\"</span><span class=\"token punctuation\">,</span> <span class=\"token function\">routeMiddleware</span><span class=\"token punctuation\">(</span><span class=\"token function\">handler</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n\n\tsrv <span class=\"token operator\">:=</span> http<span class=\"token punctuation\">.</span>Server<span class=\"token punctuation\">{</span>\n\t\tAddr<span class=\"token punctuation\">:</span>    <span class=\"token string\">\":8080\"</span><span class=\"token punctuation\">,</span>\n\t\tHandler<span class=\"token punctuation\">:</span> <span class=\"token function\">globalMiddleware</span><span class=\"token punctuation\">(</span>mux<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n\t<span class=\"token punctuation\">}</span>\n\n\t<span class=\"token keyword\">if</span> err <span class=\"token operator\">:=</span> srv<span class=\"token punctuation\">.</span><span class=\"token function\">ListenAndServe</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token operator\">!</span>errors<span class=\"token punctuation\">.</span><span class=\"token function\">Is</span><span class=\"token punctuation\">(</span>err<span class=\"token punctuation\">,</span> http<span class=\"token punctuation\">.</span>ErrServerClosed<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n\t\tlog<span class=\"token punctuation\">.</span><span class=\"token function\">Fatalf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"server error: %s\"</span><span class=\"token punctuation\">,</span> err<span class=\"token punctuation\">)</span>\n\t<span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">func</span> <span class=\"token function\">routeMiddleware</span><span class=\"token punctuation\">(</span>h http<span class=\"token punctuation\">.</span>Handler<span class=\"token punctuation\">)</span> http<span class=\"token punctuation\">.</span>Handler <span class=\"token punctuation\">{</span>\n\t<span class=\"token keyword\">return</span> http<span class=\"token punctuation\">.</span><span class=\"token function\">HandlerFunc</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">func</span><span class=\"token punctuation\">(</span>w http<span class=\"token punctuation\">.</span>ResponseWriter<span class=\"token punctuation\">,</span> r <span class=\"token operator\">*</span>http<span class=\"token punctuation\">.</span>Request<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n\t\tlog<span class=\"token punctuation\">.</span><span class=\"token function\">Printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"ROUTE pattern: %s\"</span><span class=\"token punctuation\">,</span> r<span class=\"token punctuation\">.</span>Pattern<span class=\"token punctuation\">)</span>\n\t\th<span class=\"token punctuation\">.</span><span class=\"token function\">ServeHTTP</span><span class=\"token punctuation\">(</span>w<span class=\"token punctuation\">,</span> r<span class=\"token punctuation\">)</span>\n\t<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">func</span> <span class=\"token function\">globalMiddleware</span><span class=\"token punctuation\">(</span>h http<span class=\"token punctuation\">.</span>Handler<span class=\"token punctuation\">)</span> http<span class=\"token punctuation\">.</span>Handler <span class=\"token punctuation\">{</span>\n\t<span class=\"token keyword\">return</span> http<span class=\"token punctuation\">.</span><span class=\"token function\">HandlerFunc</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">func</span><span class=\"token punctuation\">(</span>w http<span class=\"token punctuation\">.</span>ResponseWriter<span class=\"token punctuation\">,</span> r <span class=\"token operator\">*</span>http<span class=\"token punctuation\">.</span>Request<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n\t\tlog<span class=\"token punctuation\">.</span><span class=\"token function\">Printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"GLOBAL pattern: %s\"</span><span class=\"token punctuation\">,</span> r<span class=\"token punctuation\">.</span>Pattern<span class=\"token punctuation\">)</span>\n\t\th<span class=\"token punctuation\">.</span><span class=\"token function\">ServeHTTP</span><span class=\"token punctuation\">(</span>w<span class=\"token punctuation\">,</span> r<span class=\"token punctuation\">)</span>\n\t\tlog<span class=\"token punctuation\">.</span><span class=\"token function\">Printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"GLOBAL pattern after: %s\"</span><span class=\"token punctuation\">,</span> r<span class=\"token punctuation\">.</span>Pattern<span class=\"token punctuation\">)</span>\n\t<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>If we send a request <code class=\"language-text\">GET http://localhost:8080/test/123</code>, in logs we will see:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">2024/11/10 13:20:37 GLOBAL pattern: \n2024/11/10 13:20:37 ROUTE pattern: /test/{id}\n2024/11/10 13:20:37 GLOBAL pattern after: /test/{id}</code></pre></div>\n<p>This is the expected behavior. The multiplexer implements the <code class=\"language-text\">http.Handler</code> interface, and inside the <code class=\"language-text\">ServeHTTP</code> method, it searches for the handler that matches the request. Starting from Go 1.23, it fills the <code class=\"language-text\">Pattern</code> property of the request with the matching route pattern:</p>\n<div class=\"gatsby-highlight\" data-language=\"go\"><pre class=\"language-go\"><code class=\"language-go\"><span class=\"token comment\">// net/http/server.go</span>\n<span class=\"token keyword\">func</span> <span class=\"token punctuation\">(</span>mux <span class=\"token operator\">*</span>ServeMux<span class=\"token punctuation\">)</span> <span class=\"token function\">ServeHTTP</span><span class=\"token punctuation\">(</span>w ResponseWriter<span class=\"token punctuation\">,</span> r <span class=\"token operator\">*</span>Request<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n\t<span class=\"token operator\">...</span>\n\t<span class=\"token keyword\">var</span> h Handler\n\t<span class=\"token keyword\">if</span> use121 <span class=\"token punctuation\">{</span>\n\t\th<span class=\"token punctuation\">,</span> <span class=\"token boolean\">_</span> <span class=\"token operator\">=</span> mux<span class=\"token punctuation\">.</span>mux121<span class=\"token punctuation\">.</span><span class=\"token function\">findHandler</span><span class=\"token punctuation\">(</span>r<span class=\"token punctuation\">)</span>\n\t<span class=\"token punctuation\">}</span> <span class=\"token keyword\">else</span> <span class=\"token punctuation\">{</span>\n\t\th<span class=\"token punctuation\">,</span> r<span class=\"token punctuation\">.</span>Pattern<span class=\"token punctuation\">,</span> r<span class=\"token punctuation\">.</span>pat<span class=\"token punctuation\">,</span> r<span class=\"token punctuation\">.</span>matches <span class=\"token operator\">=</span> mux<span class=\"token punctuation\">.</span><span class=\"token function\">findHandler</span><span class=\"token punctuation\">(</span>r<span class=\"token punctuation\">)</span>\n\t<span class=\"token punctuation\">}</span>\n\th<span class=\"token punctuation\">.</span><span class=\"token function\">ServeHTTP</span><span class=\"token punctuation\">(</span>w<span class=\"token punctuation\">,</span> r<span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Thus, the <code class=\"language-text\">r.Pattern</code> is filled only after the <code class=\"language-text\">ServeHTTP</code> method of the multiplexer has been called, and the logs confirm this behavior.</p>\n<h2>Conclusion</h2>\n<p>In the last two Go releases, the <code class=\"language-text\">net/http</code> package has received significant improvements that reduced the gap with third-party packages, like <code class=\"language-text\">gorilla/mux</code>. Now, <code class=\"language-text\">net/http.ServeMux</code> supports HTTP methods and wildcards in routing patterns, bringing its functionality closer to what third-party packages previously provided.</p>\n<p>Additionally, the introduction of the <code class=\"language-text\">net/http.Request.Pattern</code> property in Go 1.23 has simplified middleware development by allowing us to access the route pattern without needing to re-match the request, improving performance and reducing code complexity.</p>\n<p>With each of these improvements, there are fewer reasons to choose third-party routers. While the choice between the standard package and third-party routers used to be more obvious, today I would recommend starting with the standard <code class=\"language-text\">net/http</code> package.</p>","fields":{"slug":"/go-123-the-new-pattern-property-in-http-request/","tags":["auto1","go","network_programming"]}}},{"node":{"id":"9720ef25-7d81-5307-9ea5-229d55ec766f","frontmatter":{"category":"Engineering","title":"Android JetPack Compose + Paging 3","date":"2024-03-29","summary":"A short trip around the AUTO1 Application Cockpit data model","thumbnail":null,"authorName":"Sergey Bakhtiarov","authorDescription":"Senior Android Developer at AUTO1 Group","authorAvatar":{"relativePath":"pages/android-compose-pagination/avatar_Sergey.jpeg","childImageSharp":{"resolutions":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAbABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAIEBgX/xAAWAQEBAQAAAAAAAAAAAAAAAAABAgD/2gAMAwEAAhADEAAAAessVEW4wzlnkZ2tJg3/xAAdEAACAQQDAAAAAAAAAAAAAAABAgMABCExECIz/9oACAEBAAEFAsAAq1EVIe0OSdtKzEXEgbfMHh//xAAXEQADAQAAAAAAAAAAAAAAAAAQERIh/9oACAEDAQE/AZxhj//EABURAQEAAAAAAAAAAAAAAAAAABEg/9oACAECAQE/AWP/xAAdEAACAgEFAAAAAAAAAAAAAAABEQAQAiAhImFx/9oACAEBAAY/AtzOJt9U3GCtGHk//8QAGxABAAIDAQEAAAAAAAAAAAAAAQARECExQVH/2gAIAQEAAT8hd4gIS0NTZPIjUV1DC40rgQLqvDjL0fpeUqrP/9oADAMBAAIAAwAAABD/APKz/8QAFREBAQAAAAAAAAAAAAAAAAAAEBH/2gAIAQMBAT8QBR//xAAXEQEBAQEAAAAAAAAAAAAAAAABEBEh/9oACAECAQE/EOnIBP/EAB0QAQEBAAMAAwEAAAAAAAAAAAERACExQVFhcdH/2gAIAQEAAT8QaCJVXrPnop5ivjMtoBBeM7oBFG2x3Zjtir0D+518AlC+E9yQMgcPsxpw/mVwqOXf/9k=","width":50,"height":50,"src":"/static/27c2b15cdd840519c853a653e9b049f0/d2d31/avatar_Sergey.jpeg","srcSet":"/static/27c2b15cdd840519c853a653e9b049f0/d2d31/avatar_Sergey.jpeg 1x,\n/static/27c2b15cdd840519c853a653e9b049f0/0b804/avatar_Sergey.jpeg 1.5x,\n/static/27c2b15cdd840519c853a653e9b049f0/753c3/avatar_Sergey.jpeg 2x,\n/static/27c2b15cdd840519c853a653e9b049f0/31ca8/avatar_Sergey.jpeg 3x"}}},"headerImage":null},"html":"<h1>Android JetPack Compose + Paging 3</h1>\n<h2>About pagination</h2>\n<p>Paginated APIs, often encountered when dealing with servers and databases, break down large datasets into manageable chunks or pages. This methodology not only optimizes resource usage but also enhances the overall user experience by delivering content progressively. However, integrating and managing paginated data in a mobile app can be a challenge, from maintaining loading states to ensuring a seamless transition between pages and supporting content filtering.</p>\n<p>In this guide I will show you how to work with paginated APIs in Android with Jetpack Compose and Paging 3 libraries. </p>\n<p><img src=\"/static/paging_demo-a325402259bf9864dced311c9eafa7c8.gif\" alt=\"Paging UI\"></p>\n<h2>Basics, architecture overview</h2>\n<p><br></br>\n<img src=\"https://developer.android.com/static/topic/libraries/architecture/images/paging3-library-architecture.svg\" alt=\"Paging library overview\"></p>\n<p>The key components of the Paging 3 architecture include</p>\n<h3>PagingSource</h3>\n<ul>\n<li>The foundational element responsible for loading data in chunks.</li>\n<li>Developers implement a custom PagingSource, defining how to retrieve data from a particular source or use implementation provided by a library supporting Paging 3. (Room can generate a paging source for your data query)</li>\n</ul>\n<h3>Remote Mediator</h3>\n<ul>\n<li>An integral part of the Paging 3 architecture, RemoteMediator manages the coordination between remote data sources, typically backed by a network service, and the local database.</li>\n<li>Responsible for loading pages of data from the network and storing them in the local database, ensuring efficient and reliable pagination.</li>\n</ul>\n<h3>Paging Data</h3>\n<ul>\n<li>Represents the paginated data stream emitted by the PagingSource.</li>\n<li>A Flow of PagingData is observed in the UI layer, enabling dynamic updates as new data is loaded or existing data is invalidated.</li>\n</ul>\n<h3>Pager</h3>\n<ul>\n<li>Coordinates the interaction between the PagingSource and the UI layer.</li>\n<li>Configures the pagination parameters, such as page size, prefetch distance, and initial load size, providing fine-grained control over the loading behavior.</li>\n</ul>\n<h2>Data layer</h2>\n<p>We start with the data layer and define a Retrofit API for fetching movies from network service.</p>\n<div class=\"gatsby-highlight\" data-language=\"kotlin\"><pre class=\"language-kotlin\"><code class=\"language-kotlin\"><span class=\"token keyword\">interface</span> MoviesApi <span class=\"token punctuation\">{</span>\n  <span class=\"token annotation builtin\">@GET</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"/3/discover/movie?language=en-US&amp;sort_by=popularity.desc\"</span><span class=\"token punctuation\">)</span>\n  <span class=\"token keyword\">suspend</span> <span class=\"token keyword\">fun</span> <span class=\"token function\">discover</span><span class=\"token punctuation\">(</span>\n    <span class=\"token annotation builtin\">@Query</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"api_key\"</span><span class=\"token punctuation\">)</span> api_key<span class=\"token operator\">:</span> String<span class=\"token punctuation\">,</span>\n    <span class=\"token annotation builtin\">@Query</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"page\"</span><span class=\"token punctuation\">)</span> page<span class=\"token operator\">:</span> Int<span class=\"token punctuation\">,</span>\n    <span class=\"token annotation builtin\">@Query</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"with_genres\"</span><span class=\"token punctuation\">)</span> genres<span class=\"token operator\">:</span> String<span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">)</span><span class=\"token operator\">:</span> Response<span class=\"token operator\">&lt;</span>MoviesNetworkResponse<span class=\"token operator\">></span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Next, we will leverage the Room library, which is compatible with Paging 3, to create a local paging source. </p>\n<div class=\"gatsby-highlight\" data-language=\"kotlin\"><pre class=\"language-kotlin\"><code class=\"language-kotlin\"><span class=\"token annotation builtin\">@Dao</span>\n<span class=\"token keyword\">interface</span> MoviesDao <span class=\"token punctuation\">{</span>\n  <span class=\"token annotation builtin\">@Query</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"SELECT * FROM movies ORDER BY id ASC\"</span><span class=\"token punctuation\">)</span>\n  <span class=\"token keyword\">fun</span> <span class=\"token function\">getMovies</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token operator\">:</span> DataSource<span class=\"token punctuation\">.</span>Factory<span class=\"token operator\">&lt;</span>Int<span class=\"token punctuation\">,</span> MovieDbEntity<span class=\"token operator\">></span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>It's important to highlight that we utilize <code class=\"language-text\">DataSource.Factory</code> as the return type instead of <code class=\"language-text\">PagingSource</code>. This choice is made specifically because <code class=\"language-text\">DataSource.Factory</code> offers the <code class=\"language-text\">map()</code> method, enabling us to map <code class=\"language-text\">MovieDbEntity</code> instances into domain layer models.</p>\n<p>Now we need to put together local and remote data sources in Remote mediator.</p>\n<ol>\n<li>Determine which page to load depending on the loadType and next page value. Next page number (<code class=\"language-text\">getRemoteKey().nextPage</code>) is stored in the database after each successful network request.</li>\n</ol>\n<div class=\"gatsby-highlight\" data-language=\"kotlin\"><pre class=\"language-kotlin\"><code class=\"language-kotlin\"><span class=\"token keyword\">val</span> page <span class=\"token operator\">=</span> <span class=\"token keyword\">when</span> <span class=\"token punctuation\">(</span>loadType<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        LoadType<span class=\"token punctuation\">.</span>REFRESH <span class=\"token operator\">-></span> <span class=\"token number\">1</span>\n        LoadType<span class=\"token punctuation\">.</span>PREPEND <span class=\"token operator\">-></span> <span class=\"token keyword\">null</span>\n        LoadType<span class=\"token punctuation\">.</span>APPEND <span class=\"token operator\">-></span> repository<span class=\"token punctuation\">.</span><span class=\"token function\">getRemoteKey</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token operator\">?</span><span class=\"token punctuation\">.</span>nextPage\n      <span class=\"token punctuation\">}</span> <span class=\"token operator\">?:</span> <span class=\"token keyword\">return</span> <span class=\"token function\">Success</span><span class=\"token punctuation\">(</span>endOfPaginationReached <span class=\"token operator\">=</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>For bidirectional pagination support, provide the preceding page number for the PREPEND load type. The REFRESH load type is employed when content is refreshed, initiating loading from the initial page.</p>\n<ol start=\"2\">\n<li>Request data from network</li>\n</ol>\n<p>Call our network data source method to fetch a page of data from the server.</p>\n<div class=\"gatsby-highlight\" data-language=\"kotlin\"><pre class=\"language-kotlin\"><code class=\"language-kotlin\"><span class=\"token keyword\">val</span> movies <span class=\"token operator\">=</span> moviesDataSource<span class=\"token punctuation\">.</span><span class=\"token function\">discover</span><span class=\"token punctuation\">(</span>page<span class=\"token punctuation\">)</span></code></pre></div>\n<ol start=\"3\">\n<li>Insert data into the database or refresh database if loadType is refresh</li>\n</ol>\n<p>The RemoteMediator code will appear as follows:</p>\n<div class=\"gatsby-highlight\" data-language=\"kotlin\"><pre class=\"language-kotlin\"><code class=\"language-kotlin\"><span class=\"token keyword\">class</span> <span class=\"token function\">MoviesRemoteMediator</span><span class=\"token punctuation\">(</span>\n  <span class=\"token keyword\">private</span> <span class=\"token keyword\">val</span> repository<span class=\"token operator\">:</span> MoviesRepository<span class=\"token punctuation\">,</span>\n  <span class=\"token keyword\">private</span> <span class=\"token keyword\">val</span> moviesDataSource<span class=\"token operator\">:</span> NetworkMoviesDataSource<span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">)</span> <span class=\"token operator\">:</span> RemoteMediator<span class=\"token operator\">&lt;</span>Int<span class=\"token punctuation\">,</span> Movie<span class=\"token operator\">></span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n\n  <span class=\"token keyword\">override</span> <span class=\"token keyword\">suspend</span> <span class=\"token keyword\">fun</span> <span class=\"token function\">load</span><span class=\"token punctuation\">(</span>loadType<span class=\"token operator\">:</span> LoadType<span class=\"token punctuation\">,</span> state<span class=\"token operator\">:</span> PagingState<span class=\"token operator\">&lt;</span>Int<span class=\"token punctuation\">,</span> Movie<span class=\"token operator\">></span><span class=\"token punctuation\">)</span><span class=\"token operator\">:</span> MediatorResult <span class=\"token punctuation\">{</span>\n\n    <span class=\"token keyword\">return</span> <span class=\"token keyword\">try</span> <span class=\"token punctuation\">{</span>\n\n      <span class=\"token keyword\">val</span> page <span class=\"token operator\">=</span> <span class=\"token keyword\">when</span> <span class=\"token punctuation\">(</span>loadType<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        LoadType<span class=\"token punctuation\">.</span>REFRESH <span class=\"token operator\">-></span> <span class=\"token number\">1</span>\n        LoadType<span class=\"token punctuation\">.</span>PREPEND <span class=\"token operator\">-></span> <span class=\"token keyword\">null</span>\n        LoadType<span class=\"token punctuation\">.</span>APPEND <span class=\"token operator\">-></span> repository<span class=\"token punctuation\">.</span><span class=\"token function\">getRemoteKey</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token operator\">?</span><span class=\"token punctuation\">.</span>nextPage\n      <span class=\"token punctuation\">}</span> <span class=\"token operator\">?:</span> <span class=\"token keyword\">return</span> <span class=\"token function\">Success</span><span class=\"token punctuation\">(</span>endOfPaginationReached <span class=\"token operator\">=</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">)</span>\n\n      <span class=\"token keyword\">val</span> movies <span class=\"token operator\">=</span> moviesDataSource<span class=\"token punctuation\">.</span><span class=\"token function\">getMovies</span><span class=\"token punctuation\">(</span>page<span class=\"token punctuation\">)</span>\n\n      <span class=\"token keyword\">val</span> nextPage <span class=\"token operator\">=</span> <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>movies<span class=\"token punctuation\">.</span><span class=\"token function\">isNotEmpty</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> page <span class=\"token operator\">+</span> <span class=\"token number\">1</span> <span class=\"token keyword\">else</span> <span class=\"token keyword\">null</span>\n\n      repository<span class=\"token punctuation\">.</span><span class=\"token function\">insertMovies</span><span class=\"token punctuation\">(</span>movies<span class=\"token punctuation\">,</span> nextPage<span class=\"token punctuation\">,</span> loadType <span class=\"token operator\">==</span> LoadType<span class=\"token punctuation\">.</span>REFRESH<span class=\"token punctuation\">)</span>\n\n      <span class=\"token function\">Success</span><span class=\"token punctuation\">(</span>endOfPaginationReached <span class=\"token operator\">=</span> movies<span class=\"token punctuation\">.</span><span class=\"token function\">isEmpty</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n\n    <span class=\"token punctuation\">}</span> <span class=\"token keyword\">catch</span> <span class=\"token punctuation\">(</span>e<span class=\"token operator\">:</span> Exception<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      MediatorResult<span class=\"token punctuation\">.</span><span class=\"token function\">Error</span><span class=\"token punctuation\">(</span>e<span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>RemoteMediator uses the repository to store movies list and next page number in the database.\nRepository also takes care of clearing the database table when data is refreshed:</p>\n<div class=\"gatsby-highlight\" data-language=\"kotlin\"><pre class=\"language-kotlin\"><code class=\"language-kotlin\"><span class=\"token keyword\">class</span> <span class=\"token function\">MoviesRepositoryImpl</span><span class=\"token punctuation\">(</span>\n  <span class=\"token keyword\">private</span> <span class=\"token keyword\">val</span> database<span class=\"token operator\">:</span> MoviesDatabase\n<span class=\"token punctuation\">)</span><span class=\"token operator\">:</span> MoviesRepository <span class=\"token punctuation\">{</span>\n\n  <span class=\"token keyword\">override</span> <span class=\"token keyword\">fun</span> <span class=\"token function\">getMovies</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=</span> database<span class=\"token punctuation\">.</span><span class=\"token function\">movies</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">getMovies</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">map</span> <span class=\"token punctuation\">{</span> it<span class=\"token punctuation\">.</span><span class=\"token function\">toDomain</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">}</span>\n\n  <span class=\"token keyword\">override</span> <span class=\"token keyword\">suspend</span> <span class=\"token keyword\">fun</span> <span class=\"token function\">insertMovies</span><span class=\"token punctuation\">(</span>movies<span class=\"token operator\">:</span> List<span class=\"token operator\">&lt;</span>Movie<span class=\"token operator\">></span><span class=\"token punctuation\">,</span> nextPage<span class=\"token operator\">:</span> Int<span class=\"token operator\">?</span><span class=\"token punctuation\">,</span> clear<span class=\"token operator\">:</span> Boolean<span class=\"token punctuation\">)</span><span class=\"token punctuation\">{</span>\n\n    database<span class=\"token punctuation\">.</span><span class=\"token function\">withTransaction</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>clear<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        database<span class=\"token punctuation\">.</span><span class=\"token function\">movies</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">clear</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n      <span class=\"token punctuation\">}</span>\n\n      database<span class=\"token punctuation\">.</span><span class=\"token function\">movies</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">putMovies</span><span class=\"token punctuation\">(</span>movies<span class=\"token punctuation\">.</span><span class=\"token function\">map</span> <span class=\"token punctuation\">{</span> it<span class=\"token punctuation\">.</span><span class=\"token function\">toDbEntity</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n      <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>nextPage <span class=\"token operator\">!=</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        database<span class=\"token punctuation\">.</span><span class=\"token function\">remoteKey</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">insertKey</span><span class=\"token punctuation\">(</span><span class=\"token function\">RemoteKey</span><span class=\"token punctuation\">(</span>MoviesDatabase<span class=\"token punctuation\">.</span>MOVIES_REMOTE_KEY<span class=\"token punctuation\">,</span> nextPage<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n      <span class=\"token punctuation\">}</span>\n    <span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<h2>UI layer</h2>\n<p>The Pager object serves as a bridge between remote and local data sources. It is managing the page loading, prefetching, and handling the transitions between various data sources to provide a seamless and responsive flow of paginated content within your application. You can configure the page loading behavior with the following parameters:</p>\n<ul>\n<li><strong>pageSize</strong> parameter defines the number of items loaded in each page of data.</li>\n<li><strong>initialLoadSize</strong> is the number of items loaded initially when the paging library is first initialized.</li>\n<li><strong>prefetchDistance</strong> parameter determines the distance from the edge of the loaded content at which the next page should start loading.</li>\n</ul>\n<div class=\"gatsby-highlight\" data-language=\"kotlin\"><pre class=\"language-kotlin\"><code class=\"language-kotlin\"><span class=\"token keyword\">class</span> <span class=\"token function\">MoviesScreenViewModel</span><span class=\"token punctuation\">(</span>\n  moviesSource<span class=\"token operator\">:</span> MoviesRemoteMediator<span class=\"token punctuation\">,</span>\n  repository<span class=\"token operator\">:</span> MoviesRepository<span class=\"token punctuation\">,</span>\n  <span class=\"token keyword\">private</span> <span class=\"token keyword\">val</span> movieDetails<span class=\"token operator\">:</span> MovieDetailsApi<span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">)</span> <span class=\"token operator\">:</span> <span class=\"token function\">ViewModel</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n   <span class=\"token keyword\">val</span> moviesFlow <span class=\"token operator\">=</span> <span class=\"token function\">Pager</span><span class=\"token punctuation\">(</span>\n      config <span class=\"token operator\">=</span> <span class=\"token function\">PagingConfig</span><span class=\"token punctuation\">(</span>\n        pageSize <span class=\"token operator\">=</span> PAGE_SIZE<span class=\"token punctuation\">,</span>\n        prefetchDistance <span class=\"token operator\">=</span> PREFETCH_DISTANCE<span class=\"token punctuation\">,</span>\n        initialLoadSize <span class=\"token operator\">=</span> INITIAL_LOAD<span class=\"token punctuation\">,</span>\n      <span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n      remoteMediator <span class=\"token operator\">=</span> moviesSource<span class=\"token punctuation\">,</span>\n      pagingSourceFactory <span class=\"token operator\">=</span> repository<span class=\"token punctuation\">.</span><span class=\"token function\">getMovies</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">asPagingSourceFactory</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>flow<span class=\"token punctuation\">.</span><span class=\"token function\">cachedIn</span><span class=\"token punctuation\">(</span>viewModelScope<span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<h3>Consuming paging data in Jetpack Compose UI</h3>\n<p>Now, let's explore how to consume the paginated data in your Compose UI.</p>\n<p>Use the <code class=\"language-text\">collectAsLazyPagingItems</code> extension function to collect the <code class=\"language-text\">PagingData</code> and observe changes.</p>\n<div class=\"gatsby-highlight\" data-language=\"kotlin\"><pre class=\"language-kotlin\"><code class=\"language-kotlin\"><span class=\"token keyword\">val</span> movies <span class=\"token operator\">=</span> viewModel<span class=\"token punctuation\">.</span>moviesFlow<span class=\"token punctuation\">.</span><span class=\"token function\">collectAsLazyPagingItems</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>Use the <code class=\"language-text\">LazyColumn</code> or <code class=\"language-text\">LazyVerticalGrid</code> to efficiently display paginated data in your Compose UI.</p>\n<div class=\"gatsby-highlight\" data-language=\"kotlin\"><pre class=\"language-kotlin\"><code class=\"language-kotlin\"><span class=\"token function\">LazyVerticalGrid</span><span class=\"token punctuation\">(</span>\n      modifier <span class=\"token operator\">=</span> Modifier\n        <span class=\"token punctuation\">.</span><span class=\"token function\">fillMaxSize</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n        <span class=\"token punctuation\">.</span><span class=\"token function\">padding</span><span class=\"token punctuation\">(</span><span class=\"token number\">16</span><span class=\"token punctuation\">.</span>dp<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n      columns <span class=\"token operator\">=</span> GridCells<span class=\"token punctuation\">.</span><span class=\"token function\">Fixed</span><span class=\"token punctuation\">(</span><span class=\"token number\">3</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n      horizontalArrangement <span class=\"token operator\">=</span> Arrangement<span class=\"token punctuation\">.</span><span class=\"token function\">spacedBy</span><span class=\"token punctuation\">(</span><span class=\"token number\">16</span><span class=\"token punctuation\">.</span>dp<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n      verticalArrangement <span class=\"token operator\">=</span> Arrangement<span class=\"token punctuation\">.</span><span class=\"token function\">spacedBy</span><span class=\"token punctuation\">(</span><span class=\"token number\">16</span><span class=\"token punctuation\">.</span>dp<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n\n      <span class=\"token function\">items</span><span class=\"token punctuation\">(</span>\n        count <span class=\"token operator\">=</span> movies<span class=\"token punctuation\">.</span>itemCount<span class=\"token punctuation\">,</span>\n        key <span class=\"token operator\">=</span> movies<span class=\"token punctuation\">.</span><span class=\"token function\">itemKey</span> <span class=\"token punctuation\">{</span> it<span class=\"token punctuation\">.</span>id <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n      <span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span> index <span class=\"token operator\">-></span>\n\n        movies<span class=\"token punctuation\">[</span>index<span class=\"token punctuation\">]</span><span class=\"token operator\">?</span><span class=\"token punctuation\">.</span><span class=\"token function\">let</span> <span class=\"token punctuation\">{</span> movie <span class=\"token operator\">-></span>\n          <span class=\"token function\">MovieCardSmall</span><span class=\"token punctuation\">(</span>\n            movie <span class=\"token operator\">=</span> movie<span class=\"token punctuation\">,</span>\n            onClick <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span> <span class=\"token function\">onClick</span><span class=\"token punctuation\">(</span>movie<span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n          <span class=\"token punctuation\">)</span>\n        <span class=\"token punctuation\">}</span>\n      <span class=\"token punctuation\">}</span>\n    <span class=\"token punctuation\">}</span></code></pre></div>\n<hr>\n<blockquote>\n<p><em>Note the usage of the key property for items. The key property uniquely identifies each item, allowing Compose to efficiently update and recycle composables as data changes.</em></p>\n</blockquote>\n<hr>\n<h3>Paging state handling</h3>\n<p>LazyPagingItems offers insights into the ongoing data loading process, allowing you to effectively manage errors during pagination. By examining the loadState.append property, you can determine the loading state when appending new items and present a user-friendly indication of the current status.</p>\n<p>For instance, the following code snippet demonstrates how to react to different loading states during item appending:</p>\n<div class=\"gatsby-highlight\" data-language=\"kotlin\"><pre class=\"language-kotlin\"><code class=\"language-kotlin\"><span class=\"token keyword\">when</span> <span class=\"token punctuation\">(</span>movies<span class=\"token punctuation\">.</span>loadState<span class=\"token punctuation\">.</span>append<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">is</span> LoadState<span class=\"token punctuation\">.</span>Loading <span class=\"token operator\">-></span> <span class=\"token punctuation\">{</span> <span class=\"token function\">ProgressFooter</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">}</span>\n  <span class=\"token keyword\">is</span> LoadState<span class=\"token punctuation\">.</span>Error <span class=\"token operator\">-></span> <span class=\"token punctuation\">{</span> <span class=\"token function\">ErrorFooter</span><span class=\"token punctuation\">(</span>onRetryClick <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span> movies<span class=\"token punctuation\">.</span><span class=\"token function\">retry</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">}</span> <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Similarly, you can assess the loading status when the list data is refreshed by checking the loadState.refresh property. Extension functions isError() and isLoading() provide convenient checks for error and loading states, respectively.</p>\n<div class=\"gatsby-highlight\" data-language=\"kotlin\"><pre class=\"language-kotlin\"><code class=\"language-kotlin\"><span class=\"token keyword\">fun</span> LazyPagingItems<span class=\"token operator\">&lt;</span>Movie<span class=\"token operator\">></span><span class=\"token punctuation\">.</span><span class=\"token function\">isError</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token operator\">:</span> Boolean <span class=\"token operator\">=</span> \n    loadState<span class=\"token punctuation\">.</span>refresh <span class=\"token keyword\">is</span> LoadState<span class=\"token punctuation\">.</span>Error <span class=\"token operator\">&amp;&amp;</span> itemSnapshotList<span class=\"token punctuation\">.</span><span class=\"token function\">isEmpty</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n\n<span class=\"token keyword\">fun</span> LazyPagingItems<span class=\"token operator\">&lt;</span>Movie<span class=\"token operator\">></span><span class=\"token punctuation\">.</span><span class=\"token function\">isLoading</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token operator\">:</span> Boolean <span class=\"token operator\">=</span> \n    loadState<span class=\"token punctuation\">.</span>refresh <span class=\"token keyword\">is</span> LoadState<span class=\"token punctuation\">.</span>Loading <span class=\"token operator\">&amp;&amp;</span> itemSnapshotList<span class=\"token punctuation\">.</span><span class=\"token function\">isEmpty</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>Incorporate these checks into your UI logic to display appropriate screens based on the loading or error states. The following code snippet demonstrates how to handle loading and error states along with providing a retry option:</p>\n<div class=\"gatsby-highlight\" data-language=\"kotlin\"><pre class=\"language-kotlin\"><code class=\"language-kotlin\"><span class=\"token keyword\">when</span> <span class=\"token punctuation\">{</span>\n   movies<span class=\"token punctuation\">.</span><span class=\"token function\">isLoading</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">-></span> <span class=\"token function\">LoadingScreen</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n   movies<span class=\"token punctuation\">.</span><span class=\"token function\">isError</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">-></span> ErrorScreen <span class=\"token punctuation\">{</span> movies<span class=\"token punctuation\">.</span><span class=\"token function\">retry</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">}</span>\n   <span class=\"token keyword\">else</span> <span class=\"token operator\">-></span> <span class=\"token function\">MoviesGrid</span><span class=\"token punctuation\">(</span>movies <span class=\"token operator\">=</span> movies<span class=\"token punctuation\">,</span> onClick <span class=\"token operator\">=</span> viewModel<span class=\"token operator\">::</span>onMovieClick<span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Additionally, <code class=\"language-text\">LazyPagingItems</code> offers a convenient <code class=\"language-text\">retry()</code> method, allowing you to retry the last failed data loading attempt with ease.</p>\n<h3>Adding filters</h3>\n<p>Now lets add filters to our movie list to see paginated list of movies filtered by genre.</p>\n<p><img src=\"/static/paging_demo_filters-ff80a7606fb30961e2bda56bd6ed9985.gif\" alt=\"Filters UI\"></p>\n<p>We start with requesting genres from the server and saving them in our database. We will keep genre data and selection in the database so that we can observe it from our domain and UI layers.</p>\n<div class=\"gatsby-highlight\" data-language=\"kotlin\"><pre class=\"language-kotlin\"><code class=\"language-kotlin\"><span class=\"token keyword\">interface</span> MoviesApi <span class=\"token punctuation\">{</span>\n  <span class=\"token annotation builtin\">@GET</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"/3/genre/movie/list?language=en-US\"</span><span class=\"token punctuation\">)</span>\n  <span class=\"token keyword\">suspend</span> <span class=\"token keyword\">fun</span> <span class=\"token function\">genres</span><span class=\"token punctuation\">(</span><span class=\"token annotation builtin\">@Query</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"api_key\"</span><span class=\"token punctuation\">)</span> api_key<span class=\"token operator\">:</span> String<span class=\"token punctuation\">)</span><span class=\"token operator\">:</span> Response<span class=\"token operator\">&lt;</span>GenresNetworkResponse<span class=\"token operator\">></span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token annotation builtin\">@Dao</span>\n<span class=\"token keyword\">interface</span> GenresDao <span class=\"token punctuation\">{</span>\n\n  <span class=\"token annotation builtin\">@Insert</span><span class=\"token punctuation\">(</span>onConflict <span class=\"token operator\">=</span> OnConflictStrategy<span class=\"token punctuation\">.</span>REPLACE<span class=\"token punctuation\">)</span>\n  <span class=\"token keyword\">suspend</span> <span class=\"token keyword\">fun</span> <span class=\"token function\">putGenres</span><span class=\"token punctuation\">(</span>genres<span class=\"token operator\">:</span> List<span class=\"token operator\">&lt;</span>GenreDbEntity<span class=\"token operator\">></span><span class=\"token punctuation\">)</span>\n\n  <span class=\"token annotation builtin\">@Upsert</span><span class=\"token punctuation\">(</span>entity <span class=\"token operator\">=</span> GenreDbEntity<span class=\"token operator\">::</span><span class=\"token keyword\">class</span><span class=\"token punctuation\">)</span>\n  <span class=\"token keyword\">suspend</span> <span class=\"token keyword\">fun</span> <span class=\"token function\">updateGenres</span><span class=\"token punctuation\">(</span>genres<span class=\"token operator\">:</span> List<span class=\"token operator\">&lt;</span>GenreDbUpdateEntity<span class=\"token operator\">></span><span class=\"token punctuation\">)</span>\n\n  <span class=\"token annotation builtin\">@Query</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"SELECT * FROM genres\"</span><span class=\"token punctuation\">)</span>\n  <span class=\"token keyword\">suspend</span> <span class=\"token keyword\">fun</span> <span class=\"token function\">getGenres</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token operator\">:</span> List<span class=\"token operator\">&lt;</span>GenreDbEntity<span class=\"token operator\">></span>\n\n  <span class=\"token annotation builtin\">@Query</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"SELECT * FROM genres\"</span><span class=\"token punctuation\">)</span>\n  <span class=\"token keyword\">fun</span> <span class=\"token function\">observeGenres</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token operator\">:</span> Flow<span class=\"token operator\">&lt;</span>List<span class=\"token operator\">&lt;</span>GenreDbEntity<span class=\"token operator\">></span><span class=\"token operator\">></span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Now we can add <code class=\"language-text\">with_genres</code> parameter to our network request:</p>\n<div class=\"gatsby-highlight\" data-language=\"kotlin\"><pre class=\"language-kotlin\"><code class=\"language-kotlin\">  <span class=\"token annotation builtin\">@GET</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"/3/discover/movie?language=en-US&amp;sort_by=popularity.desc\"</span><span class=\"token punctuation\">)</span>\n  <span class=\"token keyword\">suspend</span> <span class=\"token keyword\">fun</span> <span class=\"token function\">discover</span><span class=\"token punctuation\">(</span>\n    <span class=\"token annotation builtin\">@Query</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"page\"</span><span class=\"token punctuation\">)</span> page<span class=\"token operator\">:</span> Int<span class=\"token punctuation\">,</span>\n    <span class=\"token annotation builtin\">@Query</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"with_genres\"</span><span class=\"token punctuation\">)</span> genres<span class=\"token operator\">:</span> String<span class=\"token punctuation\">,</span>\n    <span class=\"token annotation builtin\">@Query</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"api_key\"</span><span class=\"token punctuation\">)</span> api_key<span class=\"token operator\">:</span> String<span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">)</span><span class=\"token operator\">:</span> Response<span class=\"token operator\">&lt;</span>MoviesNetworkResponse<span class=\"token operator\">></span></code></pre></div>\n<p>Remote mediator will get selected genres from the repository</p>\n<div class=\"gatsby-highlight\" data-language=\"kotlin\"><pre class=\"language-kotlin\"><code class=\"language-kotlin\">  <span class=\"token operator\">..</span><span class=\"token punctuation\">.</span>\n  <span class=\"token keyword\">val</span> genres <span class=\"token operator\">=</span> repository<span class=\"token punctuation\">.</span><span class=\"token function\">getGenreSelection</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n  <span class=\"token keyword\">val</span> movies <span class=\"token operator\">=</span> moviesDataSource<span class=\"token punctuation\">.</span><span class=\"token function\">getMovies</span><span class=\"token punctuation\">(</span>page<span class=\"token punctuation\">,</span> genres<span class=\"token punctuation\">)</span>\n  <span class=\"token operator\">..</span><span class=\"token punctuation\">.</span></code></pre></div>\n<p>Every time user selects a new filter we stave it in the database and restart pagination by clearing movies in the database and resetting the page to 1.</p>\n<div class=\"gatsby-highlight\" data-language=\"kotlin\"><pre class=\"language-kotlin\"><code class=\"language-kotlin\"><span class=\"token keyword\">class</span> MoviesScreenViewModel <span class=\"token punctuation\">{</span>\n\n  <span class=\"token keyword\">fun</span> <span class=\"token function\">onGenreClick</span><span class=\"token punctuation\">(</span>genreItem<span class=\"token operator\">:</span> GenreItem<span class=\"token punctuation\">)</span> <span class=\"token operator\">=</span> viewModelScope<span class=\"token punctuation\">.</span><span class=\"token function\">launch</span> <span class=\"token punctuation\">{</span>\n    genresProvider<span class=\"token punctuation\">.</span><span class=\"token function\">setSelection</span><span class=\"token punctuation\">(</span>genreItem<span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">,</span> <span class=\"token operator\">!</span>genreItem<span class=\"token punctuation\">.</span>isSelected<span class=\"token punctuation\">)</span>\n    repository<span class=\"token punctuation\">.</span><span class=\"token function\">clearMovies</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span>\n  \n<span class=\"token punctuation\">}</span></code></pre></div>\n<div class=\"gatsby-highlight\" data-language=\"kotlin\"><pre class=\"language-kotlin\"><code class=\"language-kotlin\"><span class=\"token keyword\">class</span> MoviesRepositoryImpl <span class=\"token punctuation\">{</span>\n\n  <span class=\"token keyword\">override</span> <span class=\"token keyword\">suspend</span> <span class=\"token keyword\">fun</span> <span class=\"token function\">clearMovies</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=</span> <span class=\"token function\">withContext</span><span class=\"token punctuation\">(</span>Dispatchers<span class=\"token punctuation\">.</span>IO<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    database<span class=\"token punctuation\">.</span><span class=\"token function\">withTransaction</span> <span class=\"token punctuation\">{</span>\n      database<span class=\"token punctuation\">.</span><span class=\"token function\">movies</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">clear</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n      database<span class=\"token punctuation\">.</span><span class=\"token function\">remoteKey</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">insertKey</span><span class=\"token punctuation\">(</span><span class=\"token function\">RemoteKey</span><span class=\"token punctuation\">(</span>MoviesDatabase<span class=\"token punctuation\">.</span>MOVIES_REMOTE_KEY<span class=\"token punctuation\">,</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">}</span>\n\n<span class=\"token punctuation\">}</span></code></pre></div>\n<h3>Links</h3>\n<p><br>Source code: <a href=\"https://github.com/auto1-oss/android-compose-paging\">https://github.com/auto1-oss/android-compose-paging</a></br>\n<br>Official documentation: <a href=\"https://developer.android.com/topic/libraries/architecture/paging/v3-overview\">https://developer.android.com/topic/libraries/architecture/paging/v3-overview</a></br></p>","fields":{"slug":"/android-compose-pagination/","tags":["auto1","mobile","Android"]}}},{"node":{"id":"2cda3518-ba96-5257-97f4-6f0ec1f69eb1","frontmatter":{"category":"Engineering","title":"Bug Police Officer","date":"2023-11-21","summary":"What I present today is how to use police techniques and their mindset to detect and solve bugs in software, so that you can be the best software developer that society can provide.","thumbnail":{"relativePath":"pages/bug-police-officer/bug-police-officer.png","childImageSharp":{"resolutions":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAAAsSAAALEgHS3X78AAAC20lEQVQ4y32S208TURCHF6rvvPpI/Ad8MzFIIlESaAuoAZVehEppd7fQFqjhIgiBQhEUaoFy6wUCghRrCFKQi4orhgQ0XOIFA8FoqOKTaHyg7e54zpYWUOsks2fOmd98Z85mCOIPqyNtUQf33Xp7XOZl+7oEua3AfvpgzkTZo4hIVq9oC8PQGluh7M4hpdYh0fl2aFFfh1a1AcQX2oGUWV0ol2si7bH/auAQsFptE+C4VesUZUnscPxMMxyLa2FXikXsKnIc4zOca9M5hVhbs1cT0fKzuniBkbTnSqU2iBeaA/KMZg47jmVSB9RSDjXW6BXdgv8+mf8vpDMar02qzlMG+gGkKz1cunI06Lkergid3VF1xR3URrRG2k48HZziRf31wxVrzCI01I4HZNQYh73RNBF4P7sAvUZXGdZMOMajcU1E2G3aRjDuJ4I9oAV+fQPY2fB9fbsE2OHHhg9+bkOP0dWENdP9k4JbtIP4C2qinfzq0LQTN8i+I8HTE0eZoak18H8B3/dN1rezyeKYGZx8h5L8pVjbr7EcYoTpnryG8AVLhuqYLk2Dtir/nnfrzQqA7xMLvs/s1uoylObd91ZRvboPRZUxIX2oNtxpB+osZDV0j44mR7wfKy+CRVsHGsM0++oxAwsTL8BgGGUTVAxc0r0EinJ7jXSvLlQXZmBqCTUQHBW6h1YWMhBPLkKfvsi/XprAJimfQbLCw4kVY9xZ5Qxco0ZZCenxn6MYyCmcAwSlcS1m8B3yHzXw066nh8dTtfOQSD3fldETsF12Emq1Fi6BmueSNLNcJjXDjZVL4GEJCSJybjcFaQtQDd8ZYuwDCQgOtWpgMl35CMRZrkCi3MMN5athuVgIomwPpGS7QCx3Q7WmGKrIm1ySfCSAZhNwTfCtQOwDY8v5DrVXO9wZGZ2Qkmb2J6fe5SipGV6XXIE8tKI9CNPMIEy1otjKiZAGa3ENz0MMzPoNzyOqI3a+TN4AAAAASUVORK5CYII=","width":460,"height":325,"src":"/static/19a57f273a6f7441d951955ce11fae27/b3029/bug-police-officer.png","srcSet":"/static/19a57f273a6f7441d951955ce11fae27/b3029/bug-police-officer.png 1x"}}},"authorName":"Bruno Morais","authorDescription":"Bruno is a Senior Software Engineer at AUTO1 Group.","authorAvatar":{"relativePath":"pages/bug-police-officer/avatar.jpeg","childImageSharp":{"resolutions":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAUABQDASIAAhEBAxEB/8QAGAABAQEBAQAAAAAAAAAAAAAAAAQDAQX/xAAXAQEBAQEAAAAAAAAAAAAAAAABAwIE/9oADAMBAAIQAxAAAAGmbSadPSZMPIBLBy1//8QAHBAAAwABBQAAAAAAAAAAAAAAAQIDIQAQERIj/9oACAEBAAEFAqOVEql2047LLDc7A+i5H//EABcRAQEBAQAAAAAAAAAAAAAAAAEAEBL/2gAIAQMBAT8BC5jP/8QAGREAAwADAAAAAAAAAAAAAAAAAAECEBET/9oACAECAQE/AW9HSSsf/8QAGhAAAQUBAAAAAAAAAAAAAAAAAQACEBEhQf/aAAgBAQAGPwLBZRa4VFYt5Jj/xAAcEAADAAIDAQAAAAAAAAAAAAAAAREhURAxYXH/2gAIAQEAAT8ho6G+i0ElVBP0c6AzfMaH3OHLLoTIz//aAAwDAQACAAMAAAAQcC98/8QAGREAAwADAAAAAAAAAAAAAAAAABExEFGB/9oACAEDAQE/EGQbRPcf/8QAGxEAAgIDAQAAAAAAAAAAAAAAAAERMVFhscH/2gAIAQIBAT8QuM2dElucejs//8QAGxABAQEBAAMBAAAAAAAAAAAAAREAITFBYXH/2gAIAQEAAT8QEiRCoPrgpVComQJxnQidLfOE1gCkvzQ9j4TPv80LcHh6dw+UV3//2Q==","width":50,"height":50,"src":"/static/8d7223890dda036e0121799406a35506/d2d31/avatar.jpeg","srcSet":"/static/8d7223890dda036e0121799406a35506/d2d31/avatar.jpeg 1x,\n/static/8d7223890dda036e0121799406a35506/0b804/avatar.jpeg 1.5x,\n/static/8d7223890dda036e0121799406a35506/753c3/avatar.jpeg 2x,\n/static/8d7223890dda036e0121799406a35506/31ca8/avatar.jpeg 3x"}}},"headerImage":{"relativePath":"pages/bug-police-officer/bug-police-officer.png","childImageSharp":{"resolutions":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAAAsSAAALEgHS3X78AAAC20lEQVQ4y32S208TURCHF6rvvPpI/Ad8MzFIIlESaAuoAZVehEppd7fQFqjhIgiBQhEUaoFy6wUCghRrCFKQi4orhgQ0XOIFA8FoqOKTaHyg7e54zpYWUOsks2fOmd98Z85mCOIPqyNtUQf33Xp7XOZl+7oEua3AfvpgzkTZo4hIVq9oC8PQGluh7M4hpdYh0fl2aFFfh1a1AcQX2oGUWV0ol2si7bH/auAQsFptE+C4VesUZUnscPxMMxyLa2FXikXsKnIc4zOca9M5hVhbs1cT0fKzuniBkbTnSqU2iBeaA/KMZg47jmVSB9RSDjXW6BXdgv8+mf8vpDMar02qzlMG+gGkKz1cunI06Lkergid3VF1xR3URrRG2k48HZziRf31wxVrzCI01I4HZNQYh73RNBF4P7sAvUZXGdZMOMajcU1E2G3aRjDuJ4I9oAV+fQPY2fB9fbsE2OHHhg9+bkOP0dWENdP9k4JbtIP4C2qinfzq0LQTN8i+I8HTE0eZoak18H8B3/dN1rezyeKYGZx8h5L8pVjbr7EcYoTpnryG8AVLhuqYLk2Dtir/nnfrzQqA7xMLvs/s1uoylObd91ZRvboPRZUxIX2oNtxpB+osZDV0j44mR7wfKy+CRVsHGsM0++oxAwsTL8BgGGUTVAxc0r0EinJ7jXSvLlQXZmBqCTUQHBW6h1YWMhBPLkKfvsi/XprAJimfQbLCw4kVY9xZ5Qxco0ZZCenxn6MYyCmcAwSlcS1m8B3yHzXw066nh8dTtfOQSD3fldETsF12Emq1Fi6BmueSNLNcJjXDjZVL4GEJCSJybjcFaQtQDd8ZYuwDCQgOtWpgMl35CMRZrkCi3MMN5athuVgIomwPpGS7QCx3Q7WmGKrIm1ySfCSAZhNwTfCtQOwDY8v5DrVXO9wZGZ2Qkmb2J6fe5SipGV6XXIE8tKI9CNPMIEy1otjKiZAGa3ENz0MMzPoNzyOqI3a+TN4AAAAASUVORK5CYII=","width":600,"height":424,"src":"/static/19a57f273a6f7441d951955ce11fae27/b7ca8/bug-police-officer.png","srcSet":"/static/19a57f273a6f7441d951955ce11fae27/b7ca8/bug-police-officer.png 1x"}}}},"html":"<h3>Table of contents:</h3>\n<ol>\n<li>\n<p>Sense of Security</p>\n<ol>\n<li>Why does feeling safe matter?</li>\n<li>Strategic actions</li>\n<li>A test as a Cop</li>\n</ol>\n</li>\n<li>\n<p>Treat the injured first</p>\n<ol>\n<li>Prioritizing what matters</li>\n<li>The appropriate Mental Model</li>\n<li>Ask before trying to find out</li>\n</ol>\n</li>\n<li>\n<p>Trust your tools</p>\n<ol>\n<li>When less is more</li>\n<li>Efficient distribution of efforts</li>\n<li>Confidence that avoids shame</li>\n</ol>\n</li>\n<li>\n<p>Communication via Radio</p>\n<ol>\n<li>Q-code</li>\n<li>The Language and the Domain</li>\n</ol>\n</li>\n<li>Bug is in jail</li>\n</ol>\n<p><strong>What I present today is how to use police techniques and their mindset to detect and solve bugs in software, so that you can be the best software developer that society can provide.</strong></p>\n<p>For some years, I worked as a police officer in Brazil and I can say that it is a challenging career. The first step was to pass a national test, where knowledge of various laws was required. Criminal laws, traffic laws, and even the laws of physics.</p>\n<p>The second step was to pass a battery of medical exams. Almost perfect health was necessary to be able to practice the profession, in addition to having most of the parts of the human body.</p>\n<p>The third step was the psychological examination. It was necessary to have a clear mind and not have impulses different from those expected from a person who must protect other people.</p>\n<p>As a fourth part, there was also the fitness test, a test in which career candidates had to prove they had sufficient strength and speed to carry out daily police tasks. Running, pull-ups, sit-ups and long jump are examples of what was required.</p>\n<p>The last stage was the Police Academy, where for three months those from now on known as students would learn and prove the learning of several new skills: first aid, use of firearms (pistols, carbines, submachine guns, etc.), non-lethal weapons, martial arts, public policy, and many other disciplines.</p>\n<p>All this so that society receives the best police officer that its people can provide. So, what about using some of the following principles and techniques to become the best software developer that society can provide?</p>\n<h2>Sense of Security</h2>\n<h3>Why does feeling safe matter?</h3>\n<p>Without needing to be a security expert, you already know that it is impossible to have a completely safe city. Even if we reached the point of having perfect police officers, which in itself is impossible, we would not have a police officer for every citizen. In general, the recommendation is 300 police officers for every 100 thousand inhabitants.</p>\n<p>Aware of this limitation, that it is not possible to guarantee complete security for all citizens, police agencies work with the concept of a sense of security. Through strategic actions to combat crime, citizens' feeling that they are safe is increased. This mental condition gives them peace of mind when working, studying, and carrying out their daily tasks.</p>\n<h3>Strategic actions</h3>\n<p>This sense of security also affects criminals. The common visibility of police officers carrying out their duties in strategic places, as well as effective actions to combat crime, make criminals stay away from that place.</p>\n<p>Notice that ending 100% of crime is impossible, what we do well is limit its actions. From here we can extract our first lesson when dealing with software: perfect code, totally bug-free, is impossible.</p>\n<p>Despite this conclusion, the fact that it is impossible does not mean that we should simply ignore the problem. On the contrary, we can, like the police, create strategic actions to combat Bugs. To the point that Bugs themselves will run away from our code.</p>\n<h3>A test as a Cop</h3>\n<p>Test Driven Development - TDD is a strategic action that provides a feeling of security in your code. Before the crime occurs, you position police officers in a specific region. Before the Bug occurs, you position the test in a specific place in your code.</p>\n<p>Robert C. Martin, in his book \"Clean Code: A HandBook of Agile Software Craftsmanship\", teaches us that writing unit tests before writing production code is just the tip of the iceberg in defining TDD. There must be a continuous cycle of improvement, in which there is always a test covering the code you are developing and this security that the code is protected allows you to play with it, and work with it. After all, whatever problem may happen, there is a police-test there to protect you.</p>\n<h2>Treat the injured first</h2>\n<h3>Prioritizing what matters</h3>\n<p>One of the functions of Highway Police Officers is to provide first aid in the event of traffic accidents. There are often serious injuries that must be treated as urgently as possible, as even 1 minute can make the difference between life and death.</p>\n<p>The first step when arriving at a traffic accident site is to mark the location appropriately to prevent other accidents. We must use lighting devices and other appliances to make it clear to other vehicles that there is a danger there.</p>\n<p>The police officer must then check the condition of all the injured to prioritize them according to the severity of each situation.</p>\n<p>Once the treatment of each injured person has been completed and, if necessary, they have been taken to the hospital, it is time to survey the accident site. At this stage, the police officer begins to collect all the information relating to the accident to have sufficient information so that a decision can be made on the cause of the accident and, when applicable, any culprits.</p>\n<h3>The appropriate Mental Model</h3>\n<p>This is the mental model that you and I must adopt when we are faced with a Bug. Although several procedures have been adopted to prevent it from occurring, it is a fatality that can happen. It's like when the highway was well designed, the vehicles were up to date with maintenance, but even so, due to carelessness or misunderstanding on the part of the driver, an accident happens.</p>\n<p>As in the case of traffic accidents, the first step to take is to secure the environment so that the Bug does not cause other problems. If possible, we can revert the application version to one in which the Bug did not appear. We can use a feature flag to temporarily disable a feature. Regardless of the method used to stop the bleeding, the important thing is that we must focus on treating the injured first rather than looking for culprits.</p>\n<p>We have to agree with David Thomas and Andrew Hunt, in their work \"The Pragmatic Programmer: your journey to mastery\" that facing Bugs is a sensitive subject for most developers. Instead of treating the issue as a problem to be solved, some approach it with denial, pointing fingers, lame excuses, or simply apathy. It's exactly the opposite of what is expected!</p>\n<p>Instead of looking for the culprit in a traffic accident, we must first assist the victims and stop the bleeding. In software, instead of finding out who inserted the Bug, we must solve it.</p>\n<h3>Ask before trying to find out</h3>\n<p>When treating an injured person in an emergency, one approach is to use the Glasgow Scale to determine the patient's consciousness. On this scale, one of the components is the verbal response.</p>\n<p>The injured person is asked simple questions, and by analyzing the responses, we can assess the level of consciousness and consequently the level of urgency of their care.</p>\n<p>You and I must carefully read every error message that is displayed during the Bug, it may contain vital information so that we can resolve the problem.</p>\n<p>You may be thinking, but what if there is no error message? If we are just faced with an incorrect result? Well, this also happens in traffic accidents, it is not uncommon for there to be an unconscious victim who cannot answer questions.</p>\n<p>When we discussed the sense of security, we talked about the importance of tests in our application. Go and build a test that can reproduce that Bug, so you can extract the information you need to solve it.</p>\n<p>Think of these tests like the motor tests that highway patrol officers perform on unconscious victims to check their level of consciousness: do the eyes open in response to pain? Is there a pupillary response to light stimulation? Mentally translate this into software language: Does the Bug repeat itself when I enter this and that parameter? And if I insert this new argument, does it happen too?</p>\n<p>To decide on a Bug, data is needed. If you don't receive this data, you must extract it.</p>\n<h2>Trust your tools</h2>\n<h3>When less is more</h3>\n<p>Police work is very complex and your day-to-day job involves the fight for life and protection of the most important assets for society. There would be no point in having a modern and efficient selection and training process for the development of police officers if they were not given the appropriate tools for their work.</p>\n<p>And when I say appropriate, I don't mean they are minimally capable of performing the task, as the result delivered is directly related to the quality and safety of the tools. For an excellent result, not only the police officers but their tools must also be excellent.</p>\n<p>In the police agency I worked for, one of the work tools used was an Austrian pistol known worldwide for its safety and efficiency. The Glock 17 pistol was developed to meet the strict criteria of the Austrian army who wanted to replace the model used during the Second World War.</p>\n<p>In addition to requirements on durability, efficiency, and reliability, safety against accidental firing was one of the pivots of the new model.</p>\n<p>But how did a knife factory manage to deliver the pistol model that would prove to be the safest? Well, it can be said that, in addition to intense testing, the secret to reliability was simplicity and maintainability. The person responsible for the project designed the equipment with as few parts as possible, minimizing complexity. Today the Glock pistol is made with an average of 35 parts, which is a much smaller quantity than other pistols on the market.</p>\n<p>With a simpler design, so-called first-level maintenance is much easier. Equipment users can easily perform maintenance procedures, making the equipment's efficiency last for decades.</p>\n<p>Of course, you must already remember the principle with the acronym KISS, which stands for Keep it Simple (omitting the last word because I don't want to offend the reader). The secret of that renowned pistol model was not in the used materials, but in being simple. The secret of maintaining your software in good shape is to keep it simple, having a specific component for each task. When a problem arises, you will know exactly which component to look for, as each component has a responsibility, this is the principle of Single Responsibility.</p>\n<p>Because of all this, when you are at a shooting range practicing your aim, the police officer knows that if he is not hitting the target, most likely, the error is in his procedure and not in the equipment.</p>\n<p>Allan Kelly, in one of his contributions to the Book \"97 Things Every Programmer Should Know\", corroborates this idea that we should trust our tools when dealing with Bugs. Considering our tools are widely used, mature, and in use by multiple companies, we have little reason to doubt their quality.</p>\n<p>Of course, a prototype, version 0.1, is much more fragile than a library that has been on the market for several years. We are also not saying that it is impossible to have bugs in compilers.</p>\n<p>But considering how rare compiler bugs are, what we are saying is that in the search for a Bug solution, we should trust our tools and look at our piece of code first.</p>\n<h3>Efficient distribution of efforts</h3>\n<p>Imagine it as an efficient distribution of efforts. The library or compiler code has already been reviewed and tested for many years by countless people. As for that little piece of code of yours, only God knows who besides you has looked at it on your team.</p>\n<p>On one of those days, I managed to solve an unpleasant bug that occurred in one of our services. It was a non-deterministic error in our test suite, that is, the Bug only pushed out its head when no one was looking.</p>\n<p>This type of non-deterministic error generally involves three types of origin: multithread, time sensitivity, and dissynchrony between construction and cleaning of test data.</p>\n<p>Analyzing the body of the failed test, after several hours, of course, I began to strongly distrust the way we created timestamps with a native Java library. After all, the test seemed perfect to me, if there was an error it must have been somewhere else.</p>\n<h3>Confidence that avoids shame</h3>\n<p>But, aware of this lesson that we should trust our tools, especially since the component in question had been in Java for 9 years, I ignored this distrust. This saved me a lot of time and embarrassment, as I'm going to share that the error was elsewhere.</p>\n<p>Our test suite ran all tests in a single thread, so it wouldn't be a concurrency issue. But it also ran each test in a deterministic but unpredictable order. Therefore, the source of the intermittent problem must be in some specific order in which the tests were performed.</p>\n<p>After several hours of analyzing the logs, I was able to identify two tests that failed when run in sequence. It turned out that, although our tests performed a test data cleaning routine after each execution, a simple typo had silently overwritten the cleaning method in one of the tests, which generated data inconsistency if such tests were executed in a specific order.</p>\n<h2>Communication via Radio</h2>\n<h3>Q-code</h3>\n<p>I remember that one of the first systems I developed when I worked in the police was one to replace the sending of statistics through radio communication. Many years ago, each police station was supposed to send daily work statistics via radio. Data such as number of people and vehicles inspected, car accidents, etc.</p>\n<p>This took a lot of time as the audio quality of radio communications was not always ideal. The interlocutors spent a lot of time transmitting and confirming each piece of information. All this using Q-Code</p>\n<p>The Q-Code is a standardized collection of three-letter codes used in radio communication. The use of Q-code even in voice transmissions makes communication safer and more efficient. Each set of three letters, always starting with the letter Q, has a specific meaning that is known to the interlocutors.</p>\n<p>I could see that two of those codes were widely used among police officers in radio communication: QAP and QSL.</p>\n<p>QAP was used when you wanted to transmit a message. Let's say someone wanted to talk to me, so he said on the radio: \"Bruno, QAP?\". This could be translated as \"Bruno, are you ready to hear a message?\"</p>\n<p>My answer could be QAP or for example QRM. If I responded with QAP, I was signaling that yes, I was ready to receive the message. If you responded with QRM, I would be informing you that at that moment the communication is being interfered with.</p>\n<p>During communication, the second most used Q-Code appears, QSL. At the end of each message, the sender ends it with the QSL. This means that he is asking the receiver to confirm whether they received the message. It would be something like: \"There is a suspicious vehicle heading towards your team, QSL?\" If I had understood the entire message, I should respond with a simple \"QSL\". In the absence of a response, the sender repeats the message until receiving confirmation from the receiver.</p>\n<p>Each message is concluded with a QSL, and its reception is confirmed with a QSL. Does this remind you of any transmission control protocol out here, used on the internet?</p>\n<p>The main thing here is that a large amount of knowledge is condensed into three letters, in a language that provides interlocutors with efficiency and security. Eric Evans, the author of \"Domain-Driven Design: Tackling Complexity in the Heart of Software\", would agree with me that there is a principle here that should also be adopted in software development.</p>\n<h3>The Language and the Domain</h3>\n<p>A language specific to the domain, which considers possible interference from the environment, a ubiquitous language that is known by all interlocutors, can be the difference between life and death, between success and damnation of a project.</p>\n<p>When a project does not have its own language for that domain, this creates the need for numerous translations between interlocutors. Developers have to translate for domain experts. These, in turn, have to translate their demands to developers. Even among developers, there may be a need for translations.</p>\n<p>All these translations make concepts confusing and the consequences of a lack of mutual understanding can be disastrous.</p>\n<p>The importance of this in trying to arrest a Bug goes much further than compilation errors or exceptions. It goes through the swampy characteristic that the software may be logically working almost perfectly, but it is not delivering what was expected by the stakeholder.</p>\n<p>Let's look at the following pieces of code:</p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\"><span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>order<span class=\"token punctuation\">.</span>status <span class=\"token operator\">!=</span> completed<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n     <span class=\"token comment\">// (...)</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\"><span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>order<span class=\"token punctuation\">.</span><span class=\"token function\">isFullyRefunded</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n     <span class=\"token comment\">// (...)</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Here we have a small example of two ways of expressing the same situation. In the second piece of code, a common language between developers and domain experts was used. Here, possible logical errors can be easily noticed, without the need to keep in mind what the possible states of the Order are and what the expected state is for that case.</p>\n<p>See the following code:</p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\"><span class=\"token class-name\">Payment</span> newPayment <span class=\"token operator\">=</span> payment<span class=\"token punctuation\">.</span><span class=\"token function\">add</span><span class=\"token punctuation\">(</span><span class=\"token number\">10</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>What do you expect from this code? Does it add ten dollars to the payment? Ten transactions, inbound or outbound? Will the method create a new payment object or will it just change the value of the payment variable and create a new reference called newPayment?</p>\n<p>A lesson also taken from the book \"Clean Code: A HandBook of Agile Software Craftsmanship\" shows that clear communication must also take place between software developers. Functions must communicate exactly what they are doing.</p>\n<p>If you have to look at the function's implementation to know what it's actually doing, that's a big sign that you need to rename it.</p>\n<h2>Bug is in jail</h2>\n<p>I'm very grateful that you've made it this far, you've certainly learned a lot about police activity and how some of its principles can be applied to combat and remove Bugs from your software.</p>\n<p>By applying this knowledge you will be able to work more confidently in your code, giving you peace in your daily life and also allowing you to experiment and discover new things.</p>\n<p>Your aim will be improved and you will get straight to the point, avoiding damage instead of first looking for the culprits. You become bolder and go further because you know you can trust your tools. This leaves you more time to refine your code and seek excellence.</p>\n<p>Finally, not only will your code be safe and efficient, but its result will also be in line with what your customers expect because through effective communication you can accurately deliver what was demanded from you.</p>\n<p>The result of all this is that Bug is in jail, lives are no longer in danger, and you can go home at the end of your shift to enjoy the rest of the day with your family which is looking forward to welcoming their hero back.</p>","fields":{"slug":"/bug-police-officer/","tags":["debugging","testing","TDD","DDD"]}}},{"node":{"id":"d53c49b4-fba1-5071-b078-79bbf0f23344","frontmatter":{"category":"Engineering","title":"A wild Thread appeared! Multithreaded Testing and Thread-safety","date":"2023-02-24","summary":"Today we'll talk a little about how threads work on computers and how to extract more value from concurrent tasks. For this, I will present techniques on how to develop and especially how to test code that uses multiple threads, avoiding the main pitfalls that involve this theme. Of course, along the way, you'll also learn more about Java's Concurrent package, non-blocking algorithms, immutability, and more. However, we need to start by talking a little bit about butter.","thumbnail":null,"authorName":"Bruno Morais","authorDescription":"Bruno is a Senior Software Engineer at AUTO1 Group.","authorAvatar":{"relativePath":"pages/a-wild-thread-appeared-multithreaded-testing-and-thread-safety/avatar.jpeg","childImageSharp":{"resolutions":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAUABQDASIAAhEBAxEB/8QAGAABAQEBAQAAAAAAAAAAAAAAAAQDAQX/xAAXAQEBAQEAAAAAAAAAAAAAAAABAwIE/9oADAMBAAIQAxAAAAGmbSadPSZMPIBLBy1//8QAHBAAAwABBQAAAAAAAAAAAAAAAQIDIQAQERIj/9oACAEBAAEFAqOVEql2047LLDc7A+i5H//EABcRAQEBAQAAAAAAAAAAAAAAAAEAEBL/2gAIAQMBAT8BC5jP/8QAGREAAwADAAAAAAAAAAAAAAAAAAECEBET/9oACAECAQE/AW9HSSsf/8QAGhAAAQUBAAAAAAAAAAAAAAAAAQACEBEhQf/aAAgBAQAGPwLBZRa4VFYt5Jj/xAAcEAADAAIDAQAAAAAAAAAAAAAAAREhURAxYXH/2gAIAQEAAT8ho6G+i0ElVBP0c6AzfMaH3OHLLoTIz//aAAwDAQACAAMAAAAQcC98/8QAGREAAwADAAAAAAAAAAAAAAAAABExEFGB/9oACAEDAQE/EGQbRPcf/8QAGxEAAgIDAQAAAAAAAAAAAAAAAAERMVFhscH/2gAIAQIBAT8QuM2dElucejs//8QAGxABAQEBAAMBAAAAAAAAAAAAAREAITFBYXH/2gAIAQEAAT8QEiRCoPrgpVComQJxnQidLfOE1gCkvzQ9j4TPv80LcHh6dw+UV3//2Q==","width":50,"height":50,"src":"/static/8d7223890dda036e0121799406a35506/d2d31/avatar.jpeg","srcSet":"/static/8d7223890dda036e0121799406a35506/d2d31/avatar.jpeg 1x,\n/static/8d7223890dda036e0121799406a35506/0b804/avatar.jpeg 1.5x,\n/static/8d7223890dda036e0121799406a35506/753c3/avatar.jpeg 2x,\n/static/8d7223890dda036e0121799406a35506/31ca8/avatar.jpeg 3x"}}},"headerImage":null},"html":"<h1>A wild Thread appeared! Multithreaded Testing and Thread-safety</h1>\n<p><a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/0fc0ab78e60b645d61810b733618e058/a231e/wild_appeared.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 568px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 73.94366197183098%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAAAsSAAALEgHS3X78AAAC60lEQVQ4y4VTzU8TURDfszev/jV6MzHxaGLi0YsHSTDGaKBUY2LUGhC/QBCUSktrAWkLLVDaSkERTCr02wKlBftBMUDbLbu03RnnPdgGNOgkv8y8eTO/mZ15K9RqtX2C/C8oisI1AMiSLMuIyG2mD+8rpAuEZoEukBzI9Elg90yyuU0MhiIYCkdxKRjBdDaHqhwWvyuwYDKAgWxQ7T99lAObm3mIL6/C7Nw8DBqMYB91gry/D4eEEkHLCavVKhCYk+NoZ+ysauYTxTJ+GLKi0TSIU14f7knSUcKDDll1tXWFksrlMpYlmYKUOplKyEbY129Gg8GE0Vic5zJ/nZB5fiZXIBELY6kk4ox3HOdnxnHBacHMxro6n3qnlUoFI9EfGPi2gDvb238T6nuHUNfwCJy6x/iiTYcPHj7BtrZ2DLxrxWxylROycVRrhGqF2/VFKDU+rmOEugc6PH3qDGgabkHns1a413wHmm7egOeNVyG5HOfLYEmHYzkJrPsDwm7tfbx09gLoNC04+8mD3iEDfveO4RfPJP88Vfyhr+iasaF3zkkYR/fnUZyYtmImvw5ra0ncLexKFKYVLp+/jhfPXYH2xmvwtEUDrikf1KiqvF+BYrEIdrsdbDY7mC0m6HrTAa+7O0h3kn4FnV0v4ePIMFgsFszlctLeXlkrmE0WHDCYwdTfD/19b8HpdIDDMUZwkO2EkZERlqCQrbgmXYp7yq143B6u2dlqtdZcLpcyPDwsuiYnWgSfbxp3drahWCpBJpuDZDJ5bD7ssxcXFzEajWImk8FIhP6UUJCfE4lE/cmRX8rn8xphaWkJ11PrkM1mIR6Pw8rKCtBbA1EU+TKIEAqFAi+0tbVF81qDYDAIgUAANjY2gK+YJBaLSel0ulmgQPT7/VQ1hOFwGFOpFLIi7Mze3v9E/c8pXqY5Ngl6vX5vYGBANJvNosFgEFXbaDSWyOagOZZoOXXYbDYOsoukizRfsben59d7vf72b8fyJLW9nd3vAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n    ></span>\n    <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;box-shadow:inset 0px 0px 0px 400px white;\"\n        alt=\"wild-appeared\"\n        title=\"\"\n        src=\"/static/0fc0ab78e60b645d61810b733618e058/a231e/wild_appeared.png\"\n        srcset=\"/static/0fc0ab78e60b645d61810b733618e058/01db7/wild_appeared.png 148w,\n/static/0fc0ab78e60b645d61810b733618e058/ede92/wild_appeared.png 295w,\n/static/0fc0ab78e60b645d61810b733618e058/a231e/wild_appeared.png 568w\"\n        sizes=\"(max-width: 568px) 100vw, 568px\"\n      />\n  </span>\n  </a></p>\n<p>Today we'll talk a little about how threads work on computers and how to extract more value from concurrent tasks. For this, I will present techniques on how to develop and especially how to test code that uses multiple threads, avoiding the main pitfalls that involve this theme.</p>\n<p>Of course, along the way, you'll also learn more about Java's Concurrent package, non-blocking algorithms, immutability, and more. However, we need to start by talking a little bit about butter.</p>\n<p>Butter is a product that is part of everyday life for many people. Present in cookies, cakes, bread, sweets, and snacks, as well as other culinary items that make our mouths water just imagining.</p>\n<p>Butter is not recent; we have historical records of its manufacturing process over 2500 BC. Most often made with cow's milk but it can also be produced with the milk of other mammals such as sheep, goats, and buffalo.</p>\n<p>Salt has been added to butter since ancient times as a method of preservation, but over time salt has lost this importance as the supply chain has become generally refrigerated. Today, so to speak, salt is added only for taste.</p>\n<p>Sometimes food colorings are added to butter, in Brazil, for example, it is common to use Annatto seeds.</p>\n<p>And one thing I really like to eat is bread and butter. In fact, a delicious slice of bread just out of the oven with a little butter on top, which starts to melt on the hot bread. Oh, how delicious!</p>\n<p>Sadly, my wife happens to like hazelnut cream on top of her bread. And this created a problem with our breakfast, now we have to get two knives dirty to apply the toppings that we like. A knife for the butter, and another knife for the hazelnut cream.</p>\n<p>However, our concern for the environment and its natural resources, which are not unlimited, made us rethink this process.</p>\n<p>Let's turn this problem into a software. After all, Moore's law has given us processors with more and more cores, and as nowadays virtually all computers have multiple execution cores, a computer must be able to simulate my kitchen.</p>\n<p>First, we need a straightforward Bread that takes 50 milliseconds to be ready (what a blazing fast oven, huh!?)</p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\"><span class=\"token keyword\">public</span> <span class=\"token keyword\">class</span> <span class=\"token class-name\">Bread</span> <span class=\"token punctuation\">{</span>\n   <span class=\"token keyword\">private</span> <span class=\"token class-name\">String</span> name <span class=\"token operator\">=</span> <span class=\"token string\">\"bread\"</span><span class=\"token punctuation\">;</span>\n\n   <span class=\"token keyword\">public</span> <span class=\"token class-name\">Bread</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n       <span class=\"token keyword\">try</span> <span class=\"token punctuation\">{</span>\n           <span class=\"token class-name\">TimeUnit</span><span class=\"token punctuation\">.</span>MILLISECONDS<span class=\"token punctuation\">.</span><span class=\"token function\">sleep</span><span class=\"token punctuation\">(</span><span class=\"token number\">50</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n       <span class=\"token punctuation\">}</span> <span class=\"token keyword\">catch</span> <span class=\"token punctuation\">(</span><span class=\"token class-name\">InterruptedException</span> e<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n           <span class=\"token class-name\">Thread</span><span class=\"token punctuation\">.</span><span class=\"token function\">currentThread</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">interrupt</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n       <span class=\"token punctuation\">}</span>\n   <span class=\"token punctuation\">}</span>\n\n   <span class=\"token keyword\">public</span> <span class=\"token keyword\">void</span> <span class=\"token function\">setTopping</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">String</span> toppingName<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n       <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>name <span class=\"token operator\">+=</span> <span class=\"token string\">\" with \"</span> <span class=\"token operator\">+</span> toppingName<span class=\"token punctuation\">;</span>\n   <span class=\"token punctuation\">}</span>\n\n   <span class=\"token annotation punctuation\">@Override</span>\n   <span class=\"token keyword\">public</span> <span class=\"token class-name\">String</span> <span class=\"token function\">toString</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n       <span class=\"token keyword\">return</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>name<span class=\"token punctuation\">;</span>\n   <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Now we need a naive knife that can apply the topping to our bread.</p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\"><span class=\"token keyword\">public</span> <span class=\"token keyword\">class</span> <span class=\"token class-name\">Knife</span> <span class=\"token punctuation\">{</span>\n   <span class=\"token keyword\">private</span> <span class=\"token class-name\">String</span> topping<span class=\"token punctuation\">;</span>\n\n   <span class=\"token keyword\">public</span> <span class=\"token class-name\">Knife</span> <span class=\"token function\">setTopping</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">String</span> topping<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n       <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>topping <span class=\"token operator\">=</span> topping<span class=\"token punctuation\">;</span>\n       <span class=\"token keyword\">return</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">;</span>\n\n   <span class=\"token punctuation\">}</span>\n\n   <span class=\"token keyword\">public</span> <span class=\"token class-name\">Knife</span> <span class=\"token function\">applyToppingTo</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">Bread</span> bread<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n       <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>topping <span class=\"token operator\">!=</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n           bread<span class=\"token punctuation\">.</span><span class=\"token function\">setTopping</span><span class=\"token punctuation\">(</span>topping<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n           topping <span class=\"token operator\">=</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">;</span>\n       <span class=\"token punctuation\">}</span>\n       <span class=\"token keyword\">return</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">;</span>\n   <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>We can verify that everything is working using a test. I'm using the <a href=\"https://assertj.github.io/doc/\"><ins>AssertJ</ins></a> library, a java assertion library which I do recommend that you have a look on at, as it could enhance your tests and improve readability.</p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\"><span class=\"token annotation punctuation\">@Test</span>\n<span class=\"token keyword\">void</span> <span class=\"token function\">givenKnifeWhenApplyToppingToThenChangeBreadName</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n   <span class=\"token keyword\">var</span> knife <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Knife</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n   <span class=\"token keyword\">var</span> bread <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Bread</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n   knife<span class=\"token punctuation\">.</span><span class=\"token function\">setTopping</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"butter\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">applyToppingTo</span><span class=\"token punctuation\">(</span>bread<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n   <span class=\"token function\">assertThat</span><span class=\"token punctuation\">(</span>bread<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">hasToString</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"bread with butter\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>It seems good, lets's see what happens when we are hungry and want 10 pieces of bread made at the same time! For that, we will need a basket where we will put all the cooked bread.</p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\"><span class=\"token annotation punctuation\">@Test</span>\n<span class=\"token keyword\">void</span> <span class=\"token function\">givenHungryThenCook10BreadsAtTheSameTime</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n   <span class=\"token keyword\">var</span> basket <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">ArrayList</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">Bread</span><span class=\"token punctuation\">></span></span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n   <span class=\"token keyword\">var</span> knife <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Knife</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n   <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\">&lt;</span> <span class=\"token number\">10</span><span class=\"token punctuation\">;</span> i<span class=\"token operator\">++</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n       <span class=\"token keyword\">var</span> bread <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Bread</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n       knife<span class=\"token punctuation\">.</span><span class=\"token function\">setTopping</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"butter\"</span><span class=\"token punctuation\">)</span>\n               <span class=\"token punctuation\">.</span><span class=\"token function\">applyToppingTo</span><span class=\"token punctuation\">(</span>bread<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n       basket<span class=\"token punctuation\">.</span><span class=\"token function\">add</span><span class=\"token punctuation\">(</span>bread<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n   <span class=\"token punctuation\">}</span>\n   <span class=\"token function\">assertThat</span><span class=\"token punctuation\">(</span>basket<span class=\"token punctuation\">)</span>\n           <span class=\"token punctuation\">.</span><span class=\"token function\">isNotEmpty</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n           <span class=\"token punctuation\">.</span><span class=\"token function\">allSatisfy</span><span class=\"token punctuation\">(</span>bread <span class=\"token operator\">-></span> <span class=\"token function\">assertThat</span><span class=\"token punctuation\">(</span>bread<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">hasToString</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"bread with butter\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Oops!, it worked, but it took too much time. Each bread takes 50 milliseconds to be ready, so now the whole process is taking 500 milliseconds. If we consider the real-world cook time for bread, it could take hours to cook all those pieces of bread like this.</p>\n<h2>Multiple Threads</h2>\n<p>I know what to do, we just need more workforce! I will call my wife to help me. As I said, the majority of current computer machines have more than one core, which allows us to work in parallel. Joshua Bloch, in his book Effective Java, warns that we should prefer executors, tasks, and streams to threads, but for simplicity let me demonstrate this problem using threads by hand.</p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\"><span class=\"token annotation punctuation\">@Test</span>\n<span class=\"token keyword\">void</span> <span class=\"token function\">givenHungryThenCook10BreadsWithMyWife</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n   <span class=\"token keyword\">var</span> basket <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">ArrayList</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">Bread</span><span class=\"token punctuation\">></span></span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n   <span class=\"token keyword\">var</span> knife <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Knife</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n   <span class=\"token class-name\">Runnable</span> preparation <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">-></span> <span class=\"token punctuation\">{</span>\n       <span class=\"token keyword\">var</span> bread <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Bread</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n       knife<span class=\"token punctuation\">.</span><span class=\"token function\">setTopping</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"butter\"</span><span class=\"token punctuation\">)</span>\n               <span class=\"token punctuation\">.</span><span class=\"token function\">applyToppingTo</span><span class=\"token punctuation\">(</span>bread<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n       basket<span class=\"token punctuation\">.</span><span class=\"token function\">add</span><span class=\"token punctuation\">(</span>bread<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n   <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n   <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\">&lt;</span> <span class=\"token number\">5</span><span class=\"token punctuation\">;</span> i<span class=\"token operator\">++</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n       <span class=\"token keyword\">var</span> me <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Thread</span><span class=\"token punctuation\">(</span>preparation<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n       <span class=\"token keyword\">var</span> myWife <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Thread</span><span class=\"token punctuation\">(</span>preparation<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n       me<span class=\"token punctuation\">.</span><span class=\"token function\">start</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n       myWife<span class=\"token punctuation\">.</span><span class=\"token function\">start</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n   <span class=\"token punctuation\">}</span>\n   <span class=\"token function\">assertThat</span><span class=\"token punctuation\">(</span>basket<span class=\"token punctuation\">)</span>\n           <span class=\"token punctuation\">.</span><span class=\"token function\">isNotEmpty</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n           <span class=\"token punctuation\">.</span><span class=\"token function\">allSatisfy</span><span class=\"token punctuation\">(</span>bread <span class=\"token operator\">-></span> <span class=\"token function\">assertThat</span><span class=\"token punctuation\">(</span>bread<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">hasToString</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"bread with butter\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>But wait, the test is failing, what is going wrong?</p>\n<div class=\"gatsby-highlight\" data-language=\"tex\"><pre class=\"language-tex\"><code class=\"language-tex\">java.lang.AssertionError: \nExpecting actual not to be empty</code></pre></div>\n<p>It is like the basket is empty, but we didn't change the process at all despite adding the new threads. Yes, it is a common problem that every software engineer faces when starting to work with multiple threads (or multi-thread apps).</p>\n<h2>Java's Concurrent Package</h2>\n<p>In fact, there is a thread that is responsible for running the test suite which executes each step on our test in sequential order. But when we delegate part of the process to other threads, it follows its flow without waiting for them to finish their job. When it reaches the assertion, the previously created threads have not finished creating their bread. That is why our basket is empty.</p>\n<p>Please, don't listen to this evil inner thought suggesting that it is just a matter of creating a Thread.sleep() or something like that, so that the assertion waits for the other threads. It will give you a slow and fragile test. On one hand, if you give it a big delay time, it will slow down your tests. On the other hand, with a small delay, the result could vary depending on the processing power of the machine where the tests are being executed.</p>\n<h3>Testing</h3>\n<p>The answer for cases like those is to use some tools from java's concurrent package. We have to ensure that both workers start to do their job at the same time. As a second requirement, we need that the test thread verifies the assertion only after the job is done by the other threads. For this, we can use a CountDownLatch like those below. CountDownLatch is a synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes. It does it by holding the thread until the count reaches 0.</p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\"><span class=\"token annotation punctuation\">@Test</span>\n<span class=\"token keyword\">void</span> <span class=\"token function\">givenHungryThenCook10BreadsWithMyWife</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">throws</span> <span class=\"token class-name\">InterruptedException</span> <span class=\"token punctuation\">{</span>\n   <span class=\"token keyword\">var</span> basket <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">ArrayList</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">Bread</span><span class=\"token punctuation\">></span></span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n   <span class=\"token keyword\">var</span> knife <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Knife</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n   <span class=\"token keyword\">var</span> startGate <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">CountDownLatch</span><span class=\"token punctuation\">(</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n   <span class=\"token keyword\">var</span> endGate <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">CountDownLatch</span><span class=\"token punctuation\">(</span><span class=\"token number\">10</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n   <span class=\"token class-name\">Runnable</span> preparation <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">-></span> <span class=\"token punctuation\">{</span>\n       <span class=\"token keyword\">try</span> <span class=\"token punctuation\">{</span>\n           startGate<span class=\"token punctuation\">.</span><span class=\"token function\">await</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n       <span class=\"token punctuation\">}</span> <span class=\"token keyword\">catch</span> <span class=\"token punctuation\">(</span><span class=\"token class-name\">InterruptedException</span> e<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n           <span class=\"token keyword\">throw</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">RuntimeException</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n       <span class=\"token punctuation\">}</span>\n       <span class=\"token keyword\">var</span> bread <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Bread</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n       knife<span class=\"token punctuation\">.</span><span class=\"token function\">setTopping</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"butter\"</span><span class=\"token punctuation\">)</span>\n               <span class=\"token punctuation\">.</span><span class=\"token function\">applyToppingTo</span><span class=\"token punctuation\">(</span>bread<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n       basket<span class=\"token punctuation\">.</span><span class=\"token function\">add</span><span class=\"token punctuation\">(</span>bread<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n       endGate<span class=\"token punctuation\">.</span><span class=\"token function\">countDown</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n   <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n   <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\">&lt;</span> <span class=\"token number\">5</span><span class=\"token punctuation\">;</span> i<span class=\"token operator\">++</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n       <span class=\"token keyword\">var</span> me <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Thread</span><span class=\"token punctuation\">(</span>preparation<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n       <span class=\"token keyword\">var</span> myWife <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Thread</span><span class=\"token punctuation\">(</span>preparation<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n       me<span class=\"token punctuation\">.</span><span class=\"token function\">start</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n       myWife<span class=\"token punctuation\">.</span><span class=\"token function\">start</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n   <span class=\"token punctuation\">}</span>\n\n   startGate<span class=\"token punctuation\">.</span><span class=\"token function\">countDown</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n   endGate<span class=\"token punctuation\">.</span><span class=\"token function\">await</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n   <span class=\"token function\">assertThat</span><span class=\"token punctuation\">(</span>basket<span class=\"token punctuation\">)</span>\n           <span class=\"token punctuation\">.</span><span class=\"token function\">hasSize</span><span class=\"token punctuation\">(</span><span class=\"token number\">10</span><span class=\"token punctuation\">)</span>\n           <span class=\"token punctuation\">.</span><span class=\"token function\">allSatisfy</span><span class=\"token punctuation\">(</span>bread <span class=\"token operator\">-></span> <span class=\"token function\">assertThat</span><span class=\"token punctuation\">(</span>bread<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">hasToString</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"bread with butter\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>The startGate will hold all threads so that they start virtually at the same time when the test execution reaches the startGate.countDown(). After that, the assertion will not be verified before the endGate reaches zero, which will only happen when all threads have finished their tasks.</p>\n<p>The bad news is that we have a problem with this current implementation. If you are unlucky enough (or simply repeat this test a few times), you will face the following error:</p>\n<div class=\"gatsby-highlight\" data-language=\"tex\"><pre class=\"language-tex\"><code class=\"language-tex\">java.lang.AssertionError: \nExpected size:&lt;10&gt; but was:&lt;6&gt; in:\n&lt;[bread with butter,\n    bread with butter,\n    bread with butter,\n    bread with butter,\n    bread with butter,\n    bread with butter]&gt;</code></pre></div>\n<p>It happened because we are using as our basket an ArrayList, which states in its documentation:</p>\n<p>\"<em>Note that this implementation <strong>is not synchronized</strong>. If multiple threads access an ArrayList instance concurrently, and at least one of the threads modifies the list structurally, it must be synchronized externally.</em>\"</p>\n<h3>Synchronized Collections</h3>\n<p>In other words, this implementation of the List interface is not thread-safe. Once more, to face this issue, we have at our disposal other collection implementations on the concurrent package. Instead of ArrayList, we could use CopyOnWriteArrayList or a ConcurrentLinkedQueue.</p>\n<p>As the first one is more efficient in use cases where mutations are less frequent than other operations, let's stick with ConcurrentLinkedQueue.</p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\"><span class=\"token keyword\">var</span> basket <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">ConcurrentLinkedQueue</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token punctuation\">></span></span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>But as soon as you execute the test repeatedly, you will see errors like those:</p>\n<div class=\"gatsby-highlight\" data-language=\"tex\"><pre class=\"language-tex\"><code class=\"language-tex\">java.lang.AssertionError: \nExpecting all elements of:\n  &lt;[bread with butter,\n    bread with butter,\n    bread with butter,\n    bread with butter,\n    bread with null,\n    bread with null,\n    bread with butter,\n    bread with butter,\n    bread with butter,\n    bread with butter]&gt;\nto satisfy given requirements, but these elements did not:\n\n  &lt;bread with null&gt; \nExpecting actual&#39;s toString() to return:\n  &lt;&quot;bread with butter&quot;&gt;\nbut was:\n  &lt;bread with null&gt;</code></pre></div>\n<p>We should have a problem in another part of the code, could you imagine where it is?</p>\n<p>Things get worse when my wife starts to make her bread with hazelnut cream:</p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\"><span class=\"token annotation punctuation\">@Test</span>\n<span class=\"token keyword\">void</span> <span class=\"token function\">givenHungryThenCook10BreadsWithMyWife</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">throws</span> <span class=\"token class-name\">InterruptedException</span> <span class=\"token punctuation\">{</span>\n   <span class=\"token keyword\">var</span> basket <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">ConcurrentLinkedQueue</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token punctuation\">></span></span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n   <span class=\"token keyword\">var</span> knife <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Knife</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n   <span class=\"token keyword\">var</span> startGate <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">CountDownLatch</span><span class=\"token punctuation\">(</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n   <span class=\"token keyword\">var</span> endGate <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">CountDownLatch</span><span class=\"token punctuation\">(</span><span class=\"token number\">10</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n   <span class=\"token class-name\">Function</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">String</span><span class=\"token punctuation\">,</span> <span class=\"token class-name\">Runnable</span><span class=\"token punctuation\">></span></span> preparation <span class=\"token operator\">=</span> topping <span class=\"token operator\">-></span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">-></span> <span class=\"token punctuation\">{</span>\n       <span class=\"token keyword\">try</span> <span class=\"token punctuation\">{</span>\n           startGate<span class=\"token punctuation\">.</span><span class=\"token function\">await</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n       <span class=\"token punctuation\">}</span> <span class=\"token keyword\">catch</span> <span class=\"token punctuation\">(</span><span class=\"token class-name\">InterruptedException</span> e<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n           <span class=\"token keyword\">throw</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">RuntimeException</span><span class=\"token punctuation\">(</span>e<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n       <span class=\"token punctuation\">}</span>\n       <span class=\"token keyword\">var</span> bread <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Bread</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n       knife<span class=\"token punctuation\">.</span><span class=\"token function\">setTopping</span><span class=\"token punctuation\">(</span>topping<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">applyToppingTo</span><span class=\"token punctuation\">(</span>bread<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n       basket<span class=\"token punctuation\">.</span><span class=\"token function\">add</span><span class=\"token punctuation\">(</span>bread<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n       endGate<span class=\"token punctuation\">.</span><span class=\"token function\">countDown</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n   <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\n   <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\">&lt;</span> <span class=\"token number\">5</span><span class=\"token punctuation\">;</span> i<span class=\"token operator\">++</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n       <span class=\"token keyword\">var</span> me <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Thread</span><span class=\"token punctuation\">(</span>preparation<span class=\"token punctuation\">.</span><span class=\"token function\">apply</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"butter\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n       me<span class=\"token punctuation\">.</span><span class=\"token function\">start</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n       <span class=\"token keyword\">var</span> myWife <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Thread</span><span class=\"token punctuation\">(</span>preparation<span class=\"token punctuation\">.</span><span class=\"token function\">apply</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"hazelnut cream\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n       myWife<span class=\"token punctuation\">.</span><span class=\"token function\">start</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n   <span class=\"token punctuation\">}</span>\n\n   startGate<span class=\"token punctuation\">.</span><span class=\"token function\">countDown</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n   endGate<span class=\"token punctuation\">.</span><span class=\"token function\">await</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n   <span class=\"token function\">assertThat</span><span class=\"token punctuation\">(</span>basket<span class=\"token punctuation\">)</span>\n           <span class=\"token punctuation\">.</span><span class=\"token function\">hasSize</span><span class=\"token punctuation\">(</span><span class=\"token number\">10</span><span class=\"token punctuation\">)</span>\n           <span class=\"token punctuation\">.</span><span class=\"token function\">haveExactly</span><span class=\"token punctuation\">(</span><span class=\"token number\">5</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Condition</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token punctuation\">></span></span><span class=\"token punctuation\">(</span>bread <span class=\"token operator\">-></span> bread<span class=\"token punctuation\">.</span><span class=\"token function\">toString</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">contains</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"butter\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"butter bread\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n           <span class=\"token punctuation\">.</span><span class=\"token function\">haveExactly</span><span class=\"token punctuation\">(</span><span class=\"token number\">5</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Condition</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token punctuation\">></span></span><span class=\"token punctuation\">(</span>bread <span class=\"token operator\">-></span> bread<span class=\"token punctuation\">.</span><span class=\"token function\">toString</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">contains</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"hazelnut\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"hazelnutcream bread\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>First, notice the use of a new helper method from AssertJ, we specified that the collection should have exactly 5 items that satisfy a condition.</p>\n<p>The Condition entity from the AssertJ library helps us to create a whole new set of assertions. If you are interested, please take a look at a delicious example in the appendix of this article.</p>\n<p>But let's come back to our bread story. After executing the test now with hazelnut cream, sometimes we face errors that are even strange:</p>\n<div class=\"gatsby-highlight\" data-language=\"tex\"><pre class=\"language-tex\"><code class=\"language-tex\">java.lang.AssertionError: \nExpecting elements:\n&lt;[bread with hazelnut cream,\n    bread with hazelnut cream,\n    bread with hazelnut cream,\n    bread with hazelnut cream,\n    bread with butter,\n    bread with hazelnut cream,\n    bread with butter,\n    bread with butter,\n    bread with hazelnut cream,\n    bread with hazelnut cream]&gt;\n to have exactly 5 times &lt;butter bread&gt;</code></pre></div>\n<p>Why do we have only 3 bread with butter, but 7 bread with hazelnut cream?</p>\n<h2>Summary so far</h2>\n<p>Before advancing, let's recap what we have seen until now:</p>\n<ul>\n<li>\n<p>Most today's computers have multiple cores, allowing us to get even more value from concurrent tasks;</p>\n</li>\n<li>\n<p>Working with multiple threads creates some difficulties when we depend on timing to verify our tests' assertions, nothing that couldn't be handled using tools from java's Concurrent package, like CountDownLatch;</p>\n</li>\n<li>\n<p>AssertJ is a java assertion library that helps us to improve our tests also on their readability.</p>\n</li>\n<li>\n<p>We should keep in mind that not all classes are thread-safe, like ArrayList for example. When many threads will share access to a common collection, we should use one of the thread-safe Collection implementations from the Concurrent package;</p>\n</li>\n</ul>\n<p>Ok, with all that knowledge in mind let's figure out what is the reason for the weird errors that we are facing.</p>\n<h2>Thread-safety</h2>\n<h3>Race Condition</h3>\n<p>First of all, this is a typical symptom of a Race Condition, or more specifically, a Data Race. Quoting Brian Goetz, in the book Java Concurrency in Practice</p>\n<p>\"<em>A race condition occurs when the correctness of a computation depends on the relative timing or interleaving of multiple threads by the runtime; in other words, when getting the right answer relies on lucky timing.</em>\"</p>\n<p>On our baking issue, we have multiple threads fighting to access the same shared property. My wife and I are fighting for toppings at the same knife.</p>\n<p>In the real world, one could think of it like this:</p>\n<ol>\n<li>\n<p>I get my knife and put butter on that;</p>\n</li>\n<li>\n<p>Just when I leave the knife to take the bread, my wife gets that knife and puts hazelnut cream on it;</p>\n</li>\n<li>\n<p>I take back the knife and, with tears in my eyes, realize that I'm topping my bread with some strange brown cream;</p>\n</li>\n<li>\n<p>Now my wife with her bread in hand stares at an empty knife, trying to figure out who is sabotaging her.</p>\n</li>\n</ol>\n<p><a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/1ff9d1c27bf3ef283302379138cd5bed/f680c/Race-Condition.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 420px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 70.95238095238095%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAAAsSAAALEgHS3X78AAACJElEQVQ4y21TyY7TQBDNJ/EjCPEViAtXOCEOiOXGjobRhJFgBpGQ3fHSbXe3ux3b8WQYBBckLnxJPbqdzZ5weKpyLa+2dsefTIgHnPwZp2DWlDGFHqfxSNL7jxUdnS5pMhIUeGvfNobNGZ1/NTQYpMS9KXVUFFEhNDxviZlFU24xmVYYjFdr+7wdFwYFuue/0BteYZFE6ER+RB/mPyCFomWaUKEElamo5RalRaVjWghZo1Rtv8tbakEiZNThvk/B9AiCM9KJQX94AR5lWEiJTKgaTvfnOb70LyG5bvkcTB2TQkYMHc+P6Y1XYhwZKm1gFCyQxmkrKVcSLMwQ+Hltv14sE86m1oRJEFImjTOSc7rkw4S1LBq+vEXcIBRhRMZUyKR2+2kRXe+m6XOjq90kDUI2m9PrkzMEVhZpWjvzTcJoYi85K6CTfaf1+EGGs953CGbq2BahN/ao+/YRhv0+ldrYBe+7Go4rTGdle5+bYm7X/x2Z2UfdjX9jygt7FNEIkDDJXs/EFutu27tu7tAeZaViFDKh3RHknmix0bdJmZAH+zy8sjLQsSbnMPavqYPtu8pTXQc65KlZ6yptdCtbxTaEEalwYY2ajCzwp3yIv9U9VPkKT+/cxPO7t3B1+RPdZw9w//YNaM52hXJL7uD0wkrFODrh1CMZJfaDkWQCF/IYlTyxj1vg88sn6B2/ck8K37rv8OnFY8gwRMrjOrkJZ+NzH/8AC+N/l13ojqEAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n    ></span>\n    <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;box-shadow:inset 0px 0px 0px 400px white;\"\n        alt=\"Race-Condition\"\n        title=\"\"\n        src=\"/static/1ff9d1c27bf3ef283302379138cd5bed/f680c/Race-Condition.png\"\n        srcset=\"/static/1ff9d1c27bf3ef283302379138cd5bed/4c3b3/Race-Condition.png 148w,\n/static/1ff9d1c27bf3ef283302379138cd5bed/d72a6/Race-Condition.png 295w,\n/static/1ff9d1c27bf3ef283302379138cd5bed/f680c/Race-Condition.png 420w\"\n        sizes=\"(max-width: 420px) 100vw, 420px\"\n      />\n  </span>\n  </a></p>\n<p>It could only work if each one of us does the topping at the perfect timing, that is, only getting the knife when the work of the other one is done.</p>\n<p><a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/9eb569fa960bd58a894af409fce7ccca/f680c/Race-Condition-Lucky-timming.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 420px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 70.95238095238095%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAAAsSAAALEgHS3X78AAACKklEQVQ4y3VSy47TQBDMt/Ax/AcnjnBHSFwBiQMs4iGR5UACyZJsYo8f47E9Mx4/kpDdRUJCe0f8RhczdhI57O6h1D1d45ruag/C5ZJEJCj0BUV+FzukFDNBi3NJ70439P7zmpbneVtzXLS7kwQJjSeGZjNNgnk0UJxTkxdgbA3fgu2wz4NgjaW3wXyxhedvDvz+Thw1GI5/YTq/QpVxDHjI6WPwEzJXtNYZNSqnlXbocpOpNnfcyp6bW+C4dZFTHic0EGFIkfcBuUioyAzO5j+QcgOdanz7fgHfb1ArCZMrlHfAcZXUkDzBgIUpnbAVFtzQSkrwqEKRadjOWjEnXNl6X6B/7nJpo+oEsyimUhpXJEe6blzs532Rfayl7An3BPOYkzEblLKgKpd3dlHJY3EpCqhD9z3BxA/ozacRIhsbrXfkzRHDoLab3iCz/oq4xJfpJfLEtJ0eCbIFo+HbZ5ifndGqMNbgjnTYC7qPEisymW1bT5Xtznl968iJ/amH6TU80dil5Df86sNkPX/t3ds9tEvZqhSNzKgTOfaw2l0ue7HFf7XjLSuDItXUvaZxM9qOtOmsUPqQ16o4PNAT5KTiyo5TUq0U/mwf4rp5YTuo8Xf7AL/rV6iLC/DZVzy6fw9sfApvNMRjmyfzKVambqdo7EMqERjEHiPJU3cgLTgu1QmabAItElyp16jTSbuIyH48fP4EwluCTUY4ffkUKfMtl7VCWqQQQYh/P3d/SRDg4P0AAAAASUVORK5CYII='); background-size: cover; display: block;\"\n    ></span>\n    <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;box-shadow:inset 0px 0px 0px 400px white;\"\n        alt=\"Race-Condition-Lucky-timming\"\n        title=\"\"\n        src=\"/static/9eb569fa960bd58a894af409fce7ccca/f680c/Race-Condition-Lucky-timming.png\"\n        srcset=\"/static/9eb569fa960bd58a894af409fce7ccca/4c3b3/Race-Condition-Lucky-timming.png 148w,\n/static/9eb569fa960bd58a894af409fce7ccca/d72a6/Race-Condition-Lucky-timming.png 295w,\n/static/9eb569fa960bd58a894af409fce7ccca/f680c/Race-Condition-Lucky-timming.png 420w\"\n        sizes=\"(max-width: 420px) 100vw, 420px\"\n      />\n  </span>\n  </a></p>\n<p>About our code, we have at least two problems in it: 1) we set the topping and add it to the bread in two different steps; and 2) when we add the topping to the bread, its removal from the knife also occurs in a separate step.</p>\n<p>Because of that, just before a thread applies the topping to the bread, another thread could change the topping or even remove it. And again, just before removing the topping from the knife, another thread could use that knife to add topping to other bread.</p>\n<p>That is why in the last two test logs we got some bread without topping, and more bread with one of the toppings than the other.</p>\n<h3>Atomicity</h3>\n<p>We wrote those naive classes just to enlighten the lack of atomicity in them, but even single-line codes like <code class=\"language-text\">++i</code> are not atomic, in fact, it comprehends three operations: 1) get the value; 2) add one to it; and 3) update the value back.</p>\n<p>What we should do is enforce the concept of atomicity, which means that each of our tasks should be considered as one. One indivisible task, an atom.</p>\n<p>Java has a built-in mechanism that allows us to achieve atomicity, which is called “synchronized block”.</p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\"><span class=\"token keyword\">synchronized</span><span class=\"token punctuation\">(</span>lock<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n\t<span class=\"token comment\">// Code that handles the shared memory</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>We can use any java object to act as a lock, and it will ensure that only one thread that acquires that lock will be able to execute the code within. When the thread finishes its job, it releases that lock so that other threads could do the same thing.</p>\n<p>It is also allowed to create a synchronized method, just by adding the synchronized keyword before the return type of the method. Doing so, the lock will be the object on which the method is being invoked.</p>\n<p>Ok, let's stop talking, and let's get our hands dirty!</p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\"><span class=\"token annotation punctuation\">@Test</span>\n<span class=\"token keyword\">void</span> <span class=\"token function\">givenHungryThenCook10BreadsWithMyWife</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">throws</span> <span class=\"token class-name\">InterruptedException</span> <span class=\"token punctuation\">{</span>\n   <span class=\"token keyword\">var</span> basket <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">ConcurrentLinkedQueue</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token punctuation\">></span></span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n   <span class=\"token keyword\">var</span> knife <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Knife</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n   <span class=\"token keyword\">var</span> startGate <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">CountDownLatch</span><span class=\"token punctuation\">(</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n   <span class=\"token keyword\">var</span> endGate <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">CountDownLatch</span><span class=\"token punctuation\">(</span><span class=\"token number\">10</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n   <span class=\"token class-name\">Function</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">String</span><span class=\"token punctuation\">,</span> <span class=\"token class-name\">Runnable</span><span class=\"token punctuation\">></span></span> preparation <span class=\"token operator\">=</span> topping <span class=\"token operator\">-></span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">-></span> <span class=\"token punctuation\">{</span>\n       <span class=\"token keyword\">try</span> <span class=\"token punctuation\">{</span>\n           startGate<span class=\"token punctuation\">.</span><span class=\"token function\">await</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n       <span class=\"token punctuation\">}</span> <span class=\"token keyword\">catch</span> <span class=\"token punctuation\">(</span><span class=\"token class-name\">InterruptedException</span> e<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n           <span class=\"token keyword\">throw</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">RuntimeException</span><span class=\"token punctuation\">(</span>e<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n       <span class=\"token punctuation\">}</span>\n       <span class=\"token keyword\">synchronized</span> <span class=\"token punctuation\">(</span>knife<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n           <span class=\"token keyword\">var</span> bread <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Bread</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n           knife<span class=\"token punctuation\">.</span><span class=\"token function\">setTopping</span><span class=\"token punctuation\">(</span>topping<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">applyToppingTo</span><span class=\"token punctuation\">(</span>bread<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n           basket<span class=\"token punctuation\">.</span><span class=\"token function\">add</span><span class=\"token punctuation\">(</span>bread<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n           endGate<span class=\"token punctuation\">.</span><span class=\"token function\">countDown</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n       <span class=\"token punctuation\">}</span>\n   <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\n   <span class=\"token comment\">// (...) omitted for brevity</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Now the fix of our code is just a matter of adding a synchronized block using the knife as the lock. With this, only one thread at a time can take the knife and execute the code inside it.</p>\n<h3>Thread blocking</h3>\n<p>\"Oh! This is the solution for everything, we should synchronize everything!\" Think twice.  Synchronization isn't for free; it creates a performance problem, as now all other threads are blocked waiting for the availability of the lock, which in our case is the knife.</p>\n<p>In our kitchen, we could say that when my wife touches the knife I become blocked, waiting for her. If the phone rings, she should say: \"darling, please answer the phone\". But I will be blocked, I'll not be able to do anything except wait for her to leave the knife.</p>\n<p>A blocked thread goes to the TIMED_WAITING state, and during this time it can not be used. It is really advisable to keep track of how many threads our applications are using because threads are a scarce resource.</p>\n<p>But there is light at the end of the tunnel, at least in this concern you should know that Java 19 is coming up with the concept of <a href=\"https://blogs.oracle.com/javamagazine/post/java-loom-virtual-threads-platform-threads\"><ins>Virtual threads</ins></a>, in its Project Loom. This new feature will cut the one-to-one relationship between Java threads and OS threads, which means that more than one Java virtual thread will be able to use the same OS thread. With that, when some virtual thread gets blocked by an I/O operation, for example, another virtual thread can perform calculations on that same OS thread.</p>\n<p>But, as we said, until there we should use our threads with wisdom.</p>\n<h3>Nonblocking Algorithms</h3>\n<p>\"But, what to do?\", you could ask. Well, if you need better performance you can use Nonblocking Synchronization. Nonblocking algorithms are widely used by JVMs implementations, Operational Systems, and in Java itself to implement locks and other concurrent data structures.</p>\n<p>Those Nonblocking algorithms are way more complicated to design and implement, but they provide better performance by avoiding the thread block itself and give us other benefits like being immune to Deadlock.</p>\n<p>To provide a simple example of Deadlock, imagine that my wife and I are in the living room. The remote controller of the TV and the sofa are Locks. To watch TV, a person needs to sit on the sofa and press the button on the remote controller. A Deadlock would occur if I get the remote controller and my wife sits on the sofa. She will be blocked waiting for the remote controller, and I'll be blocked waiting for the sofa. And we will be like that \"until death does us part.\"</p>\n<p>Let's go back to the Nonblocking algorithm. First of all, we need a way to ensure atomicity to our tasks. And it is possible because modern computer processors have special instructions for managing access to shared data. A common approach is the implementation of the compare-and-swap (CAS) instruction. It guarantees us that the access to the value and its update will occur as a single task.</p>\n<p>Java's Concurrent package provides us with some so-called atomic classes. Let's take AtomicInteger as an example, its documentation states that it is \"An int value that may be updated atomically\".</p>\n<p>The following code shows us the same algorithm, but only the last one achieves thread-safe by delegating its thread-safety to an AtomicInteger:</p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\"><span class=\"token keyword\">class</span> <span class=\"token class-name\">Counter</span> <span class=\"token punctuation\">{</span>\n   <span class=\"token keyword\">private</span> <span class=\"token class-name\">Integer</span> count <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span>\n\n   <span class=\"token keyword\">public</span> <span class=\"token keyword\">void</span> <span class=\"token function\">incrementCount</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n       <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>count <span class=\"token operator\">=</span> count <span class=\"token operator\">+</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span>\n   <span class=\"token punctuation\">}</span>\n\n   <span class=\"token keyword\">public</span> <span class=\"token keyword\">int</span> <span class=\"token function\">getCount</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n       <span class=\"token keyword\">return</span> count<span class=\"token punctuation\">;</span>\n   <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">class</span> <span class=\"token class-name\">ThreadSafeCounter</span> <span class=\"token punctuation\">{</span>\n   <span class=\"token keyword\">private</span> <span class=\"token class-name\">AtomicInteger</span> count <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">AtomicInteger</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n   <span class=\"token keyword\">public</span> <span class=\"token keyword\">void</span> <span class=\"token function\">incrementCount</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n       <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>count<span class=\"token punctuation\">.</span><span class=\"token function\">incrementAndGet</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n   <span class=\"token punctuation\">}</span>\n\n   <span class=\"token keyword\">public</span> <span class=\"token keyword\">int</span> <span class=\"token function\">getCount</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n       <span class=\"token keyword\">return</span> count<span class=\"token punctuation\">.</span><span class=\"token function\">get</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n   <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>And how does AtomicInteger ensure atomicity? Using the CAS algorithm! Its incrementAndGet method executes a code that could be simplified like this:</p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\"><span class=\"token keyword\">private</span> <span class=\"token keyword\">int</span> value<span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">public</span> <span class=\"token keyword\">final</span> <span class=\"token keyword\">int</span> <span class=\"token function\">incrementAndGet</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> expectedValue<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n   <span class=\"token keyword\">int</span> oldValue<span class=\"token punctuation\">;</span>\n   <span class=\"token keyword\">do</span> <span class=\"token punctuation\">{</span>\n       oldValue <span class=\"token operator\">=</span> value<span class=\"token punctuation\">;</span>\n   <span class=\"token punctuation\">}</span> <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span><span class=\"token function\">compareAndSetInt</span><span class=\"token punctuation\">(</span>oldValue<span class=\"token punctuation\">,</span> oldValue <span class=\"token operator\">+</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n   <span class=\"token keyword\">return</span> oldValue<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>To start, it gets the current value and stores it in a local variable. Then using the compareAndSetInt method it first checks if, at that precise moment, the current value is the same that was earlier fetched. If it is so, it proceeds with the update and then returns True. If the current value was changed by another thread, the compareAndSetInt method returns False and restarts the process.</p>\n<p>It is worth saying that the compareAndSetInt method is a native method, which uses the most efficient instructions provided by the underlying hardware.</p>\n<p>With this new knowledge, what about trying it on our bread? Let's remove the blocking synchronization and create the faster bread with butter that a computer could have (and some with hazelnut cream too, for the sake of my wife's happiness). We can do this using an AtomicReference.</p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\"><span class=\"token keyword\">public</span> <span class=\"token keyword\">class</span> <span class=\"token class-name\">Knife</span> <span class=\"token punctuation\">{</span>\n   <span class=\"token keyword\">private</span> <span class=\"token keyword\">final</span> <span class=\"token class-name\">AtomicReference</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">String</span><span class=\"token punctuation\">></span></span> topping <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">AtomicReference</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token punctuation\">></span></span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n   <span class=\"token keyword\">public</span> <span class=\"token class-name\">Knife</span> <span class=\"token function\">setTopping</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">String</span> topping<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n       <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>topping<span class=\"token punctuation\">.</span><span class=\"token function\">compareAndSet</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">null</span><span class=\"token punctuation\">,</span> topping<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span>\n       <span class=\"token keyword\">return</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">;</span>\n   <span class=\"token punctuation\">}</span>\n\n   <span class=\"token keyword\">public</span> <span class=\"token class-name\">Knife</span> <span class=\"token function\">applyToppingTo</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">Bread</span> bread<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n       <span class=\"token class-name\">String</span> currentTopping<span class=\"token punctuation\">;</span>\n       <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span>currentTopping <span class=\"token operator\">=</span> topping<span class=\"token punctuation\">.</span><span class=\"token function\">getAndUpdate</span><span class=\"token punctuation\">(</span>s <span class=\"token operator\">-></span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">!=</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span>\n           bread<span class=\"token punctuation\">.</span><span class=\"token function\">setTopping</span><span class=\"token punctuation\">(</span>currentTopping<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n       <span class=\"token keyword\">return</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">;</span>\n   <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Of course, we did that after removing the synchronized block from our test. Good, fast, and easy, and without thread blocking! But, please pay close attention to this piece of code. We have some problems there as it is some kind of adaptation of the canonical CAS algorithm.</p>\n<p>The hard part of building nonblocking algorithms is to isolate the shared memory into an atomic single change. But in our baker issue, we have a two-step action: first, we set the topping to the knife, and then we add the topping to the bread. So we have two states to keep track of: the knife and the bread.</p>\n<p>As we said, this code works and does not block the thread, but doesn't give us all the advantages of the CAS algorithm, because we still can have a Livelock issue.</p>\n<p>A Livelock issue can occur even when the thread is not blocked, if it is waiting for an operation that will never succeed. In our code, we used the topping value as a kind of lock. The first thread that moves it from null to another value, it will put all other threads waiting for that value to become null again. It works, but if any thread fails to add the topping to the bread, which moves the topping value back to null, all the other threads will be waiting forever.</p>\n<p>The control mechanism, when more than one thread fights for the knife topping, is done by retrying again immediately, like in the CAS. But the canonical CAS will not fail indefinitely if any other thread fails. It will just finish its job as soon as no other thread touches the shared memory when it is still working.</p>\n<h3>Immutability</h3>\n<p>\"So, what to do!? I'm reading this to find answers, not questions!\" Ok, I'll let you know. The other side of the coin, in the context of thread safety, is Immutability. If we use an immutable object, virtually all problems with atomicity are gone. That's because all problems that we are facing here are based on threads fighting to access the same shared memory. If the memory that they want to access cannot be modified, those risks are gone and thread safety is achieved.</p>\n<p>We can summarise that an Immutable object is one that can't be changed after its creation.</p>\n<p>Java introduced the Record, which is a simple way to create immutable objects. We just need to provide the type and name of the fields. The public constructor, equals, hashCode, and toString methods, along with the private, final fields, are all given for free to us, by the compiler.</p>\n<p>Take a look at the following code:</p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\"><span class=\"token keyword\">public</span> <span class=\"token keyword\">record</span> <span class=\"token class-name\">Knife</span> <span class=\"token punctuation\">(</span><span class=\"token class-name\">String</span> topping<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n\n   <span class=\"token keyword\">public</span> <span class=\"token class-name\">Knife</span> <span class=\"token function\">setTopping</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">String</span> topping<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n       <span class=\"token keyword\">return</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Knife</span><span class=\"token punctuation\">(</span>topping<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n   <span class=\"token punctuation\">}</span>\n   <span class=\"token keyword\">public</span> <span class=\"token class-name\">Knife</span> <span class=\"token function\">applyToppingTo</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">Bread</span> bread<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n       <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>topping <span class=\"token operator\">!=</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span>\n           bread<span class=\"token punctuation\">.</span><span class=\"token function\">setTopping</span><span class=\"token punctuation\">(</span>topping<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n       <span class=\"token keyword\">return</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Knife</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n   <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Some could argue that immutable objects are a waste of resources, but it isn't true in the majority of cases. Dealing with immutable objects offers us performance advantages when it frees us from using synchronization or creating defensive copies, it even reduces the impact on generational garbage collection.</p>\n<p>But talking about defensive copies, is the record really immutable? Look at this test:</p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\"><span class=\"token annotation punctuation\">@Test</span>\n<span class=\"token keyword\">void</span> <span class=\"token function\">givenReferenceToRecordThenItShouldBeImmutable</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n   <span class=\"token keyword\">record</span> <span class=\"token class-name\">Parent</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">String</span> name<span class=\"token punctuation\">,</span> <span class=\"token class-name\">List</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">String</span><span class=\"token punctuation\">></span></span> childrenNames<span class=\"token punctuation\">)</span><span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n   <span class=\"token keyword\">var</span> childrenNames <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">ArrayList</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token punctuation\">></span></span><span class=\"token punctuation\">(</span><span class=\"token class-name\">List</span><span class=\"token punctuation\">.</span><span class=\"token function\">of</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Haru\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n   <span class=\"token keyword\">var</span> parent <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Parent</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Bruno\"</span><span class=\"token punctuation\">,</span> childrenNames<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n   <span class=\"token keyword\">var</span> parentBeforeNewChild <span class=\"token operator\">=</span> parent<span class=\"token punctuation\">.</span><span class=\"token function\">toString</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n   childrenNames<span class=\"token punctuation\">.</span><span class=\"token function\">add</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Ayumi\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n   <span class=\"token function\">assertThat</span><span class=\"token punctuation\">(</span>parent<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">hasToString</span><span class=\"token punctuation\">(</span>parentBeforeNewChild<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>This task will fail with the following log:</p>\n<div class=\"gatsby-highlight\" data-language=\"tex\"><pre class=\"language-tex\"><code class=\"language-tex\">java.lang.AssertionError: \nExpecting actual&#39;s toString() to return:\n  &lt;&quot;Parent[name=Bruno, childrenNames=[Haru]]&quot;&gt;\nbut was:\n  &lt;Parent[name=Bruno, childrenNames=[Haru, Ayumi]]&gt;</code></pre></div>\n<p>We have to keep in mind that in the way that we created the Parent record we have kept a reference to its internals. A record is still unmodifiable, but to achieve immutability you have to avoid exposing its inner state. In our example, we can avoid that by overriding the constructor and coping the list of children's names:</p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\"><span class=\"token keyword\">record</span> <span class=\"token class-name\">Parent</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">String</span> name<span class=\"token punctuation\">,</span> <span class=\"token class-name\">List</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">String</span><span class=\"token punctuation\">></span></span> childrenNames<span class=\"token punctuation\">)</span><span class=\"token punctuation\">{</span>\n   <span class=\"token keyword\">public</span> <span class=\"token class-name\">Parent</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">String</span> name<span class=\"token punctuation\">,</span> <span class=\"token class-name\">List</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">String</span><span class=\"token punctuation\">></span></span> childrenNames<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n       <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>name <span class=\"token operator\">=</span> name<span class=\"token punctuation\">;</span>\n       <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>childrenNames <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">ArrayList</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token punctuation\">></span></span><span class=\"token punctuation\">(</span>childrenNames<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n   <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>Now the test is successful, but we are still publishing the internal state of the record. The getter method for the property childrenNames is publishing the reference to the record's inner state, allowing it to be modified:</p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\"><span class=\"token annotation punctuation\">@Test</span>\n<span class=\"token keyword\">void</span> <span class=\"token function\">givenReferenceToRecordThenItShouldBeImmutable</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n   <span class=\"token keyword\">record</span> <span class=\"token class-name\">Parent</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">String</span> name<span class=\"token punctuation\">,</span> <span class=\"token class-name\">List</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">String</span><span class=\"token punctuation\">></span></span> childrenNames<span class=\"token punctuation\">)</span><span class=\"token punctuation\">{</span>\n       <span class=\"token keyword\">public</span> <span class=\"token class-name\">Parent</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">String</span> name<span class=\"token punctuation\">,</span> <span class=\"token class-name\">List</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">String</span><span class=\"token punctuation\">></span></span> childrenNames<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n           <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>name <span class=\"token operator\">=</span> name<span class=\"token punctuation\">;</span>\n           <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>childrenNames <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">ArrayList</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token punctuation\">></span></span><span class=\"token punctuation\">(</span>childrenNames<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n       <span class=\"token punctuation\">}</span>\n   <span class=\"token punctuation\">}</span>\n   <span class=\"token keyword\">var</span> childrenNames <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">ArrayList</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token punctuation\">></span></span><span class=\"token punctuation\">(</span><span class=\"token class-name\">List</span><span class=\"token punctuation\">.</span><span class=\"token function\">of</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Haru\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n   <span class=\"token keyword\">var</span> parent <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Parent</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Bruno\"</span><span class=\"token punctuation\">,</span> childrenNames<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n   <span class=\"token keyword\">var</span> parentBeforeNewChild <span class=\"token operator\">=</span> parent<span class=\"token punctuation\">.</span><span class=\"token function\">toString</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n   parent<span class=\"token punctuation\">.</span><span class=\"token function\">childrenNames</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">add</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Ayumi\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n   <span class=\"token function\">assertThat</span><span class=\"token punctuation\">(</span>parent<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">hasToString</span><span class=\"token punctuation\">(</span>parentBeforeNewChild<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>This code will fail as well:</p>\n<div class=\"gatsby-highlight\" data-language=\"tex\"><pre class=\"language-tex\"><code class=\"language-tex\">java.lang.AssertionError: \nExpecting actual&#39;s toString() to return:\n  &lt;&quot;Parent[name=Bruno, childrenNames=[Haru]]&quot;&gt;\nbut was:\n  &lt;Parent[name=Bruno, childrenNames=[Haru, Ayumi]]&gt;</code></pre></div>\n<p>To avoid that you have at least two options: override the getter and return a copy of our list, or the one that I prefer: save our internal state as an unmodifiable list:</p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\"><span class=\"token keyword\">record</span> <span class=\"token class-name\">Parent</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">String</span> name<span class=\"token punctuation\">,</span> <span class=\"token class-name\">List</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">String</span><span class=\"token punctuation\">></span></span> childrenNames<span class=\"token punctuation\">)</span><span class=\"token punctuation\">{</span>\n   <span class=\"token keyword\">public</span> <span class=\"token class-name\">Parent</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">String</span> name<span class=\"token punctuation\">,</span> <span class=\"token class-name\">List</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">String</span><span class=\"token punctuation\">></span></span> childrenNames<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n       <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>name <span class=\"token operator\">=</span> name<span class=\"token punctuation\">;</span>\n       <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>childrenNames <span class=\"token operator\">=</span> <span class=\"token class-name\">List</span><span class=\"token punctuation\">.</span><span class=\"token function\">copyOf</span><span class=\"token punctuation\">(</span>childrenNames<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n   <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Like this, every time someone tries to update our inner state, they will get a UnsupportedOperationException, which I believe is what we should expect from trying to modify something supposed to be immutable.</p>\n<h2>Summary so far</h2>\n<p>What we have seen so far?</p>\n<ul>\n<li>\n<p>We learned more about Race Conditions, in real life and in the software, and the main solution tool from Java: the monitor pattern, using the synchronized keyword;</p>\n</li>\n<li>\n<p>After understanding the downside of locking, we were introduced to the compare-and-swap (CAS) nonblocking algorithm, which despite being hard to develop can lead us to better performance and protect us from Deadlock</p>\n</li>\n<li>\n<p>For the cases when we are unable to isolate our shared memory, or even in other scenarios where we just need more protection, we talked about immutability and how immutable objects can grant us thread safety.</p>\n</li>\n<li>\n<p>We then revisited the java Record, which is a fairly easy way to create an immutable object, but that is not immune to bad programming technic. To really achieve immutability in our objects we saw how we should avoid publishing its inner state.</p>\n</li>\n</ul>\n<h2>Conclusion</h2>\n<p>Oh, it was an amazing journey, we started with a brief introduction about threads, how to properly test them, and we met some new friends from Java's Concurrency package. With new algorithms and tools under our belt, we are ready to travel to the multithreaded world riding our thread-safe software. I'll now eat my bread with butter, see you soon!</p>\n<h2>Appendix</h2>\n<p>Baking delicious cakes with AssertJ's Condition entity:</p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\"><span class=\"token annotation punctuation\">@Test</span>\n<span class=\"token keyword\">void</span> <span class=\"token function\">testTheCake</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n   <span class=\"token keyword\">record</span> <span class=\"token class-name\">Cake</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">String</span> name<span class=\"token punctuation\">,</span> <span class=\"token keyword\">boolean</span> hasFruit<span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span> weightInKg<span class=\"token punctuation\">)</span><span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\n   <span class=\"token keyword\">var</span> chocolateCake <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Cake</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Chocolate\"</span><span class=\"token punctuation\">,</span> <span class=\"token boolean\">false</span><span class=\"token punctuation\">,</span> <span class=\"token number\">5</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n   <span class=\"token keyword\">var</span> strawberryCake <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Cake</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Strawberry\"</span><span class=\"token punctuation\">,</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">,</span> <span class=\"token number\">3</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n   <span class=\"token keyword\">var</span> bakery <span class=\"token operator\">=</span> <span class=\"token class-name\">List</span><span class=\"token punctuation\">.</span><span class=\"token function\">of</span><span class=\"token punctuation\">(</span>chocolateCake<span class=\"token punctuation\">,</span> strawberryCake<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n   <span class=\"token keyword\">var</span> heavyCakes <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Condition</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">Cake</span><span class=\"token punctuation\">></span></span><span class=\"token punctuation\">(</span>cake <span class=\"token operator\">-></span> cake<span class=\"token punctuation\">.</span>weightInKg <span class=\"token operator\">>=</span> <span class=\"token number\">3</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"heavy cake\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n   <span class=\"token keyword\">var</span> bigChocolate <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Condition</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">Cake</span><span class=\"token punctuation\">></span></span><span class=\"token punctuation\">(</span>cake <span class=\"token operator\">-></span>\n           cake<span class=\"token punctuation\">.</span>name<span class=\"token punctuation\">.</span><span class=\"token function\">contains</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Chocolate\"</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">&amp;&amp;</span>\n           cake<span class=\"token punctuation\">.</span>weightInKg <span class=\"token operator\">>=</span> <span class=\"token number\">5</span>\n           <span class=\"token punctuation\">,</span> <span class=\"token string\">\"big chocolate\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n   <span class=\"token function\">assertThat</span><span class=\"token punctuation\">(</span>bakery<span class=\"token punctuation\">)</span>\n           <span class=\"token punctuation\">.</span><span class=\"token function\">haveExactly</span><span class=\"token punctuation\">(</span><span class=\"token number\">2</span><span class=\"token punctuation\">,</span> heavyCakes<span class=\"token punctuation\">)</span>\n           <span class=\"token punctuation\">.</span><span class=\"token function\">haveExactly</span><span class=\"token punctuation\">(</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> bigChocolate<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>","fields":{"slug":"/a-wild-thread-appeared-multithreaded-testing-and-thread-safety/","tags":["Thread-safety","testing","nonblocking_algorithms","immutability"]}}},{"node":{"id":"62f571b3-f36e-549e-bb49-e2f60369d524","frontmatter":{"category":"Engineering","title":"How We Implement Feature Requests at AUTO1","date":"2022-11-30","summary":"In this blog post I want to emphasize how important the process of exceptional software delivery is.","thumbnail":null,"authorName":"Karim Baydon","authorDescription":"Senior Software Engineer in the AUTO1 Production Domain Team based in our Berlin Office","authorAvatar":{"relativePath":"pages/how-we-implement-feature-requests-at-auto1/karim-baydon-avatar.png","childImageSharp":{"resolutions":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAYAAACQjC21AAAACXBIWXMAABYlAAAWJQFJUiTwAAAFIklEQVQ4yx2U21PUZRzGfzeZOaXNVM6UJpoYoiGDkiIHB5DDLuyRPbHnA/uDBXZZ9ySwgItyEJaD7gqSmmbgZFAwKCDqKDlmTjU1XWQ5ZTdNTV020z/w6ZcX33kv3pnPPO/zfJ9X0Bwrx3i8ElNMiTGkwdKhQ9kqR9FSTUNCh/ekFrFPTWTMTnDQQ+xkiOYWEY/NhlmlJeAP4HY3IatUEA+FEerDVVg6K7B3GiWAGW1bFUdsRVR6i9GFpLt2GWK3hmC7n1AggEOrpyA3n7w9+8jYksG+3TmUllRSU61CdHoRrMdleHoVuKSxx2vx9atoG9TjCGlpioiE2tvwtzbSGwqhq1Gy5Y3XeWn9i6xb9wIbXtrAq5teZcOGl9n82mays95D6J3y4O2rxRGvwhVV0NIuPc0vEmgVaW504QtaaW520d3Swu53drJx/ToO7s4kL3MHmW+9Sc72DA5l7WLzxlfY+MomhPAJO6ZGJc5ALd6AhuaAmcaIAV+nDndAhdNfi6fFglGtZe+ODGaGT/LsziLfz05zOz3KamqIh5cnOB9rI+vttxFE0YHDZcTtU+Nw6rBZtHhjGlp7DZJaIw6/5E3QTFlpIR0Ndv75/kt+f3CH31Zv8Gx5nl+leXJjjp8Wr+PXaRAsBp0E1OJwyzHo5NQbVbidGsxGSW2rE4/biKWxilJZCee6wvzxYIW/H6/x16M1fr9/mz/Wbj8/f1mZJx1uQXDb9disCiwGjbQKJlw2CV6vx+t0YFApMTtlqOqLKK+o4OpQDz8uzXHv0hRfTKV5dPEcKyMDpKNhrg328clgAkGrqsZpMeGx6rGYlJjqNdhsRnxuF4l4J8dPNuO2m9Cp1HyePs1UyEdpdjaq97L4pOsYYtH75G3ZSlCrZm504H+FVtwWM6LDgdNlwqDXoq1VkBob5evHP3B5ahp5lZxD+QeZPTvIo6uTxE119NuNPF2aZzoeJWHScTM1yv2PLiC0h8MEmn10nUjgsFoxqDWkzqRZvXWPuU/nsVrq2Jezm6Kiw1yWEv7z4R2eLlznyWcz/PvdN/y8MMu301ckD5dYTI8hzC4skpq6gNGoxyV5N3EmxcrSXZZv3iMU9GF11GFx19E30M/50WG+nLnAN9MXuT85zsyJONcSXTy8dJ6vJOhUPIbQNT6O3mHDolVw/uxZbt1a4+7tR7THQhgN1RwLRegfSDL98XVSI8NMdrQwebyVTk0t9txcxOJieiTPRwIiQYsFwRTw0+CxkxoeZmF+ldXlBwz2D6BUlOIwGxjp6yWdHGJibISuxDg2tY5jejmXAo2Ma3VMOp3PgbL8XCorbQjeRjfJ00MsLKyyvLTGRPoDZNWFdEaC9HW0M5U8zfS5MfpOpdA5hqRfxULB3iyG2pqY7g5xtSeKvPAwZfkHqK12IowODDA3t8yNxTvMXJ1FrarEbq/nbHKUi5IFZ04nCUeTmDxJKpQRZDIRzZES3t22HfmhgxTn5JDx1lYi0rZkvVuC8OHlWT668pmU6DIup00CVhHv7KHBF0VlCOMJSB4/h0U5WtPGnv16FKU1iIqj5O3cyYHMTKJWqW0KLZu3FiIMJT9gYnKGSCSGQlFJIBgl3JHA7O2hQh1DYx9EYz2FwtTD4TKRnP117NhVht+gp1vqfbtJzZi/gZzsErL2SV2+IikcHjrD0aOFOKW0xaYAzdE+golrNMU+pM45TLkyRo2+m4KyBvbmKtmVLWdbRgGG0nK6TQpqCorJyCwnN9/Af3EcVq8wGWCGAAAAAElFTkSuQmCC","width":50,"height":50,"src":"/static/29be57150f6568025a4db433fa0deedc/45876/karim-baydon-avatar.png","srcSet":"/static/29be57150f6568025a4db433fa0deedc/45876/karim-baydon-avatar.png 1x,\n/static/29be57150f6568025a4db433fa0deedc/eb85b/karim-baydon-avatar.png 1.5x,\n/static/29be57150f6568025a4db433fa0deedc/4f71c/karim-baydon-avatar.png 2x"}}},"headerImage":null},"html":"<h1>How We Implement Feature Requests at AUTO1</h1>\n<p>In this blog post I want to emphasize how important the process of exceptional software delivery is. I’m going through all the steps used by AUTO1 to achieve the best possible implementation in software development. All in all, there are 5 steps that require a clean and effective implementation:</p>\n<ul>\n<li>Product Specs</li>\n<li>Tech Specs</li>\n<li>Implementation</li>\n<li>Quality Assurance</li>\n<li>Monitoring</li>\n</ul>\n<p><a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/f4a1c09b710c1ba7f40345bfce644242/81d54/auto1-feature-request-lifecycle.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 590px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 22.421875000000004%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAECAYAAACOXx+WAAAACXBIWXMAAAsSAAALEgHS3X78AAAA/klEQVQY002MXU+CcBjF+ex9BLtq3dS6sZrdtPXCYs008DVbNkFwYgJa4oaDEkP+/IKVW2c7e87Z89uRgnWKOvSpKG0alk/XjpFbc640B7Uf4Cq31A9L9I4PcLUqmmFxfiOjPPXx5xbBQMF7lvmyNdjGSHEiUEcBZc2l+xbxMl1z3Qmp1H2a1gZHVbFKe0yO9pnXFbqjMWePTWrGCG824du8I+iU2TotsniFtIwSetOQBzNgMPtEdzc0hjE1fYNhhyzUe7yLE94vT/H015z5yH8mfWdGtLARbptkXEUsTTKRIoksI8tdqLhCFPmvC0GWpr85t8i7+MfmADvtNn4AKnkiQHck8EgAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n    ></span>\n    <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;box-shadow:inset 0px 0px 0px 400px white;\"\n        alt=\"auto1-feature-request-lifecycle\"\n        title=\"\"\n        src=\"/static/f4a1c09b710c1ba7f40345bfce644242/40fad/auto1-feature-request-lifecycle.png\"\n        srcset=\"/static/f4a1c09b710c1ba7f40345bfce644242/707e9/auto1-feature-request-lifecycle.png 148w,\n/static/f4a1c09b710c1ba7f40345bfce644242/649e0/auto1-feature-request-lifecycle.png 295w,\n/static/f4a1c09b710c1ba7f40345bfce644242/40fad/auto1-feature-request-lifecycle.png 590w,\n/static/f4a1c09b710c1ba7f40345bfce644242/b3fef/auto1-feature-request-lifecycle.png 885w,\n/static/f4a1c09b710c1ba7f40345bfce644242/301c0/auto1-feature-request-lifecycle.png 1180w,\n/static/f4a1c09b710c1ba7f40345bfce644242/81d54/auto1-feature-request-lifecycle.png 1280w\"\n        sizes=\"(max-width: 590px) 100vw, 590px\"\n      />\n  </span>\n  </a></p>\n<p>In the following I would like to go into detail about these steps.</p>\n<h2>1. Product Specs</h2>\n<p>The most valuable feature implementation does not help if you have a bad user experience. This is why the product managers at AUTO1 work closely with the design team to build great product specifications and UIs to let the users handle their work with the application easily.</p>\n<p>The product specs are usually divided into stories to simplify the work on them for designers, as well as software engineers. Once this is done, the software engineers work their way up from specifications and UI to database schemas, requests and responses, etc. in the tech specs.</p>\n<h2>2. Tech Specs</h2>\n<p>One vital process for building new features at AUTO1 is the concept of creating Tech Specs. Tech Specs stands for Technical Specifications, and is basically a design document that represents the bits and pieces of a new feature implementation. At AUTO1, we have over 600 microservices that are handling various different tasks. So to provide exceptional and error-proof work, we create a sort of contract between developers within a team that are aware of how the technical implementation has to be done. The Tech Specs generally include the following important information:</p>\n<ul>\n<li>An agreement of Requests/Responses between FE and BE engineers so that FE/BE can work autonomously</li>\n<li>Api Relationships between services that provide specific data that is needed for the implementation</li>\n<li>Architectural diagrams of the Api flows between services</li>\n<li>Database schemas</li>\n<li>Finding consent between other teams that are affected by the changes</li>\n</ul>\n<p>With that said, the Tech Specs provide very helpful instructions to put all engineers on the same implementation ideas so the work can be accomplished in a straight-forward manner.</p>\n<h2>3. Implementation - a few key takeaways</h2>\n<p>In the following I would like to go into detail about a few key takeaways for one of our implementations in the production domain.</p>\n<h3>Tech Decision 1: Data duplication to provide a fast search</h3>\n<p>One of the key points of a new feature implementation in the Production domain was to provide a list of specific data regarding cars that have to be refurbished. This list should also include a search on the top to look up cars by specific values like the VIN (Vehicle Identification Number), stock number, and refurbishment number. In order to get the appropriate data we have to send request to multiple services. There are actually two ways to fetch the cars by the given filters:</p>\n<ol>\n<li>Use the Aggregator Pattern and request two api endpoints to combine the data afterwards and list the cars.</li>\n<li>Import the data into the database of the new service and simply query it.</li>\n</ol>\n<p>Let's have a deeper look at these two methods....</p>\n<h4>Method 1 - The Aggregator Pattern</h4>\n<p>The Aggregator Pattern is usually a standalone microservice. It offers a uniform API that a client can use to access data from different microservices.</p>\n<p><a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/4ed585dd6c350563cbffeb47bacdca14/47d1e/aggregator-pattern.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 582px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 56.013745704467354%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAAsSAAALEgHS3X78AAABiUlEQVQoz32SCW+CQBCF/f//p4lp2thL40E1HoCAsrCKTRFBkEtFX0cMaoJ1kwkw8+abN2QreHCOpzgeL+98NgczTOyzwzlHtaJenMq/sBtx4DkIPRu6IkKV+ti4v/Bd+zrsBvoQePJ1oMdK78Ebv8FTvxBMGlgrH3C0NrIbpw+BV3dnoMe6sAdVcOEJ9ugF/rgGnwm0elbaplJ2dRUU376zQOJacBdT6FIXuijAUEd3f0/lHuz2xHGEMIoRxglsx8VQlPH+WUe90YTv+6XN7joMggCWZcFZLuGv10jiGFEUIiDAhmpFnHS2befaNelKDgugs1phJIowOMfKdRElCZI0vQze7naIKecShM/nkGQZ1uLn/sopNQ6mDH1jBkGZoEMhaDpEnSHb73PdmO5iR5uiM9ZyzYC0/QmjLeIyMKHJ3+oELY2h2uyg1huiPTXzhhOQhAQ38tyr0MNzS0BL1fPBYRiWgXtq0kwO2eBQ+AyKOYPETLC5hePhfO84rScx41LPteQ63W7xB6IFSW1pdvGFAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n    ></span>\n    <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;box-shadow:inset 0px 0px 0px 400px white;\"\n        alt=\"aggregator-pattern\"\n        title=\"\"\n        src=\"/static/4ed585dd6c350563cbffeb47bacdca14/47d1e/aggregator-pattern.png\"\n        srcset=\"/static/4ed585dd6c350563cbffeb47bacdca14/0d10c/aggregator-pattern.png 148w,\n/static/4ed585dd6c350563cbffeb47bacdca14/f53bb/aggregator-pattern.png 295w,\n/static/4ed585dd6c350563cbffeb47bacdca14/47d1e/aggregator-pattern.png 582w\"\n        sizes=\"(max-width: 582px) 100vw, 582px\"\n      />\n  </span>\n  </a></p>\n<p>This composite service is utilized when we need to prepare the result data produced from the outputs of several microservices. The aggregator pattern is designed to combine data from several endpoints and provide it as a single endpoint to the client. If necessary, it can also cache that data according to predetermined criteria or rules. You can read more about this pattern here: <a href=\"https://www.edureka.co/blog/microservices-design-patterns\">https://www.edureka.co/blog/microservices-design-patterns</a></p>\n<p>So to sum up, we can simply execute two or more api requests to separate services and accumulate the data we need to show the results in the list. This sounds good, except for one drawback: Performance! It is at the expense of performance. One more way to enhance this behavior is by using asynchronous api requests, which basically execute these multiple api requests in parallel. However, it does not provide the best performance (depending on the use-case, it was not an option for us).</p>\n<h4>Method 2 - Importing the data into the microservice</h4>\n<p>Since the data like VIN, stock number, etc. will not change in the future, importing fixed data to the service database sounds very suitable. So the key message here is: don't rely on sending synchronous queries to obtain data that was previously controlled by another microservice if your primary microservice requires it. Instead, use consistency to duplicate or propagate that data (just the properties you require) into the other service's database.</p>\n<p>The only data that changes over the course of a refurbishment is the state. For syncing the refurbishment state, we used asynchronous messaging. Every time the initial state of a refurbishment is changed, a message will be produced to SQS (Simple Queue Service). From there, we can easily consume that message and change the state in the new microservice.</p>\n<p>To provide a fast search, we added an index only to the state field, since too many composite indexes can have degradation on insertion, deletion, and updating performance. The Data Manipulation Language statement has to modify the table data and the indexed data too, which might decrease the performance depending on the amount of data. We have slow query alerts in place, so we get notified when it might be time for an investigation to improve the performance.</p>\n<h3>Tech Decision 2: Event Sourcing the State Changes</h3>\n<p>Event sourcing is a way for an event-driven microservice to respond to events in order to carry out its tasks. A higher-level operation is performed by a number of these services interacting with one another in an event-driven architecture based on messaging. The interaction usually consists of a series of messages taken by the various services to handle, for e.g. state changes.</p>\n<p>Messaging at AUTO1 works in the following way. Every service that publishes messages must specify the SNS topic to which it intends to deliver those messages. Topics are bound by message type, so if the message type is <code class=\"language-text\">Refurbishment.State</code> then the topic is named <code class=\"language-text\">Refurbishment_State</code>. Messages are then routed to the subscribed SQS queues using topics that have been specified. These messages can be consumed by multiple consumers.</p>\n<p><a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/008c7e32b470559ed983d982ac6e9ebe/1ed58/aws-sns-sqs-messaging-auto1.jpg\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 590px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 42.4287856071964%; position: relative; bottom: 0; left: 0; background-image: url('data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAIABQDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAAIF/8QAFQEBAQAAAAAAAAAAAAAAAAAAAQD/2gAMAwEAAhADEAAAAd6QgT//xAAWEAEBAQAAAAAAAAAAAAAAAAAAAUH/2gAIAQEAAQUCZH//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAVEAEBAAAAAAAAAAAAAAAAAAAAQf/aAAgBAQAGPwJVf//EABkQAAIDAQAAAAAAAAAAAAAAAAARASExkf/aAAgBAQABPyFbciltjq+j/9oADAMBAAIAAwAAABAL/wD/xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/ED//xAAXEQEAAwAAAAAAAAAAAAAAAAABEBEh/9oACAECAQE/EDGo/8QAGxABAAICAwAAAAAAAAAAAAAAAQARQVExYYH/2gAIAQEAAT8QXWVrEAqs0pfkHCL2Fn//2Q=='); background-size: cover; display: block;\"\n    ></span>\n    <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;box-shadow:inset 0px 0px 0px 400px white;\"\n        alt=\"aws-sns-sqs-messaging-auto1\"\n        title=\"\"\n        src=\"/static/008c7e32b470559ed983d982ac6e9ebe/f8fb9/aws-sns-sqs-messaging-auto1.jpg\"\n        srcset=\"/static/008c7e32b470559ed983d982ac6e9ebe/e8976/aws-sns-sqs-messaging-auto1.jpg 148w,\n/static/008c7e32b470559ed983d982ac6e9ebe/63df2/aws-sns-sqs-messaging-auto1.jpg 295w,\n/static/008c7e32b470559ed983d982ac6e9ebe/f8fb9/aws-sns-sqs-messaging-auto1.jpg 590w,\n/static/008c7e32b470559ed983d982ac6e9ebe/1ed58/aws-sns-sqs-messaging-auto1.jpg 667w\"\n        sizes=\"(max-width: 590px) 100vw, 590px\"\n      />\n  </span>\n  </a></p>\n<p>So to keep the state changes updated, we created a Message Listener that listens to state changes and updates the state. A message producer for the state changes was already in place since several other services needed to consume this message as well and make their own updates.</p>\n<h3>Tech Decision 3: Implementing Feature Flags</h3>\n<p>Feature flags can be helpful in a variety of situations. It's essential to understand that feature flags can be used to configure a wide range of application components. Some feature flags are used to run specific parts of the application, and some feature flags intentionally prevent that. Additionally, feature flags may be applied to the frontend and/or backend. Enabling or disabling features for individual parts of an application is a common use case.</p>\n<p>The strategy we usually apply is to enable features for specific car repair workshops using a feature flag. That way, we can steadily monitor for errors and let the feature evolve so it is ready to be rolled out to all the other car repair workshops as well. For some features, it might be needed to backfill data to pre-existing entities to support the feature in earlier refurbishments.</p>\n<h2>4. Quality Assurance (QA)</h2>\n<p>Quality assurance is an essential part of software development and therefore should ideally take place not only at the end, but throughout the development process.</p>\n<p>If you want to create good software, you should include software tests in the development process from the very beginning. Here are three reasons for the need of good-quality testing:</p>\n<ol>\n<li>\n<p><strong>A high-quality user experience is guaranteed by quality assurance</strong><br>\nSoftware quality issues have an impact on functionality and as a result the user experience. When it comes to developing good software, the user always comes first. Only this ensures that the product is of high quality.</p>\n</li>\n<li>\n<p><strong>Quality assurance saves time and money</strong><br>\nThose who recognize quality assurance as an essential component of software development from the start save time and money. The later errors are discovered, the longer the development time and the higher the costs.</p>\n</li>\n<li>\n<p><strong>More security is provided by quality assurance</strong><br>\nContinuous quality assurance throughout the development process ensures that security vulnerabilities are detected and addressed early on.</p>\n</li>\n</ol>\n<h2>5. Monitoring</h2>\n<p>To improve the quality of an application, you need monitoring. Application monitoring helps developers to locate bugs easier and speeds up the development time. If application monitoring is ignored, it could lead to unexpected crashes or poor performance that would cause significant harm to the company. It can enable engineers to gain insights into how their systems will behave.</p>\n<p>This information enables them to identify issues or flaws while they are still small enough to be handled with relative ease. At AUTO1 every new service has its own Grafana monitoring dashboard to provide several key metrics like:</p>\n<ul>\n<li>JVM Memory usage</li>\n<li>JVM Heap size usage</li>\n<li>ECS Container Memory usage</li>\n<li>Docker Container CPU usage</li>\n<li>Load Averages</li>\n<li>Garbage Collector Metrics</li>\n<li>Cache Metrics</li>\n<li>Thread Pool Metrics</li>\n<li>etc.</li>\n</ul>\n<p><a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/4b1a5fc3828f80a25193475f942c3c3a/1b776/auto1-monitoring.jpg\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 590px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 72.99270072992701%; position: relative; bottom: 0; left: 0; background-image: url('data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAPABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAECBf/EABUBAQEAAAAAAAAAAAAAAAAAAAAB/9oADAMBAAIQAxAAAAHk5kSg/8QAGBAAAgMAAAAAAAAAAAAAAAAAABEBICH/2gAIAQEAAQUCxUcn/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAFRABAQAAAAAAAAAAAAAAAAAAIEL/2gAIAQEABj8Clf/EABwQAAMAAQUAAAAAAAAAAAAAAAABESEQMUGRsf/aAAgBAQABPyHCsvRy8DhHokbN9n//2gAMAwEAAgADAAAAELzv/8QAFhEBAQEAAAAAAAAAAAAAAAAAABEh/9oACAEDAQE/EK1//8QAFREBAQAAAAAAAAAAAAAAAAAAACH/2gAIAQIBAT8QV//EAB0QAAICAQUAAAAAAAAAAAAAAAERACFBUWGRweH/2gAIAQEAAT8QAEIkTTPSLILX5LMcSiw5YyoGQY2j/9k='); background-size: cover; display: block;\"\n    ></span>\n    <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;box-shadow:inset 0px 0px 0px 400px white;\"\n        alt=\"auto1-monitoring\"\n        title=\"\"\n        src=\"/static/4b1a5fc3828f80a25193475f942c3c3a/f8fb9/auto1-monitoring.jpg\"\n        srcset=\"/static/4b1a5fc3828f80a25193475f942c3c3a/e8976/auto1-monitoring.jpg 148w,\n/static/4b1a5fc3828f80a25193475f942c3c3a/63df2/auto1-monitoring.jpg 295w,\n/static/4b1a5fc3828f80a25193475f942c3c3a/f8fb9/auto1-monitoring.jpg 590w,\n/static/4b1a5fc3828f80a25193475f942c3c3a/85e3d/auto1-monitoring.jpg 885w,\n/static/4b1a5fc3828f80a25193475f942c3c3a/1b776/auto1-monitoring.jpg 1096w\"\n        sizes=\"(max-width: 590px) 100vw, 590px\"\n      />\n  </span>\n  </a></p>\n<h2>Conclusion</h2>\n<p>Working on a feature implementation is guided by a step-by-step process to provide the best solutions possible on every part of the application.</p>\n<p>The key lesson here is that the process is intertwined with the product itself. Because of this, each stage in the development process — from planning to execution — involves stakeholders, product managers, designers and software engineers. You don't have to plan too much in advance. Software engineers can always make up tentative plans as they go, saving them time and also increasing their productivity.</p>","fields":{"slug":"/how-we-implement-feature-requests-at-auto1/","tags":["auto1","engineering","aws","feature implementation","software architecture","design patterns"]}}},{"node":{"id":"de226d1e-aa44-5f73-9bc5-3d554df1f7e6","frontmatter":{"category":"Engineering","title":"How we manage Network Devices at Auto1","date":"2022-10-28","summary":"Network automatization management using Unimus","thumbnail":null,"authorName":"Besnik Shala","authorDescription":"Besnik is a Senior Network and Security Engineer based in our Berlin office","authorAvatar":{"relativePath":"pages/how-we-manage-network-devices-at-auto1/avatar_Shala.jpg","childImageSharp":{"resolutions":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAeABQDASIAAhEBAxEB/8QAGQAAAgMBAAAAAAAAAAAAAAAAAAMBAgQF/8QAFQEBAQAAAAAAAAAAAAAAAAAAAQD/2gAMAwEAAhADEAAAAeNoRvTmElNESlion//EABoQAAMAAwEAAAAAAAAAAAAAAAECAwAREiD/2gAIAQEAAQUCVSxrBpDEOjWncyMkwVnbo+P/xAAXEQEBAQEAAAAAAAAAAAAAAAAAEQEh/9oACAEDAQE/AeRW4j//xAAXEQEBAQEAAAAAAAAAAAAAAAAAEQEh/9oACAECAQE/Ae1Gar//xAAaEAEBAAIDAAAAAAAAAAAAAAABEQAQIEGR/9oACAEBAAY/AoYL3ocnuqlMsnH/xAAbEAEAAgMBAQAAAAAAAAAAAAABABEQIUExUf/aAAgBAQABPyEh6Mohr45jRi75BAlL6W4gwLSOSxAtwl4vH//aAAwDAQACAAMAAAAQCO5D/8QAFxEAAwEAAAAAAAAAAAAAAAAAAAERIf/aAAgBAwEBPxC0bEhTCD//xAAYEQEBAQEBAAAAAAAAAAAAAAABABEhMf/aAAgBAgEBPxAEAlD5Ydt3/8QAHRABAAICAwEBAAAAAAAAAAAAAQARITFBUWGBEP/aAAgBAQABPxAm71HcudD6t0xMy7AGQqfjHhJMwa4zqUDfpKk0b+NwRQWkAOINMsGpZK/P/9k=","width":50,"height":50,"src":"/static/389e6ac4cc3981149603d886ba880ccb/d2d31/avatar_Shala.jpg","srcSet":"/static/389e6ac4cc3981149603d886ba880ccb/d2d31/avatar_Shala.jpg 1x,\n/static/389e6ac4cc3981149603d886ba880ccb/0b804/avatar_Shala.jpg 1.5x,\n/static/389e6ac4cc3981149603d886ba880ccb/753c3/avatar_Shala.jpg 2x,\n/static/389e6ac4cc3981149603d886ba880ccb/31ca8/avatar_Shala.jpg 3x"}}},"headerImage":null},"html":"<p>With over 400 locations across Europe, managing our network devices has become a big endeavor. In order to be more efficient on this challenge the Corporate IT Network Team recently implemented Unimus.</p>\n<p>Unimus does network automation, configuration backups, change management, updates and enables automation for all the processes. This also benefits the engineers not to work late hours or on weekends.</p>\n<p>To provide an example, here is a quick overview of how we upgrade our MikroTik routers using Unimus, which are located at our Autohero workshops all over Europe:</p>\n<table>\n<thead>\n<tr>\n<th><strong>1. On the Unimus platform we add each device with the devices IP and Credentials.</strong></th>\n<th><img src=\"https://lh4.googleusercontent.com/8EZA89AIL5p8v723-rdyslTwOTbCIAqreXMF9_sd-fP6L7EEfbSN9h1yCvd6n7Ljc62P5GXAdj0KvtGqLhU2BKUdVd9dQEh8QP3rCRMhCZ2Q2yo_Rq9vrAj8grXr06wyWqhMYIAhtlgoG3uzqZGzCw8hcwhZHWXtvUgA7wamde5V5ZNnhkmwXMis0Q\"></th>\n<th></th>\n<th></th>\n<th></th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><strong>2. From “Schedules” we configure the time and date for the desired upgrade.</strong></td>\n<td><img src=\"https://lh3.googleusercontent.com/lxogAJ5Uq3wfk3-co_sG3dt_nnSph-bOuOOHItnd_-IKRcvOAzJ50PJgJnyRwKeHdwHk5pFWroeEbRuOcOcm-DiFCTKOKlCqsduwyxQK1nUknzKJpXPPv8z405le3v3C2oMqr2qYp1oq5Mj_XPP4cAhQDjYMUUPcSq-WP-W304PIw2ak2b5qnCNi0Q\"></td>\n<td></td>\n<td></td>\n<td></td>\n</tr>\n<tr>\n<td><strong>3. After adding all devices of the same model to Unimus, we go to the “Mass Configuration Push” menu. Templates and configurations for the upgrade need to be prepared.</strong> <br><br><br> <strong>4. From here we also add a Mikrotik Script to download the latest update, add the schedule for this push and select the target devices.</strong></td>\n<td><img src=\"https://lh6.googleusercontent.com/2pAyEXvc4hlAGNcMYNalJJDwM91YihSX4NdVRO-Hwzp52Zxldz_P0PH6OSlPSjp4DgGv5TSRTbjzxTQs3I0Li5h1_57g4tR9TB__80NL-petgqahPdZeOcgRYJt9G6h12xrLQfjmm9ijjJbTzXLqJPps3Ana2TZ5yTNJ_VXap4Hd6C7OZahMiHQY1g\"></td>\n<td></td>\n<td></td>\n<td></td>\n</tr>\n<tr>\n<td><strong>5. Lastly we add a second command to issue the upgrade and reboot the device.</strong> <br><br><br> <strong>6. All that’s left to be done is to add a corresponding downtime in our monitoring tool (CheckMK) and wait for the magic to happen.</strong></td>\n<td><img src=\"https://lh3.googleusercontent.com/2xOP2Pq7LztBRRr-B2VJ5_roCubvYa4xJ_SlVeTz8LWzRTYqXflYowAAaNDsDh7y77M2vDDB8l1r_BpOvQsKQfHGssADO7FnbzGEmjtXKfFKfV5mES8whAQdYfUTJHwEdv9OGJ2A2GvkxS5XglrDG29p7zNZrtFNXvAMjThrQloKfFmSuqs7Nmd-xw\"></td>\n<td></td>\n<td></td>\n<td></td>\n</tr>\n</tbody>\n</table>","fields":{"slug":"/how-we-manage-network-devices-at-auto1/","tags":["auto1","IT","Network","Automation "]}}},{"node":{"id":"c228c662-0cfd-54f0-ad54-4e1ef0c854d8","frontmatter":{"category":"Engineering","title":"Enter the End to End Testing of Internal Libraries ","date":"2022-07-18","summary":"End2End testing could help us tackle problems of increasing new code across the whole platform","thumbnail":null,"authorName":"Mikołaj Kłosowski","authorDescription":"Mikołaj is an Senior Software Engineer based in our Szczecin office","authorAvatar":{"relativePath":"pages/e2e-testing-internal-libraries/avatar_Kłosowski.jpg","childImageSharp":{"resolutions":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAPABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAMEAgX/xAAXAQADAQAAAAAAAAAAAAAAAAAAAQID/9oADAMBAAIQAxAAAAHPSiqzp4sF/8QAHBAAAgICAwAAAAAAAAAAAAAAAQIAAwQTESIj/9oACAEBAAEFAsYlcVG5r7CKRrrPnsn/xAAWEQEBAQAAAAAAAAAAAAAAAAAAEUH/2gAIAQMBAT8BxH//xAAVEQEBAAAAAAAAAAAAAAAAAAAAEf/aAAgBAgEBPwFH/8QAGhAAAgIDAAAAAAAAAAAAAAAAATEAEBIhYf/aAAgBAQAGPwIntKYncSr/xAAaEAEBAQADAQAAAAAAAAAAAAABEQAhMUGB/9oACAEBAAE/IQode8wvC2YhG/uoApOa9YSQYzv/2gAMAwEAAgADAAAAEI8v/8QAFhEBAQEAAAAAAAAAAAAAAAAAABEx/9oACAEDAQE/EJhT/8QAGBEAAwEBAAAAAAAAAAAAAAAAAAERQVH/2gAIAQIBAT8Qira0rp//xAAbEAEAAgMBAQAAAAAAAAAAAAABACERQVFxgf/aAAgBAQABPxDAIpp0LiTEIqARnq9gI/maHxA+0omb7FWMPxn/2Q==","width":50,"height":50,"src":"/static/08ff7d0f10dc02e43f61b30c3bf69631/d2d31/avatar_K%C5%82osowski.jpg","srcSet":"/static/08ff7d0f10dc02e43f61b30c3bf69631/d2d31/avatar_K%C5%82osowski.jpg 1x,\n/static/08ff7d0f10dc02e43f61b30c3bf69631/0b804/avatar_K%C5%82osowski.jpg 1.5x,\n/static/08ff7d0f10dc02e43f61b30c3bf69631/753c3/avatar_K%C5%82osowski.jpg 2x,\n/static/08ff7d0f10dc02e43f61b30c3bf69631/31ca8/avatar_K%C5%82osowski.jpg 3x"}}},"headerImage":null},"html":"<p>When a software-based company grows, it creates lots of new code, which means multiple engineers may be facing the same problems across the whole platform. They will usually come up with various solutions to fix it. Some of them might be generic and reusable, while others will be tailored to one’s needs. As it usually happens, the solutions will then be bundled together to create libraries. This is very good, up to a certain point, since over the years, engineers will create them by the dozens and this, in turn, will bring about other hurdles such as:</p>\n<ul>\n<li>how to maintain multiple libraries or prevent buggy code from getting in</li>\n<li>how to release one of them or many at the same time</li>\n<li>how to ensure a smooth process for updating libs for service maintainers</li>\n<li>how to ensure cross-compatibility for all of the libs</li>\n</ul>\n<p>This was quite a big pain point for AUTO1 software developers as we have 60+ common libraries that need to work perfectly in 600+ production services across multiple business units and products. One simple mistake, for example, a wrong configuration change leftover after a debug session can end up in disaster.</p>\n<p>Enabling protection against direct commits for main branches will address the first hurdle - only pull requests with double approvals and tested by CI can be merged.</p>\n<p>The next 2 issues are more about ease of usability for the developers, as they might be reluctant to upgrade their service if the process is troublesome. So, in the best-case scenario, our end-user should periodically update only a single property. In addition, our common library developers need to be able to easily publish their changes.</p>\n<p>The solution to it was the release trains, usually known as BOMs or for AUTO1 developers, service-commons-dependencies. After successful implementation, you will just need to trigger CI build to get the newly released version, which in turn can be pasted into a pom/gradle file. So, right now everything looks good, but can we be 100% sure that our changes are going to work? Perhaps there is a very small bug in a messaging lib or we will lose tracing for incidents. That’s unacceptable. So let’s ensure that will never happen by introducing automatic real use case testing.</p>\n<p>In our approach, we thought most of the problems could be revealed by running extensive integration testing. The test harness probably catches all bugs in our codebase and simply fails when needed preventing the release of a buggy version.</p>\n<p>But no matter what you do or how extensive your tests are, you are never going to be able to perfectly mock the production environment.</p>\n<p>Enter the End to End testing of newly released <code class=\"language-text\">service-commons-dependencies</code>, more commonly known in AUTO1 from here on out, “E2E testing”.</p>\n<p>To get it done, we need CI pipelines that will automatically test our new versions of release trains that are triggered either manually or automatically every week. All tests need to be as close to the real-world scenarios as possible. A practical solution is to create a new service that will include all of the most popular use cases of the aforementioned libs. Then we need to deploy it to all of our environments - as previously mentioned there is always something different between local, QA, and production environments, so we need to cover them all. The tests must be the same for all environments. But the trigger may differ - for example, we are using our test environments to prepare new releases for production.</p>\n<p>The following diagram illustrates the basic principle of how it should work:</p>\n<p><img src=\"https://lh6.googleusercontent.com/-K5rLPtggaNeQpml856NbA9UyUU6_scnBUgUE_W-RA7MVORz_dYAzrQ_jg7a9vBfQJHqmdosoCH7Evd0dbTF8-kzH0dlygQPeoqQu47__E5Pky0GmeyhlcJ1UWNuQrC7j5s3MZvQhj_EoSgwBA\"></p>\n<p>In our implementation, we chose to use Jenkins with JobDSL pipelines and Groovy for scripting. The first stage of the E2E process is checking whether a new version of service-commons-dependencies exists by using the maven versions plugin:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">mvn -U versions:update-property -Dproperty='service-commons-dependencies.version'</code></pre></div>\n<p>To check for any changes:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">def hasChanges = sh(returnStatus: true, script: \"git diff --exit-code\")</code></pre></div>\n<p>If nothing new was found let’s just abort the pipeline and wait for another CRON or manual trigger.\nIn case a new release was found, we need to build it, deploy it, and run E2E tests.\nIf there are no failures the pipeline will create a new core-test-service release.\nFor those cases, we are using parameterized jobs, for example, to trigger the E2E tests we can use the following commands:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">build(job: 'java/core-svc/core_test_end_to_end_test', parameters: [booleanParam(name: 'SEND_SLACK_NOTIFICATION', value: \"true\"), string(name: 'RELEASE_TRAIN_VERSION', value: service_commons_dependencies_version)])</code></pre></div>\n<p>The new release will be picked up by the production pipeline by checking the latest tag creation time in our repository:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">String latestTagDateString = sh(returnStdout: true, script: \"git rev-list -1 \\$(git describe --abbrev=0 --tags) --pretty=oneline --format=%ci | awk 'NR%2==0'\")\n\ndef proceedWithE2ETesting = wasTagReleasedRecently(latestTagDateString)\n\n@NonCPS\n\n    def wasTagReleasedRecently(String lastTagDateString) {\n\n    def formatter = DateTimeFormatter.ofPattern(\"yyyy-MM-dd HH:mm:ss Z\")\n\n    def lastTagDateTime = OffsetDateTime.parse(lastTagDateString.trim(), formatter)\n\n    def currentTimeMinus2hours = OffsetDateTime.now().minus(2, ChronoUnit.HOURS)\n\n    return lastTagDateTime.isAfter(currentTimeMinus2hours)\n\n}</code></pre></div>\n<p>If the release of core-test-service was created within the last 2 hours we will deploy it by triggering another pipeline. As the last step, it will run E2E tests. As mentioned above, both testing environments will use a shared codebase for acceptance testing. It can be done by setting up one extra job that will fetch an external repository using this block:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">definition {\n      cpsScm {\n          scm {\n              git {\n                  remote {\n                      github(\"core-e2e-tests\", 'ssh')\n                      credentials(\"token\")\n                      branch(\"master\")\n                  }\n                  extensions {\n                      wipeOutWorkspace()\n                  }\n               }\n       }\n\n       scriptPath(\"jenkins/core_e2e_tests.gvy\")\n  }\n}</code></pre></div>\n<p>We chose Cucumber as our main test framework since it will give us unparalleled leverage compared to other choices. Tests are written using natural language in a way that allows for troubleshooting to be done basically at a glance. For example here is the scenario that tests the libraries responsible for sending messages in our platform exposed via HTTP endpoint:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">Scenario: Should have a working API endpoint for creating a message\n\nGiven an object with generated id and message: This is a test\nWhen making a POST call on messaging endpoint with the body containing the given object in JSON representation\nThen should result in a 201 response status code\nAnd should receive an empty body</code></pre></div>\n<p>The above, combined with this generated report, is a joy to work with.\n<img src=\"https://lh5.googleusercontent.com/qyj0MbKLCEPO9M3Q8kalZoXkgfgcxddnmxk6lYUu0DrbBHhT747lCyy1SFhZDHKZXOGwUqcnsDFDPM2_rWAhnWC5l5m58RVcpsWWrBmwHIZgd3tKxSmhC6aqZHsB016Z7MXAhT0EX7mnT_N3_w\"></p>\n<p>Furthermore, we decided to create a dedicated slack channel to notify us about the new releases and test results.</p>\n<p>So after getting this message</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">Sanity checks for new release train X.Y.Z on env:\n\n    * REST API simple entity integration ✅\n    * REST API dated entity integration ✅\n    * REST API auditable entity integration\n    * Messaging integration ✅\n    * Messaging FIFO integration ✅\n    * Storage integration ✅\n    * Health integration ✅\n    * Metrics integration ✅\n    * Logging integration ✅</code></pre></div>\n<p>We can finally get our much-needed stress-free beauty sleep, not that it will help us much, right? Hopefully, this small article will get you in the mood for some nice automation work in your company. Have fun and enjoy your peaceful nights.</p>","fields":{"slug":"/e2e-testing-internal-libraries/","tags":["auto1","engineering","end2end","testing","internallibraries"]}}},{"node":{"id":"19cc0c42-5288-55fa-abfe-4af1aeb242ca","frontmatter":{"category":"Engineering","title":"Rate Limiters and Thread blocking, is there an alternative?","date":"2022-07-18","summary":"There are some cases where you would like to limit the frequency that something happens to it work properly","thumbnail":null,"authorName":"Bruno Morais","authorDescription":"Bruno is a Senior Software Engineer at AUTO1 Group.","authorAvatar":{"relativePath":"pages/rate-limiters/avatar_Morais.jpeg","childImageSharp":{"resolutions":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAUABQDASIAAhEBAxEB/8QAGAABAQEBAQAAAAAAAAAAAAAAAAQDAQX/xAAXAQEBAQEAAAAAAAAAAAAAAAABAwIE/9oADAMBAAIQAxAAAAGmbSadPSZMPIBLBy1//8QAHBAAAwABBQAAAAAAAAAAAAAAAQIDIQAQERIj/9oACAEBAAEFAqOVEql2047LLDc7A+i5H//EABcRAQEBAQAAAAAAAAAAAAAAAAEAEBL/2gAIAQMBAT8BC5jP/8QAGREAAwADAAAAAAAAAAAAAAAAAAECEBET/9oACAECAQE/AW9HSSsf/8QAGhAAAQUBAAAAAAAAAAAAAAAAAQACEBEhQf/aAAgBAQAGPwLBZRa4VFYt5Jj/xAAcEAADAAIDAQAAAAAAAAAAAAAAAREhURAxYXH/2gAIAQEAAT8ho6G+i0ElVBP0c6AzfMaH3OHLLoTIz//aAAwDAQACAAMAAAAQcC98/8QAGREAAwADAAAAAAAAAAAAAAAAABExEFGB/9oACAEDAQE/EGQbRPcf/8QAGxEAAgIDAQAAAAAAAAAAAAAAAAERMVFhscH/2gAIAQIBAT8QuM2dElucejs//8QAGxABAQEBAAMBAAAAAAAAAAAAAREAITFBYXH/2gAIAQEAAT8QEiRCoPrgpVComQJxnQidLcJrAFJfmh7Hwmff5oW4eD07h8orv//Z","width":50,"height":50,"src":"/static/7b4637bf5ab4eaf01facec045622cc5c/d2d31/avatar_Morais.jpeg","srcSet":"/static/7b4637bf5ab4eaf01facec045622cc5c/d2d31/avatar_Morais.jpeg 1x,\n/static/7b4637bf5ab4eaf01facec045622cc5c/0b804/avatar_Morais.jpeg 1.5x,\n/static/7b4637bf5ab4eaf01facec045622cc5c/753c3/avatar_Morais.jpeg 2x,\n/static/7b4637bf5ab4eaf01facec045622cc5c/31ca8/avatar_Morais.jpeg 3x"}}},"headerImage":{"relativePath":"pages/rate-limiters/header_Morais.jpg","childImageSharp":{"resolutions":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAUBAwT/xAAVAQEBAAAAAAAAAAAAAAAAAAABAP/aAAwDAQACEAMQAAABtzsIJMMhP//EABoQAAIDAQEAAAAAAAAAAAAAAAECAAMREBL/2gAIAQEAAQUCNWyxTnkdKrP/xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAVEQEBAAAAAAAAAAAAAAAAAAAAEf/aAAgBAgEBPwFX/8QAGRAAAwADAAAAAAAAAAAAAAAAAAExEBEh/9oACAEBAAY/AuM04TMP/8QAGhAAAgIDAAAAAAAAAAAAAAAAAAERYRAhUf/aAAgBAQABPyFTTBRag4ywx57U/9oADAMBAAIAAwAAABAfP//EABYRAQEBAAAAAAAAAAAAAAAAAAEAEf/aAAgBAwEBPxDZNb//xAAWEQEBAQAAAAAAAAAAAAAAAAAAARH/2gAIAQIBAT8QTD//xAAbEAEBAQEBAAMAAAAAAAAAAAABESEAUTFxsf/aAAgBAQABPxC+laoo/XnLJVVmzJ2YRT5s/eDOI4g51avPO//Z","width":1280,"height":849,"src":"/static/d7fdf1093c10ccf7ff201925fb486d79/966a5/header_Morais.jpg","srcSet":"/static/d7fdf1093c10ccf7ff201925fb486d79/966a5/header_Morais.jpg 1x,\n/static/d7fdf1093c10ccf7ff201925fb486d79/aa36d/header_Morais.jpg 1.5x"}}}},"html":"<p>Let's talk about harmony! If you have a look at an English dictionary, you'll see that even though almost everyone has some knowledge of the meaning of the word harmony, it's not so simple to properly define it. There are many contexts that it may apply, such as people relationships, business, law, and so on.</p>\n<p>But, at the end of the day, this concept imported from the music means that something happens in a way or frequency that makes it pleasant and less error-prone. So I want you to focus on the idea that the proper frequency is a way to achieve harmony.</p>\n<p>There are some cases where you would like to limit the frequency that something happens to it work properly. Imagine that you have a coffee machine, it's obvious that you would like it to dispense coffee at a frequency that you can replace the cups and be able to serve all your guests.</p>\n<p>It happens everywhere, even on software. At least while we have limited resources, we have to orchestrate them to work in harmony. One strategy is to use Rate Limiters, a maneuver to control the frequency in which some action is handled.</p>\n<h2>Rate Limiters</h2>\n<p>A common pattern to achieve the Rate Limiter strategy is to use the Token Bucket algorithm. In a nutshell, the Token Bucket mimics a real bucket where Theme Park tickets are stored. To enter to play around at the Theme Park, you need to take a ticket. But if the bucket is empty, you have to wait until some new tickets are put in there. Doing like that, you become able to control the flow of people to the Theme Park by controlling the number of tickets that are put into the bucket and the time interval in which the refill occurs.</p>\n<p>If we put 10 tickets per minute on that bucket, it'll assure that at most 10 people will enter the Theme Park in each 1-minute interval.</p>\n<p>Libraries like Google Guava, Resilience4j, and Bucket4j are examples of how we can achieve rate-limiting in our Java software.</p>\n<p>Despite being a beta version by the time of this writing, using the Google Guava RateLimiter library is pretty straightforward. You create a RateLimiter object defining the number of permits per second and, for each task, you specify that it should \"acquire\" the token that allows it to proceed.</p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\"><span class=\"token keyword\">final</span> <span class=\"token class-name\">RateLimiter</span> rateLimiter <span class=\"token operator\">=</span> <span class=\"token class-name\">RateLimiter</span><span class=\"token punctuation\">.</span><span class=\"token function\">create</span><span class=\"token punctuation\">(</span><span class=\"token number\">2.0</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// rate is \"2 permits per second\"</span>\n    <span class=\"token keyword\">void</span>  <span class=\"token function\">submitTasks</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">List</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">Runnable</span><span class=\"token punctuation\">></span></span> tasks<span class=\"token punctuation\">,</span> <span class=\"token class-name\">Executor</span> executor<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token class-name\">Runnable</span> task <span class=\"token operator\">:</span> tasks<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        rateLimiter<span class=\"token punctuation\">.</span><span class=\"token function\">acquire</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// may wait</span>\n        executor<span class=\"token punctuation\">.</span><span class=\"token function\">execute</span><span class=\"token punctuation\">(</span>task<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>For Resilience4J you need to create some configuration before and decorate your task:</p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\"> <span class=\"token comment\">// Create a custom RateLimiter configuration</span>\n<span class=\"token class-name\">RateLimiterConfig</span> config <span class=\"token operator\">=</span> <span class=\"token class-name\">RateLimiterConfig</span><span class=\"token punctuation\">.</span><span class=\"token function\">custom</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">.</span><span class=\"token function\">timeoutDuration</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">Duration</span><span class=\"token punctuation\">.</span><span class=\"token function\">ofMillis</span><span class=\"token punctuation\">(</span><span class=\"token number\">100</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">.</span><span class=\"token function\">limitRefreshPeriod</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">Duration</span><span class=\"token punctuation\">.</span><span class=\"token function\">ofSeconds</span><span class=\"token punctuation\">(</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">.</span><span class=\"token function\">limitForPeriod</span><span class=\"token punctuation\">(</span><span class=\"token number\">2</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">.</span><span class=\"token function\">build</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token comment\">// Create a RateLimiter</span>\n<span class=\"token class-name\">RateLimiter</span> rateLimiter <span class=\"token operator\">=</span> <span class=\"token class-name\">RateLimiter</span><span class=\"token punctuation\">.</span><span class=\"token function\">of</span><span class=\"token punctuation\">(</span><span class=\"token operator\">*</span><span class=\"token operator\">*</span><span class=\"token string\">\"backendName\"</span><span class=\"token operator\">*</span><span class=\"token operator\">*</span><span class=\"token punctuation\">,</span> config<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// Decorate your call to BackendService.doSomething()</span>\n<span class=\"token class-name\">Supplier</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">String</span><span class=\"token punctuation\">></span></span> restrictedSupplier <span class=\"token operator\">=</span> <span class=\"token class-name\">RateLimiter</span>\n    <span class=\"token punctuation\">.</span><span class=\"token function\">decorateSupplier</span><span class=\"token punctuation\">(</span>rateLimiter<span class=\"token punctuation\">,</span> backendService<span class=\"token operator\">::</span><span class=\"token function\">doSomething</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// First call is successful</span>\n<span class=\"token class-name\">Try</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">String</span><span class=\"token punctuation\">></span></span> firstTry <span class=\"token operator\">=</span> <span class=\"token class-name\">Try</span><span class=\"token punctuation\">.</span><span class=\"token function\">ofSupplier</span><span class=\"token punctuation\">(</span>restrictedSupplier<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token function\">assertThat</span><span class=\"token punctuation\">(</span>firstTry<span class=\"token punctuation\">.</span><span class=\"token function\">isSuccess</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">isTrue</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>In the same path, now using Bucket4j, you need to specify the refill interval and the limit:</p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\"><span class=\"token class-name\">Refill</span> refill <span class=\"token operator\">=</span> <span class=\"token class-name\">Refill</span><span class=\"token punctuation\">.</span><span class=\"token function\">intervally</span><span class=\"token punctuation\">(</span><span class=\"token number\">2</span><span class=\"token punctuation\">,</span> <span class=\"token class-name\">Duration</span><span class=\"token punctuation\">.</span><span class=\"token function\">ofSeconds</span><span class=\"token punctuation\">(</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token class-name\">Bandwidth</span> limit <span class=\"token operator\">=</span> <span class=\"token class-name\">Bandwidth</span><span class=\"token punctuation\">.</span><span class=\"token function\">classic</span><span class=\"token punctuation\">(</span><span class=\"token number\">2</span><span class=\"token punctuation\">,</span> refill<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token class-name\">Bucket</span> bucket <span class=\"token operator\">=</span> <span class=\"token class-name\">Bucket4j</span><span class=\"token punctuation\">.</span><span class=\"token function\">builder</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">.</span><span class=\"token function\">addLimit</span><span class=\"token punctuation\">(</span>limit<span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">.</span><span class=\"token function\">build</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>bucket<span class=\"token punctuation\">.</span><span class=\"token function\">tryConsume</span><span class=\"token punctuation\">(</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    executor<span class=\"token punctuation\">.</span><span class=\"token function\">execute</span><span class=\"token punctuation\">(</span>task<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>But if you want that the employees from the theme park's main entrance do other tasks while the customers are in the queue and still not allowed to enter, I mean if you want that your thread is used for other tasks, at least these 3 libraries have a pattern that may be a problem to you: they block the thread.</p>\n<h2>Thread Blocking</h2>\n<p>Now we are in the second part of this article, and as we are talking about Threads, it's good to know some basics about them. The first step is to know that they allow us to work concurrently, two tasks running virtually at the same time. But Threads are notoriously complex and error-prone, inaugurating a new sorts of problems like Deadlock, Race Condition, and so on.</p>\n<p>As we said at the start of this article, considering that we have limited resources, we have to use Threads with wisdom and be as clever as possible.</p>\n<p>If I and my wife are in the kitchen and we have just one knife available, it is appropriate that once one of us stop using the knife we leave it available to the other over the table, so that the other could start working with this piece of cutlery.</p>\n<p>When one forgets about this rule, the other one is kept waiting for the tool, and important work is not held, preventing the flow of a harmonious cuisine.</p>\n<p>The computer environment works like this kitchen, we have a limited number of Threads. And when something blocks one thread with a Thread.sleep() or LockSupport.parkNanos(), this Thread goes to the TIMED_WAITING state and during this time it can not be used. It is like the unused knife in the cooker's hand of an unharmonious kitchen.</p>\n<p>In practical terms, consider the following code:</p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\"><span class=\"token keyword\">private</span> <span class=\"token keyword\">void</span> <span class=\"token function\">guavaRateLimiter</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n<span class=\"token class-name\">RateLimiter</span> rateLimiter <span class=\"token operator\">=</span> <span class=\"token class-name\">RateLimiter</span><span class=\"token punctuation\">.</span><span class=\"token function\">create</span><span class=\"token punctuation\">(</span><span class=\"token number\">2</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token function\">logWithThreadTimeStamped</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Starting\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token class-name\">IntStream</span><span class=\"token punctuation\">.</span><span class=\"token function\">rangeClosed</span><span class=\"token punctuation\">(</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token number\">4</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">forEach</span><span class=\"token punctuation\">(</span>i <span class=\"token operator\">-></span> <span class=\"token punctuation\">{</span>\n    rateLimiter<span class=\"token punctuation\">.</span><span class=\"token function\">acquire</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token function\">logWithThreadTimeStamped</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Task n. \"</span> <span class=\"token operator\">+</span> i<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token function\">logWithThreadTimeStamped</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"I'm blocked =(\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token function\">logWithThreadTimeStamped</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Finishing\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>It will output as follow:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">[12:01:31.972073] Starting Thread: main\n[12:01:31.978520] Task n. 1 Thread: main\n[12:01:32.471752] Task n. 2 Thread: main\n[12:01:32.967231] Task n. 3 Thread: main\n[12:01:33.470331] Task n. 4 Thread: main\n[12:01:33.470662] I'm blocked =( Thread: main\n[12:01:33.470845] Finishing Thread: main</code></pre></div>\n<p>What we wanted was that our 4 tasks were completed in a frequency of at most 2 for each second, but the Rate Limiter also has blocked the other tasks.</p>\n<p>You may ask, what to do? Perhaps, we should schedule instead of blocking!</p>\n<h2>Scheduling</h2>\n<p>Imagine when you need to go to the doctor. Unless there is an emergency, you will likely have to make an appointment. The schedules are spread in a timeline, considering the doctor's ability to do the entire checkup: anamnesis, some additional exams, and so on. So to say, if the doctor takes an average of 30 minutes to attend to a patient appointment, those appointments should be guaranteed in intervals of 30 minutes.</p>\n<p>With this in mind, we could refactor our previous code. If we need that our tasks are executed at a rate of 2 per second, it means that we should schedule our tasks for every 500 milliseconds, which is one second (1000 milliseconds) divided by 2.</p>\n<p>Now that we know our interval, we have to find a way to keep track of our \"appointments\", to avoid scheduling more than one task to the same interval. Let's use an AtomicInteger class for that.</p>\n<p>Let's scratch some code:</p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\"><span class=\"token keyword\">private</span> <span class=\"token keyword\">void</span> <span class=\"token function\">taskScheduling</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n<span class=\"token keyword\">var</span> scheduleExecutor <span class=\"token operator\">=</span> <span class=\"token class-name\">Executors</span><span class=\"token punctuation\">.</span><span class=\"token function\">newSingleThreadScheduledExecutor</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">var</span> intervalDiary <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">AtomicInteger</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">var</span> expectedInterval <span class=\"token operator\">=</span> <span class=\"token number\">500</span><span class=\"token punctuation\">;</span>\n<span class=\"token function\">logWithThread</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Starting\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token class-name\">IntStream</span><span class=\"token punctuation\">.</span><span class=\"token function\">rangeClosed</span><span class=\"token punctuation\">(</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token number\">4</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">forEach</span><span class=\"token punctuation\">(</span>i <span class=\"token operator\">-></span> <span class=\"token punctuation\">{</span>\n    scheduleExecutor<span class=\"token punctuation\">.</span><span class=\"token function\">schedule</span><span class=\"token punctuation\">(</span>\n        <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">-></span> <span class=\"token function\">logWithThread</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Task n. \"</span> <span class=\"token operator\">+</span> i<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        intervalDiary<span class=\"token punctuation\">.</span><span class=\"token function\">getAndAdd</span><span class=\"token punctuation\">(</span>expectedInterval<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token class-name\">TimeUnit</span><span class=\"token punctuation\">.</span>MILLISECONDS\n    <span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token function\">logWithThread</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"I'm NOT blocked =D\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token function\">logWithThread</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Finishing\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">private</span> <span class=\"token keyword\">void</span> <span class=\"token function\">logWithThread</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">String</span> message<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token class-name\">System</span><span class=\"token punctuation\">.</span>out<span class=\"token punctuation\">.</span><span class=\"token function\">println</span><span class=\"token punctuation\">(</span>message <span class=\"token operator\">+</span> <span class=\"token string\">\" Thread: \"</span> <span class=\"token operator\">+</span> <span class=\"token class-name\">Thread</span><span class=\"token punctuation\">.</span><span class=\"token function\">currentThread</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">getName</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>It will output as follows:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">Starting - Thread: main\nI'm NOT blocked =D Thread: main\nFinishing - Thread: main\nTask n. 1 - Thread: pool-1-thread-1\nTask n. 2 - Thread: pool-1-thread-1\nTask n. 3 - Thread: pool-1-thread-1\nTask n. 4 - Thread: pool-1-thread-1</code></pre></div>\n<p>Oh, it worked, but seems like we are cheating, because we just added a new thread to the game. How can we know for sure if that new thread is not being blocked? Well, we can test it like this:</p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\"><span class=\"token keyword\">private</span> <span class=\"token keyword\">void</span> <span class=\"token function\">taskSchedulingV2</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n<span class=\"token keyword\">var</span> scheduleExecutor <span class=\"token operator\">=</span> <span class=\"token class-name\">Executors</span><span class=\"token punctuation\">.</span><span class=\"token function\">newSingleThreadScheduledExecutor</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">var</span> intervalDiary <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">AtomicInteger</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">var</span> expectedInterval <span class=\"token operator\">=</span> <span class=\"token number\">500</span><span class=\"token punctuation\">;</span>\nscheduleExecutor<span class=\"token punctuation\">.</span><span class=\"token function\">execute</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">-></span> <span class=\"token function\">logWithThread</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Starting\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token class-name\">IntStream</span><span class=\"token punctuation\">.</span><span class=\"token function\">rangeClosed</span><span class=\"token punctuation\">(</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token number\">4</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">forEach</span><span class=\"token punctuation\">(</span>i <span class=\"token operator\">-></span> <span class=\"token punctuation\">{</span>\n    scheduleExecutor<span class=\"token punctuation\">.</span><span class=\"token function\">schedule</span><span class=\"token punctuation\">(</span>\n        <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">-></span> <span class=\"token function\">logWithThread</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Task n. \"</span> <span class=\"token operator\">+</span> i<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        intervalDiary<span class=\"token punctuation\">.</span><span class=\"token function\">getAndAdd</span><span class=\"token punctuation\">(</span>expectedInterval<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token class-name\">TimeUnit</span><span class=\"token punctuation\">.</span>MILLISECONDS\n    <span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\nscheduleExecutor<span class=\"token punctuation\">.</span><span class=\"token function\">execute</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">-></span> <span class=\"token function\">logWithThread</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"I'm NOT blocked =D\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\nscheduleExecutor<span class=\"token punctuation\">.</span><span class=\"token function\">execute</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">-></span> <span class=\"token function\">logWithThread</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Finishing\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>And voilà:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">Starting Thread: pool-1-thread-1\nTask n. 1 Thread: pool-1-thread-1\nI'm NOT blocked =D Thread: pool-1-thread-1\nFinishing Thread: pool-1-thread-1\nTask n. 2 Thread: pool-1-thread-1\nTask n. 3 Thread: pool-1-thread-1\nTask n. 4 Thread: pool-1-thread-1</code></pre></div>\n<p>The downside of this approach is that the ScheduledExecutorService, that we receive from the newSingleThreadScheduledExecutor() method of the Executors class, uses an unbounded queue. This means that no task will ever be rejected (by the meaning of the unbounded word, it is like an unlimited queue), and because of that, we have the risk of consuming too much memory if we receive tasks more quickly than we can handle them.</p>\n<p>Of course, we can avoid that in many ways. One approach could be to track the number of scheduled tasks and reject new tasks if we hit the specified threshold. First of all, let's refactor our code so that we use a queue of tasks as the source to be used by the scheduler.</p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\"><span class=\"token keyword\">private</span> <span class=\"token keyword\">void</span> <span class=\"token function\">taskSchedulingV3</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n<span class=\"token keyword\">var</span> scheduleExecutor <span class=\"token operator\">=</span> <span class=\"token class-name\">Executors</span><span class=\"token punctuation\">.</span><span class=\"token function\">newSingleThreadScheduledExecutor</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">var</span> myTasks <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">ConcurrentLinkedQueue</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">Runnable</span><span class=\"token punctuation\">></span></span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">var</span> EXPECTED_INTERVAL <span class=\"token operator\">=</span> <span class=\"token number\">500</span><span class=\"token punctuation\">;</span>\nscheduleExecutor<span class=\"token punctuation\">.</span><span class=\"token function\">execute</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">-></span> <span class=\"token function\">logWithThread</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Starting\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\nscheduleExecutor<span class=\"token punctuation\">.</span><span class=\"token function\">scheduleAtFixedRate</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">-></span>\n    <span class=\"token function\">ofNullable</span><span class=\"token punctuation\">(</span>myTasks<span class=\"token punctuation\">.</span><span class=\"token function\">poll</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">ifPresent</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">Runnable</span><span class=\"token operator\">::</span><span class=\"token function\">run</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> EXPECTED_INTERVAL<span class=\"token punctuation\">,</span> <span class=\"token class-name\">TimeUnit</span><span class=\"token punctuation\">.</span>MILLISECONDS\n<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token class-name\">IntStream</span><span class=\"token punctuation\">.</span><span class=\"token function\">rangeClosed</span><span class=\"token punctuation\">(</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token number\">4</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">forEach</span><span class=\"token punctuation\">(</span>i <span class=\"token operator\">-></span>\n    myTasks<span class=\"token punctuation\">.</span><span class=\"token function\">add</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">-></span> <span class=\"token function\">logWithThread</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Task n.\"</span> <span class=\"token operator\">+</span> i<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\nscheduleExecutor<span class=\"token punctuation\">.</span><span class=\"token function\">execute</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">-></span> <span class=\"token function\">logWithThread</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"I'm NOT blocked =D\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\nscheduleExecutor<span class=\"token punctuation\">.</span><span class=\"token function\">execute</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">-></span> <span class=\"token function\">logWithThread</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Finishing\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Our log:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">Starting Thread: pool-1-thread-1\nTask n.1 Thread: pool-1-thread-1\nI'm NOT blocked =D Thread: pool-1-thread-1\nFinishing Thread: pool-1-thread-1\nTask n.2 Thread: pool-1-thread-1\nTask n.3 Thread: pool-1-thread-1\nTask n.4 Thread: pool-1-thread-1</code></pre></div>\n<p>Now in this version, we are using the scheduleAtFixedRate() method, which frees us from keeping track of the already used intervals. It now checks for new tasks for every expected interval.</p>\n<p>But what would happen if we have more tasks coming than we are able to handle? The following code creates a new task for each 250ms but handles new tasks just in an interval of 500ms.</p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\"><span class=\"token keyword\">private</span>  <span class=\"token keyword\">void</span>  <span class=\"token function\">taskSchedulingOverload</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n<span class=\"token keyword\">var</span> scheduleExecutor <span class=\"token operator\">=</span> <span class=\"token class-name\">Executors</span><span class=\"token punctuation\">.</span><span class=\"token function\">newSingleThreadScheduledExecutor</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">var</span> myTasks <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">ConcurrentLinkedQueue</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">Runnable</span><span class=\"token punctuation\">></span></span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">var</span> EXPECTED_INTERVAL <span class=\"token operator\">=</span> <span class=\"token number\">500</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">var</span> SMALLER_INTERVAL <span class=\"token operator\">=</span> <span class=\"token number\">250</span><span class=\"token punctuation\">;</span>\nscheduleExecutor<span class=\"token punctuation\">.</span><span class=\"token function\">execute</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">-></span> <span class=\"token function\">logWithThread</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Starting\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\nscheduleExecutor<span class=\"token punctuation\">.</span><span class=\"token function\">scheduleAtFixedRate</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">-></span>\n    <span class=\"token function\">ofNullable</span><span class=\"token punctuation\">(</span>myTasks<span class=\"token punctuation\">.</span><span class=\"token function\">poll</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">ifPresent</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">Runnable</span><span class=\"token operator\">::</span><span class=\"token function\">run</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> EXPECTED_INTERVAL<span class=\"token punctuation\">,</span> <span class=\"token class-name\">TimeUnit</span><span class=\"token punctuation\">.</span>MILLISECONDS\n<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n\nscheduleExecutor<span class=\"token punctuation\">.</span><span class=\"token function\">scheduleAtFixedRate</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">-></span>\n    myTasks<span class=\"token punctuation\">.</span><span class=\"token function\">add</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">-></span> <span class=\"token function\">logWithThread</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Fast Task! Task lasting: \"</span> <span class=\"token operator\">+</span> myTasks<span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> SMALLER_INTERVAL<span class=\"token punctuation\">,</span> <span class=\"token class-name\">TimeUnit</span><span class=\"token punctuation\">.</span>MILLISECONDS\n<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n\nscheduleExecutor<span class=\"token punctuation\">.</span><span class=\"token function\">execute</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">-></span> <span class=\"token function\">logWithThread</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"I'm NOT blocked =D\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\nscheduleExecutor<span class=\"token punctuation\">.</span><span class=\"token function\">execute</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">-></span> <span class=\"token function\">logWithThread</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Finishing\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Our output would be something like this:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">Starting Thread: pool-1-thread-1\nI'm NOT blocked =D Thread: pool-1-thread-1\nFinishing Thread: pool-1-thread-1\nFast Task! Task lasting: 1 Thread: pool-1-thread-1\nFast Task! Task lasting: 2 Thread: pool-1-thread-1\nFast Task! Task lasting: 3 Thread: pool-1-thread-1\nFast Task! Task lasting: 4 Thread: pool-1-thread-1\nFast Task! Task lasting: 5 Thread: pool-1-thread-1\nFast Task! Task lasting: 6 Thread: pool-1-thread-1\nFast Task! Task lasting: 7 Thread: pool-1-thread-1\nFast Task! Task lasting: 8 Thread: pool-1-thread-1\nFast Task! Task lasting: 9 Thread: pool-1-thread-1\n\n(...)</code></pre></div>\n<p>The size of the queue will not stop raising, leading us to an out-of-memory error. Oh, but don't be so afraid my friend, as we said we can limit the schedule based on that queue. Like if you call the doctor to make an appointment and they answer you: \"sorry, for the next 10 years all our schedules are already taken, please call in another day (or year).\"</p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\"><span class=\"token keyword\">private</span>  <span class=\"token keyword\">void</span>  <span class=\"token function\">taskSchedulingLimitingByQueueSize</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n<span class=\"token keyword\">var</span> scheduleExecutor <span class=\"token operator\">=</span> <span class=\"token class-name\">Executors</span><span class=\"token punctuation\">.</span><span class=\"token function\">newSingleThreadScheduledExecutor</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">var</span> myTasks <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">ConcurrentLinkedQueue</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">Runnable</span><span class=\"token punctuation\">></span></span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">var</span> EXPECTED_INTERVAL <span class=\"token operator\">=</span> <span class=\"token number\">500</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">var</span> SMALLER_INTERVAL <span class=\"token operator\">=</span> <span class=\"token number\">250</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">var</span> QUEUE_LIMIT <span class=\"token operator\">=</span> <span class=\"token number\">4</span><span class=\"token punctuation\">;</span>\nscheduleExecutor<span class=\"token punctuation\">.</span><span class=\"token function\">execute</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">-></span> <span class=\"token function\">logWithThread</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Starting\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\nscheduleExecutor<span class=\"token punctuation\">.</span><span class=\"token function\">scheduleAtFixedRate</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">-></span>\n    <span class=\"token function\">ofNullable</span><span class=\"token punctuation\">(</span>myTasks<span class=\"token punctuation\">.</span><span class=\"token function\">poll</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">ifPresent</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">Runnable</span><span class=\"token operator\">::</span><span class=\"token function\">run</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> EXPECTED_INTERVAL<span class=\"token punctuation\">,</span> <span class=\"token class-name\">TimeUnit</span><span class=\"token punctuation\">.</span>MILLISECONDS\n<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n\nscheduleExecutor<span class=\"token punctuation\">.</span><span class=\"token function\">scheduleAtFixedRate</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">-></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>myTasks<span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">&lt;</span> QUEUE_LIMIT<span class=\"token punctuation\">)</span>\n        myTasks<span class=\"token punctuation\">.</span><span class=\"token function\">add</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">-></span> <span class=\"token function\">logWithThread</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Fast Task! Task lasting: \"</span> <span class=\"token operator\">+</span> myTasks<span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">else</span>\n        <span class=\"token function\">logWithThread</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"I was rejected =(\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> SMALLER_INTERVAL<span class=\"token punctuation\">,</span> <span class=\"token class-name\">TimeUnit</span><span class=\"token punctuation\">.</span>MILLISECONDS\n<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\nscheduleExecutor<span class=\"token punctuation\">.</span><span class=\"token function\">execute</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">-></span> <span class=\"token function\">logWithThread</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"I'm NOT blocked =D\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\nscheduleExecutor<span class=\"token punctuation\">.</span><span class=\"token function\">execute</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">-></span> <span class=\"token function\">logWithThread</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Finishing\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Our output:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">Starting Thread: pool-1-thread-1\nI'm NOT blocked =D Thread: pool-1-thread-1\nFinishing Thread: pool-1-thread-1\nFast Task! Task lasting: 1 Thread: pool-1-thread-1\nFast Task! Task lasting: 2 Thread: pool-1-thread-1\nFast Task! Task lasting: 3 Thread: pool-1-thread-1\nI was rejected =( Thread: pool-1-thread-1\nFast Task! Task lasting: 3 Thread: pool-1-thread-1\nI was rejected =( Thread: pool-1-thread-1\nFast Task! Task lasting: 3 Thread: pool-1-thread-1\nI was rejected =( Thread: pool-1-thread-1\nFast Task! Task lasting: 3 Thread: pool-1-thread-1</code></pre></div>\n<p>Here we have to talk about backpressure. Remember that this problem about memory only occurs if always the input of tasks is faster than the output. If the input of tasks was faster in just a point of time, this surplus of tasks will be kept on the queue and properly handled in the following time. So with this approach, our application could control the rate of events so that fast producers (sending new tasks) does not overwhelm our consumer.</p>\n<p>In a blocking approach, the producer will be forced to wait. In the scheduling approach, the new tasks will be handled in time, and only if it overloads that some of them will be queued.</p>\n<p>You could say, but how long should be my queue? Well, I may say that it depends on your use case. A doctor could have a schedule book for all the current year. And if it shows to be not enough, the doctor can buy a new schedule book for the next year. As in your application service, if you can afford more memory, your queues can be as long as you want.</p>\n<p>But in the case of a traveling circus, if it will be in the town for just 3 weeks it doesn't make sense to accept schedules for the next month. The same as your application, if its capacity of handling tasks isn't fast enough at a point that the handling of an older schedule task starts to become unmeaningful, you should shrink your queue.</p>\n<h2>Conclusion</h2>\n<p>We can conclude that scheduling is a good approach for rate-limiting without the downside of blocking the thread. It gives us the opportunity of controlling the flow of incoming tasks, queueing peaks, and always handle the tasks in harmony with all other components.</p>","fields":{"slug":"/rate-limiters/","tags":["auto1","engineering","RateLimiter","Thread","Scheduling"]}}},{"node":{"id":"91a0b82d-55ee-5f65-88a2-165a2e1c5a81","frontmatter":{"category":"Engineering","title":"Functional style MDC","date":"2022-05-20","summary":"Mapped Diagnostic Context for everyone","thumbnail":null,"authorName":"Adam Seretny","authorDescription":"Adam is a Senior Software Engineer in our Katowice office.","authorAvatar":{"relativePath":"pages/functional-style-mdc/adam.png","childImageSharp":{"resolutions":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAIAAAAC64paAAAACXBIWXMAAA7CAAAOwgEVKEqAAAAEL0lEQVQ4y2XTW0yaZxgHcNOrmW6rRWjl+4BkN0uXNbqtq3ZpxrTOuRY7sUzBAwcR5KgoIKicz2cKioeIVu3qiWkr2mpBPE1AtNJVi2czd9F0SZvsYsmSLbsZziZTmzx3b37v+3/e5J8AKK3xSZGbUuTmFJUVrnUg9Y4Mfg2GRsjG5VD55em3m6C6JoTOAeicoPY2qLEDKtuhSniDZUa43AQozHCdI43NwmR/cgN98asrFzJSUeya0s8creeVNoTahlDZQJX1kPyP4VJ9fACFBamwXP766qULQH5mGvt7dPGNjOxPURhGGVLjQMiMCLkJoTCBCvMxDMSlVB+/FSUxoLMu8/HZHlONv7VxoVs9aKq5/sVHqAomQmZCNmqRMj0Yz3gstkgJFynA+DFXyMLnBFokK0P21fvO56Oul8GhQR0LkX4JFKmR9RqkRHcCW2AMPozChlXyPySWO+tI/ubGpbumaL/56YBl19+77XXl5l1LZghRYg2yXh3Pfwwnk1kQHPFsIRWFwTqEpAm7ONilezZkjw7YF3rNm6PN1Xzqe+QqlECBFKlBqeEtXFB2toAIz/pGTr/FI+TirqbOtUkeaDml6FSvva5Nzf2Yzj3HqUcKFKDkBCaxkrFl7+YVf55f0CEkGemFldnpD7WcUJu8v7Fy2eNc7FTmcHlJNAGqVoY4hhWWZCITii05nUf4srhk0sjzKtl3uAS/oXZnpHnjx6a9xz2rw67UCjaUVouqlZ7E0DjGlcFwRFh+saGBO28VullFEwZBbMAeG3G9mOsvlza8T6CDDCGi5q2XoWQWtIhynkB952ZJIZM2aeGbKgp66iuCXfrwD6bnj9xpdM6ZUibAFoN8GSjRA0rbkdgkJqSIAsNTzxSUXSSQ3Eq2iYjpImN9ck6kR+vpsQKl9HOUqhS2GDjAhiNYaYUQGUk3CZD8kiRM4Sn0DUE15Z6YPNxAi3Rp93zulnZzwnU8lMSBs0RwngRo0B12481vQ/Dlp7Mwp65kJWZk5lXxHOo6XSVuUFvt69SGh1uW5scrmtoAMjuxhJlMFwBizRGssCTmYiHoa5lUmqbZOTI5Njpyz8wjdevr5odaF4fbnz2Z23/123g4zGjp+IAlgFRLQLX9AIMqW7zJWIm009MXWAxOzAZ6Pf3TS6EBl27MpVmd6G+VVm3t7zzZiD3dWF/b3ZqIhL9zuaEyc7xFCXClFamy3Znyr26t+8Oh+/7Hg2MPppYjM6H5Dq1IiP92oLf99d9/zi5Fopsbi2trsc2YbPRhksQY7/YBBpXWu9OB7V92A6Hgo+mp8Slf8OdoOLbmbDLVcyl//PPXi99fh1ai63vbm7/u/zQ/W9vngcjMCNV/O4NKS8fMbGg91uf3DQamhgIB72LYPeYVWo3e5cjaq5fhnS3fSjS+88L2lnd2ht7dd4j/BfAXIxQ37XYMAAAAAElFTkSuQmCC","width":50,"height":50,"src":"/static/37b7f8651bdc618080e3838b6beeb39a/45876/adam.png","srcSet":"/static/37b7f8651bdc618080e3838b6beeb39a/45876/adam.png 1x,\n/static/37b7f8651bdc618080e3838b6beeb39a/eb85b/adam.png 1.5x,\n/static/37b7f8651bdc618080e3838b6beeb39a/4f71c/adam.png 2x,\n/static/37b7f8651bdc618080e3838b6beeb39a/9ec3e/adam.png 3x"}}},"headerImage":null},"html":"<h1>Logging with MDC in functional style</h1>\n<h2>Introduction</h2>\n<p>If you are already familiar with MDC (Mapped Diagnostic Context) you can go to the next section of this article. If not, please take a look at <a href=\"https://www.baeldung.com/mdc-in-log4j-2-logback\">this</a> first to get a better understanding of what MDC is.</p>\n<h2>Use case</h2>\n<p>In one of our services we had an endpoint responsible for invoking process related to car auction with a lot of logs for debugging purposes. We already had a request-id to trace it in Kibana, but we wanted to filter logs in a more convenient way, by value that we know even before invoking this endpoint which was the stock number of the car. So we decided to use MDC as it allows us to add diagnostic key-value pairs to every log in given Thread.</p>\n<h2>MDC code drawbacks</h2>\n<p>Although MDC is a great tool, it forces programmers to write clunky code due to the fact that every key-value pair that was set should be cleared, otherwise in some edge cases it could be used by another thread.</p>\n<p>Clearing can be done by invoking MDC.clear() or by MDC.remove(key). First one clears all MDC keys so we could accidentally remove keys that were set higher in stack. Second one is better then but it has to be invoked for every key. And also in both cases it should be done in finally block to be sure that no matter what happened, context was cleared.</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">try {\n  MDC.put(\"key1\", \"value1\");\n  MDC.put(\"key1\", \"value2\");\n  //some process\n  log.info(\"very important log\");\n}finally {\n  MDC.remove(\"key1\");\n  MDC.remove(\"key2\");\n}</code></pre></div>\n<p>MDC also has <code class=\"language-text\">method putCloseable(key, value)</code> which returns <code class=\"language-text\">AutoClosable object</code> but it allows only one key-value pair and has to be assigned to a variable, which may look better for a single key but it is not perfect. IDE will complain about never used variable</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">try (MDC.MDCCloseable closeable = MDC.putCloseable(\"key\", \"value\")) {\n  //some process\n  log.info(\"very important log\");\n}</code></pre></div>\n<h2>Solution</h2>\n<p>To stand against MDC drawbacks, we came up with this functional style solution:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">LogContext.withLogKey(\"key1\", \"value1\")\n  .andKey(\"key2\", \"value2\")\n  .andKey(\"key3\", \"value3\")\n  .execute(() -> {\n    // some process\n    log.info(\"very important log\");\n  });</code></pre></div>\n<p>At first glance we can see that there is no <em>Try Catch</em> block anymore and we are only setting key-value pairs and not clearing them, however everything works exactly the same. So how is it done?</p>\n<p>Solution is pretty simple. It is based on a container class for storing MDC context keys mixed with <a href=\"https://www.svlada.com/step-builder-pattern/\"><em>Step Builder Pattern</em></a>. Let's take a look at implementation.</p>\n<h3>LogContextSteps</h3>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">@NoArgsConstructor(access = AccessLevel.PRIVATE)\npublic  final  class  LogContextSteps {\n\n  public  interface  ContextStep {\n    ExecuteStep andKey(final String key, final Object value);\n  }\n\n  public  interface  ExecuteStep  extends  ContextStep {\n\n    &lt;T> T execute(final Supplier&lt;T> action);\n\n    default  void  execute(final Runnable action) {\n      if (action == null) {\n        throw  new IllegalArgumentException(\"Action for execution cannot be null.\");\n      }\n\n      execute(() -> {\n        action.run();\n        return  null;\n      });\n    }\n  }\n}</code></pre></div>\n<p><strong>LogContextSteps</strong> is a wrapping class for two step interfaces:</p>\n<ul>\n<li>\n<p><strong>ContextStep</strong> which contains method for adding new log key-value pair</p>\n</li>\n<li>\n<p><strong>ExecuteStep</strong> which also extends ContextStep and serves execute method responsible for invoking action that we want to wrap with MDC.</p>\n</li>\n</ul>\n<h3>LogContext</h3>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">public  class  LogContext  implements  ContextStep, ExecuteStep {\n  private  static  final MDCLogContextSetter MDC_LOG_CONTEXT_SETTER = new MDCLogContextSetter();\n\n  private  final LogContextSetter contextSetter;\n  private  final Set&lt;String> contextKeys = new HashSet&lt;>();\n\n  private  LogContext(final LogContextSetter contextSetter) {\n    this.contextSetter = contextSetter;\n  }\n\n  public  static ExecuteStep withLogKey(String key, Object value) {\n    return withContextSetter(MDC_LOG_CONTEXT_SETTER).andKey(key,value);\n  }\n\n  static ExecuteStep withContextSetter(LogContextSetter contextSetter){\n    return  new LogContext(contextSetter);\n  }\n\n  @Override\n  public ExecuteStep andKey(String key, Object value) {\n    contextSetter.put(key, value);\n    contextKeys.add(key);\n    return  this;\n  }\n\n  @Override\n  public &lt;T> T execute(final Supplier&lt;T> action) {\n    if (action == null) {\n      throw  new IllegalArgumentException(\"Action for execution cannot be null.\");\n    }\n\n    try {\n      return action.get();\n    } finally {\n      contextKeys.forEach(contextSetter::remove);\n    }\n  }\n\n  interface  LogContextSetter {\n\n    void  remove(final String key);\n\n    void  put(final String key, final Object value);\n  }\n\n  private  static  class  MDCLogContextSetter  implements  LogContextSetter {\n\n    @Override\n    public  void  remove(String key) {\n      MDC.remove(key);\n    }\n\n    @Override\n    public  void  put(String key, Object value) {\n      MDC.put(key, Objects.toString(value));\n    }\n  }\n}</code></pre></div>\n<p><strong><code class=\"language-text\">LogContext</code></strong> is our main class here. It:</p>\n<ul>\n<li>\n<p>implements interfaces from <strong><code class=\"language-text\">LogContextSteps</code></strong></p>\n</li>\n<li>\n<p>stores MDC keys in <code class=\"language-text\">Set</code></p>\n</li>\n<li>\n<p>executes action that we want to wrap with MDC context</p>\n</li>\n</ul>\n<p>For testing purposes there are some package protected classes and methods like <strong><code class=\"language-text\">LogContextSetter</code></strong> interface and its implementation <strong><code class=\"language-text\">MDCLogContextSetter</code></strong>, as it would be hard to test static methods of MDC class.</p>\n<p><strong>So, how does this flow work?</strong></p>\n<p>We begin with the static factory method <code class=\"language-text\">LogContext.withLogKey</code>(\"key1\", \"value1\") which sets up our <strong><code class=\"language-text\">MDCLogContextSetter</code></strong> and invokes the <code class=\"language-text\">andKey</code>(\"key2\", \"value2\") method for the first time. Then we can chain next invocations of <code class=\"language-text\">andKey</code> where every invocation causes two things:</p>\n<ul>\n<li>\n<p>MDC <em>key</em> is stored in <code class=\"language-text\">Set&lt;String> contextKeys</code> as only keys are needed to clear context</p>\n</li>\n<li>\n<p><strong><code class=\"language-text\">LogContextSetter::put</code></strong> method is invoked where implementation is: <code class=\"language-text\">MDC.put(key, Objects.toString(value))</code> and at that moment <em>key-value</em> is stored in MDC</p>\n</li>\n</ul>\n<p>Finally we can invoke <code class=\"language-text\">execute(()</code> -> <code class=\"language-text\">action())</code> which is classic <em>try-finally</em> block where <em>try</em> invokes our <em>action</em> and <em>finally</em> clears MDC iterating every through <code class=\"language-text\">contextKeys</code> and invoking <strong><code class=\"language-text\">LogContextSetter::remove</code></strong> where implementation id <code class=\"language-text\">MDC.remove(key)</code></p>\n<h2>Practical usage (filtering in Kibana)</h2>\n<p>Assuming that we have an ELK stack for monitoring and proper log configuration we can go to Kibana to find interesting logs via our MDC <em>key-value</em> pairs. Depending on the log configuration, <em>key</em> can be directly accessible or under the <strong>flat</strong> field (which was in our case)</p>\n<p>For <em>key-value</em> pair: <strong>stock-number - SN12356</strong> Kibana filter may look like this:</p>\n<p><img src=\"https://lh6.googleusercontent.com/F4M8xRSQWe86JzTN8G5uPIc62Y_uNhPB-_YDLlhHtTpy0PseDIX7fb8_jh37YbpVQEIJiy4gE76vP0eqkU5jjHKOeac5h3tprc52Iz2oQvv0Ros5AHC00DqsW_YZ6H_hXWdJ0yPe6evaU3Ir7Q\"></p>","fields":{"slug":"/functional-style-mdc/","tags":["auto1","engineering","java"]}}},{"node":{"id":"b22a99d0-7b45-5941-bfd1-051c13fa44cc","frontmatter":{"category":"Engineering","title":"Embedded libraries with Mac on the M1 chip","date":"2022-04-30","summary":"Are you running a Mac(book) with the M1 chip? Ran into issues?","thumbnail":null,"authorName":"Ihor Sila","authorDescription":"Ihor is a Senior Software Engineer in our Berlin office.","authorAvatar":{"relativePath":"pages/embedded-libraries/ihor.png","childImageSharp":{"resolutions":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAbCAIAAADzvTiPAAAACXBIWXMAABYlAAAWJQFJUiTwAAAFqklEQVQ4y13P+U+TdxwH8CfZsmTZD8uyZL+YbNmGLnHLvJgiinIVQYEiMGi5W+oBSjnLPY61AxEPFAQt99kKFMrRp7T0sBQK5ailhZ7P8X2eAorL/oc9D6hLlrzyzvunz/v7hRwIcGMkxUlBaQ6Mto1SCMoWQm55KVQhbF6f3eOzeQi7B9i8BORCgRcnPTTiAOnGSRcF+4/zAwdGONBDJAXyYDgKCAQQ3vfIjzwfkkYfJSiuQxiFhBAMwwiAfgSoJA6Q/4MQpJcgaAAczkAoRhUcBzhO0LD3BeAEgZME7iOAjwQkSXeSxEjiAKD2qAKhqBsA5ABKJ0F9AiNICk76AIXwgd29nbf7bwj6EKCR+AEAocg2gXveAx6S8JL00xCSRHw+lMr9d7texLViXtr/e3dnFxz+ANBQCHVtAtRBHMKcFBK4SNxFEi6q7L/FX1tM0aEXQk780FBf+eYNAMBFw10E4YYw9ybw2nGPDfdu4ogNeG0EYifRLRLboso/7wAsGyyNDpipTilMCtnYWNrzuXCU2rMDzA6tGdXbr02o04I41lHXBgVzb+AeC81t2d/1wNJuQaR/Jy/qZTnbtjIPECviXEVda6h7HeoRP91Y1m1bVxxWk2PT5LItu2wmt33Zs7Xstpt8uH1OKi4OPdnDZaib+W6rwWkzOqyvnFaDy7YAKRRy06LeZNTp4ZfmJa15SbNm0q0v6ywrtM11g9kIF8YHN7P81V31G6t6s2Fm1Ti7uqBYX4QhlVat1qnVmjm1RgGrpkZGxfpXKq1WqdfBOp1Cp1UoZ8aL2YzHnMvm4UbLqkYNj87Ih5QzI6pZCTQ1MzELT8AapZKmUKinVVp4bn4WVk/Dc1Nz8OTYy8H56YHXRhnqXLKa1RazRq+V9/e1SyRd0Ki0d0zaPTE1KpuUyqfHJukimZRLJ6ekctmQRj29aFBSg8tGhWVZaVlWOa061GEQi5+0dzyCBturhzuqx7trJR2VvS2CnidlPS3l3S0Vkk5Rb8e9ifGh9RXVmkkBT49YV+fcmyqLUerz6F+0CiuKb0FDrcUDLXmSVn67iNt57+b4izJZZ0X3g7tt9ZzuNlHPi8dri1MrryZkIx0m7YjXKl+Y635Lmntaq3isYKgoN36gtURYmtLyJ6+rKVfSlt/zME/cfLe76UZpWkRTJX/DpDAbJvXKQbN2wGaStldmTQk5ZVnhsVdOQ7UlSfJBUetfeV33bv5R/LuwLK3kdsyNNEbFncSkX78RFnDNS7MmvcyyNInaFGb9QFHMmcarx5r4ceWFbKiCz3xcm1V8i1mXn5yTHvGsgV8rSGHGBKREnc0MPPr0Xo1BM27Ujjks8I5HY1sZE6QyhNG/dFaxCnOioaCLfiHn/bJSgkWV6cLiFEEuMzMtLCkxJOL0d/y4S0P9nWrFsF41gjjmdxDt1upESUZUc+KpOh4jIfY8JCiIrSplNdTxHtwvKihKb2rk9z+vHh0QZcf457OuDvY/V8h7DRqJd0u1h+nVkx23GSceJvtzkkKZzGDocrAfM/pcsyhP/Kj0YS1P2isc6axRjTXWZoY0lPMnJiSjw2169aDDMrOHLfS11uSFHa9K/O1sgF9A4I9QGCOAkx5aVZhanht/J/0KO/Ealx3VUM4qSzjTwImWjfYpp3qWtIN2swx3akUl3JLwo2nR/tfjgrJTL0GMK5dLClI56TEBgT8nxIeEh59hxV0UCVh1d69lMPwz2XGCinzpcJsK7nvcUpdz7ez9zKCc7Kh45mku+zzEyUx82pD7qJ4bywj0P3H8yLefxkWeEtyKrS1Oup6VeT2bFxp3PT6dzeRwIy6cro48NnI/h8eN+uRz6NjxryBhTb70WX6rMKO+6jY3OzUiLODSuZ+yk4Or8hPi01jMzIzIxPiErPTQ39m8sJNibtDz+wXs5OAvv/7syPdf/AtdJiDMRTPZsgAAAABJRU5ErkJggg==","width":50,"height":50,"src":"/static/be35f8628e2a3806d381d258ef13d02a/45876/ihor.png","srcSet":"/static/be35f8628e2a3806d381d258ef13d02a/45876/ihor.png 1x,\n/static/be35f8628e2a3806d381d258ef13d02a/eb85b/ihor.png 1.5x,\n/static/be35f8628e2a3806d381d258ef13d02a/4f71c/ihor.png 2x,\n/static/be35f8628e2a3806d381d258ef13d02a/9ec3e/ihor.png 3x"}}},"headerImage":null},"html":"<h2>MacBook with ARM chip and embedded-libraries problems</h2>\n<p>Hello everyone, my name is Ihor Sila and I'm a Senior Software Engineer in AUTO1, with over 6 years of developing experience. When I joined AUTO1, I received my laptop and I found out that it's a new MacBook Pro with M1 processor and I believe that's really great, because I've read a lot of articles about this chip's performance and comparisons with Intel i-core series. However when I've tried to build microservices that my team presented to me, I found some unusual situations with tests, which are working with embedded libraries such as redis and postgres.</p>\n<h3>Embedded-postgres problems</h3>\n<h4>Problem</h4>\n<p>When I've run first time integration-tests that using embedded-postgres library, I've got next exception in stack trace:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\"> Factory method 'postgres' threw  exception; nested exception is\n java.lang.IllegalStateException: Process\n [/var/folders/61/ls8bv20x4w3fsn3wpm8dlpfm0000gp/T/embedded-pg/\n PG-0c0585587b40695247cf72650cd42f92/bin/initdb</code></pre></div>\n<h4>Solution</h4>\n<p>With the postgres problem, the solution was pretty simple and after I found it in our Slack channel I applied it and it solved the problem. So, when you are setting up your Mac, please check the environment variables and switch locale to en_US.UTF-8 from default one, because the embedded postgres library tries to start its library with a different locale and has problems with the process id. Another solution is to increase the size of a single shared memory segment a Linux process can allocate. So the commands in terminal will be the next</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">sudo sysctl kern.sysv.shmmax=104857600\nsudo sysctl kern.sysv.shmall=25600\nsudo sysctl kern.sysv.shmmin=1\nsudo sysctl kern.sysv.shmmni=10240\nsudo sysctl kern.sysv.shmseg=4096\n\nexport LC_NUMERIC=en_US.UTF-8\nexport LC_MONETARY=en_US.UTF-8\nexport LC_TIME=en_US.UTF-8\nexport LC_ALL=en_US.UTF-8\nexport LC_COLLATE=en_US.UTF-8\nexport LC_MESSAGES=en_US.UTF-8\nexport LC_CTYPE=en_US.UTF-8\nexport LANG=en_US.UTF-8</code></pre></div>\n<p>And that you should restart your MacBook to apply all settings. After that the problem should gone.</p>\n<h3>Embedded-redis problems</h3>\n<h4>Problem</h4>\n<p>Moving on to redis, the problem was that it was newly added to AUTO1. So, from a code perspective everything is fine, but when you try to run the integration tests that are using embedded redis, they just won't be executed, because redis doesn't want to start. There is some exception log that you receive but that's about it, nothing special.</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">java.lang.RuntimeException: Can't start redis server. Check\nlogs for details.\n\nat\nredis.embedded.AbstractRedisInstance.awaitRedisServerReady\n(AbstractRedisInstance.java:61)\nat\nredis.embedded.AbstractRedisInstance.start\n(AbstractRedisInstance.java:39)\nat redis.embedded.RedisServer.start(RedisServer.java:9)\nat\nwkda.common.distributed.cache.redis.EmbeddedSingleRedisServer\n.before(EmbeddedSingleRedisServer.java:48)\nat org.springframework.test.context.junit4.SpringJUnit4ClassRunner\n.run(SpringJUnit4ClassRunner.java:190)</code></pre></div>\n<h4>Deep diving into problem</h4>\n<p>When I've tried to debug the library code, it also appeared fine from a first look, but when I've debugged the stack trace of the startup, I've realized that this old version of redis doesn't know anything about the new M1 architecture and that macOS can be built on something different other than an Intel chip.</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">=== REDIS BUG REPORT START: Cut &amp; paste starting  from here ===\n30203:M 15 Feb 14:01:14.039 # Redis 3.2.4 crashed by signal: 10\n30203:M 15 Feb 14:01:14.040 # Crashed running the instuction\nat: 0x7fff20406440\n30203:M 15 Feb 14:01:14.040 # Accessing address: 0x305685000\n30203:M 15 Feb 14:01:14.040 # Failed  assertion: &lt;no\nassertion  failed> (&lt;no  file>:0)\n\n------ STACK TRACE ------\nEIP:\n0 libsystem_platform.dylib 0x00007fff20406440\n_platform_memset$VARIANT$Rosetta + 108\n\nBacktrace:\n0 redis-server.app 0x0000000100a70a7e logStackTrace + 110\n1 redis-server.app 0x0000000100a70e4d sigsegvHandler + 253\n2 libsystem_platform.dylib 0x00007fff20403d7d _sigtramp + 29\n3 ??? 0x00000001091c1200  0x0 + 4447801856\n4 ??? 0x31207070612e7265  0x0 + 3539952935082291813</code></pre></div>\n<p>Basically, old redis library only knows that macOS can be either x86 or x86_64. After a thorough investigation, I realized that there is no solution yet and repositories that provide embedded redis solutions haven't updated their libraries so far.</p>\n<h4>Solution</h4>\n<p>The solution to this problem consists of two parts:</p>\n<ol>\n<li>The first part is to somehow find the redis application that can be started up on both macOS with M1 chip and on Intel chip, gracefully.</li>\n<li>The second one is to replace the old redis-application with a new one.</li>\n</ol>\n<p>To solve the first problem, I thought that I could just download the latest redis-server, then get the application file from the library folder and replace the old app file with the new one. Soon after the first try I've realized that my solution will work only for M1 chips, therefore no compatibility with the Intel chipped Macs.</p>\n<p>I've dived deeper into the redis library to understand how it knows which architecture (x86 or x86_64) it needs to use. The solution was pretty simple, it just executes the command to get system flags and then analyzes these flags to see which version to use. When I executed the same command on my local machine, I realized that on M1 architecture some new flags were added, which represents that the current architecture is written with a new chip. In embedded redis you can tell redis to use another embedded redis application, but not the solution from the library.</p>\n<p>If you execute next command at the terminal, you will found extra flags for AMD architecture:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">sysctl -a | grep hw.optional\n\n------- Result -------\n\nhw.optional.amx_version: 2\nhw.optional.arm64: 1\nhw.optional.armv8_1_atomics: 1\nhw.optional.armv8_2_fhm: 1\nhw.optional.armv8_2_sha3: 1\nhw.optional.armv8_2_sha512: 1\nhw.optional.armv8_crc32: 1\nhw.optional.breakpoint: 6\nhw.optional.floatingpoint: 1\nhw.optional.neon: 1\nhw.optional.neon_fp16: 1\nhw.optional.neon_hpfp: 1\nhw.optional.ucnormal_mem: 1\nhw.optional.watchpoint: 4</code></pre></div>\n<p>But if you will execute the same command on Intel-based architecture, you will see another flags, that are specific for Intel architecture:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">sysctl -a | grep hw.optional\nhw.optional.floatingpoint: 1\nhw.optional.mmx: 1\nhw.optional.sse: 1\nhw.optional.sse2: 1\nhw.optional.sse3: 1\nhw.optional.supplementalsse3: 1\nhw.optional.sse4_1: 1\nhw.optional.sse4_2: 1\nhw.optional.x86_64: 1\nhw.optional.aes: 1\nhw.optional.avx1_0: 1\nhw.optional.rdrand: 1\nhw.optional.f16c: 1\nhw.optional.enfstrg: 1\nhw.optional.fma: 1\nhw.optional.avx2_0: 1\nhw.optional.bmi1: 1\nhw.optional.bmi2: 1\nhw.optional.rtm: 0\nhw.optional.hle: 0\nhw.optional.adx: 1\nhw.optional.mpx: 0\nhw.optional.sgx: 0\nhw.optional.avx512f: 0\nhw.optional.avx512cd: 0\nhw.optional.avx512dq: 0\nhw.optional.avx512bw: 0\nhw.optional.avx512vl: 0\nhw.optional.avx512ifma: 0\nhw.optional.avx512vbmi: 0</code></pre></div>\n<p>After realizing that, we created a class so that we can tell the library the fact that if the OS is macOS, then it needs to analyze the system flags. If it will find M1-specific flags (which are not present on Intel architecture), then use the latest redis application file which can be executed on macOS with M1(AMD) architecture, otherwise use the existing solution, because it's working on macOS with Intel processor. We also should store this application file in our resource folder, so in that case new developers can just download the source code and the redis application file will be already there.</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">protected  void before() {\nRedisExecProvider provider = RedisExecProvider.defaultProvider()\n.override(OS.UNIX, \"redis-server/redis-server\")\n.override(OS.WINDOWS, Architecture.x86,\n\"redis-server/redis-server.exe\")\n.override(OS.WINDOWS, Architecture.x86_64,\n\"redis-server/redis-server.exe\")\n.override(OS.MAC_OS_X, Architecture.x86,\n\"redis-server/redis-server.app\")\n.override(OS.MAC_OS_X, Architecture.x86_64,\ngetRedisServerForAppleArchitecture());\n\n\nthis.redisServer = RedisServer.builder()\n.redisExecProvider(provider)\n.port(redisPort)\n.setting(\"bind \" + this.redisHost)\n.build();\n\nthis.redisServer.start();\nlog.info(\"Started Redis server at [{}:{}]\",\nthis.redisHost, this.redisPort);\n}\n\n\nprivate  String getRedisServerForAppleArchitecture()\nthrows Exception {\nProcess process = Runtime.getRuntime().exec(\"sysctl hw\");\ntry (BufferedReader input = new  BufferedReader(new\nInputStreamReader(process.getInputStream()))) {\nString  line;\nwhile((line = input.readLine()) != null) {\nif (line.contains(\"hw.optional.arm64\") &amp;&amp;\nline.trim().endsWith(\"1\")) {\nreturn  \"redis-server/amd64/redis-server.app\";\n}\n}\n} catch (IOException e) {\nlog.error(\"Error during parsing system process\");\nthrow  new RuntimeException(e);\n}\nreturn  \"redis-server/redis-server.app\";\n}</code></pre></div>\n<p>We've tested this approach on our microservices and it's stable.</p>\n<p>As for now, our core-team already replaced dependency from old embedded-redis to new one and it's working for both Intel and AMD architecture without additional changes.</p>\n<p>Thanks for reading!</p>","fields":{"slug":"/embedded-libraries/","tags":["auto1","engineering"]}}},{"node":{"id":"d980aa96-d832-53e1-a6c2-0f3710beb58a","frontmatter":{"category":"Engineering","title":"Application Cockpit Architecture Overview","date":"2022-02-17","summary":"An overview of AUTO1 Application Cockpit architecture and its most notable features","thumbnail":{"relativePath":"pages/application-cockpit/architecture-intro/thumb.png","childImageSharp":{"resolutions":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAAsTAAALEwEAmpwYAAADfUlEQVQ4y61UW2tcVRQ+OyAiiIIRVBRT6UPibmIcze2cOff7LZOZzORq0lorMiQxzjgdxQfFB6VFyJPSWKrRNE2wIW3BovlrHrrZy7X3MJGCjxn4OGuvy7e+tfY5oyjn/dN27hNj55ioP9wnMzePycjX98jQF/vkQvcuudA5IIMbe2Rg/WfywrU98lrzgLzePCSX2ifk3c5DMvrZAzK8cUJeXjsiz1TvEpLvk3MXqOjf741o3/1G3//mDvVvHNDxr+7Q4c5tOtb9hY53f6VvNG9RpXKDksYOHVz/ib5yZZeOb+/TydY9Otrcp8Mf/06fr2JO+CN9NtulinXr8ZPo9inzd0+fvHPzIbv47TF79csjNvj5IXupdche/BSxecTe7Dxgb3UesaHWI3ax/Se71P2LjV0/ZW+3/mZDzcfsuaUTpuR/MGXqw21Qr7Zgcm0TSqub+NyG91a2YHRhA7EFY40tKK+1wb5yHdRlzF1ugbrUgpnFFmhLbVAXEQttmJ5vw0i0BUpkWzwLPB6YOne1ae7pM2cIDJX7psotdZK7aEeuwV30W+oEt7UpbmmTEnZZYIp7xjRXoiSB+UYDstkK2K7Xg+Oe2Y7lgWFYkOWzsLL6AURJCkmagReE4MUBxHh2vQAckYtQgiCAWq0GYRiC67oQRREIn7Bdz4VwIwY7tiHAojRN0OdBks/1YnkEOTbyfR8cx5E1im3bkkw4+nYcx9IWPm/RB9M1ZXKC03hYnGaZjAtyz0d1ji3PAopIStMUTNOUDsuyzmwJ3QZd16Xqer0u1YgcERN5Av2zJIzSCsS4kzCKIUxyqeopuA6YlimJxDrkKhCeGB3FiIn665Iju54PPnYXCX7QC4gEUdwfXxALW6jsNxKjr1++Cg280KcIsYDHUcRRLsddcCTm1WqVY3eJLMs4JnLXcbjvudw0DG6aBrctiyMZxyZc18vcskwJRexPSO93Ft1E1/5OhA8J5OtRqTVQGY4Yp4gMLFvcbG+yIIxxLQEoWPAPKijwWSBBgR0LVCVt4ceCAlUVUV4vVj/pFrXlj4q5xctFbeVakVbqRZxXi3SuUVQW1opkdr5QNE0bx1sqCSBJqVwulyYmJqSNNyj9hmGgXyvp2rT06WW1VFaFbci4eBqGLmPn//eFrAOoZgA7/S9EDBVK4Kc1gJ8lwukBYz38dz53gf8CwA4PmL99534AAAAASUVORK5CYII=","width":325,"height":325,"src":"/static/b08a403a7e9534ad64f67f1ad61141df/b3029/thumb.png","srcSet":"/static/b08a403a7e9534ad64f67f1ad61141df/b3029/thumb.png 1x,\n/static/b08a403a7e9534ad64f67f1ad61141df/8d141/thumb.png 1.5x,\n/static/b08a403a7e9534ad64f67f1ad61141df/ee72c/thumb.png 2x,\n/static/b08a403a7e9534ad64f67f1ad61141df/5dfa8/thumb.png 3x"}}},"authorName":"Przemyslaw Walat","authorDescription":"Przemyslaw is an Expert Software Engineer based in our Szczecin office","authorAvatar":null,"headerImage":{"relativePath":"pages/application-cockpit/architecture-intro/1.png","childImageSharp":{"resolutions":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAAAsTAAALEwEAmpwYAAACaUlEQVQoz0VSS08TURSelQtXrkhI1JjYhQuIIZEC7bzuvTN3bjtDH5TSQlqUBGGlKOGZCOnWP0Di2oAJCTHEgH9O5/Oca6csvsy55/Gdc74zTnjx60/y7Teii/t87utPlEbXmD6+wtTBJab2r/DkwyUe737H9N41nn+6wbOPNyh9vsXM4R1mD+7xau8OT9/f4lH3Gk76A86b3ROUd0/z8s4pZreO8HrrBDObxyitH+Bl/xCl3hHmt85Q3R6h/PYLyptnmB+eY35wjsXhCAsD8m+MMLd2jhe1EziJknlmEqjAy4VbQRR4UH4VEUGHHmLhQrhLiMnWMoDwKggqCwiriwiqCxMIdxHSX4JjanV0VrvIlpcRCkkQCEIxsUNXwnV9JKaG7lrPfqM4hlQRpI4Q6wRCqnG+hBNTsN1uQ2sNKSWSJAH72JZKQu8kCHSIOIpRr9fJr5BmTahIQTcSNBpNRFEEQWRc4wiagkn4wRMxsTEGgqbkWDSM4SvfEmZZRsX0bbQQhiE1VDSttnkFnGRM4PsegsAnBGT7tsCiGsKtuig2iYikiHEeg2sKn2No/HqakRYaupaNO8mHrjS5T42YsFarQREh+/lbpzdvNJGIV5a0ApOx0JE25BQ2gRMZLAd3LgqZjAsVHaW/McDKSmcimSU0JsnHRbmgQkUCt1otewBGmqZ2GiZVdCQrC60pRIher2/JXNe1cV7d4SJaJS9W5Ek6nc5EE/Z5nke/i0G63LRy8CEUoYjz5flA/1eW8i8bFMg5gdfiaz4kk4aeiyRrY317H43uEI3VAVq9dzBpE9qkMFkLWbtv3/8ADCO9cUtyqcEAAAAASUVORK5CYII=","width":1280,"height":786,"src":"/static/477fbbb52f4a6b56a8627202336a0dce/26421/1.png","srcSet":"/static/477fbbb52f4a6b56a8627202336a0dce/26421/1.png 1x"}}}},"html":"<p>Hello fellow concerned developers, or, if you are not yet concerned, while it is not the crux of today’s entry, I hope\nthat by the end of it, you might get interested in becoming one and/or find out how you could do that on your own and\nwhat it actually means for us. Still, the focal point of this post is to fill you in on the architecture of Application\nCockpit (or “App Cockpit”, as we call it in private), the newest tool AUTO1 has brought in for its concerned developers.</p>\n<p><strong>The “why”</strong></p>\n<p>However, before dwelling on the “how” too much, let us pay homage to propriety and start with the ‘why’ of the whole\nmatter. The main reason for the emergence of the Cockpit stems from the plethora of tools AUTO1 has adopted to help us\ntrace, measure and monitor our services, not to mention alerting us when things go south. This opulence often means that\nif you are looking for a specific bit of information, whatever the reason, chances are the data is there somewhere, but\nyou need to make a significant effort finding out where to look for it first.</p>\n<p><a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/7913f56e8ec1a8e1392f735128cb79a1/ea190/2.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 590px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 37.099494097807764%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAYAAAAIy204AAAACXBIWXMAAAsSAAALEgHS3X78AAABLklEQVQoz12P626CQBSE9xlUKO+g9YJGQRFhuUbFhED7/q/RNDnTnZPSH/1xwpyZ2W8XMw7D9ziOsDYXay04RVEgz3MdanrUUzb1mqZB27Yoy1KqqoKbLzN+fOLx7KQoK9zvd5p6mLrrOtX0Xq+XAggihB7h7P36wt2UbSf1Y0Ca0bC4XC44nU6o61qL1GmaKvh8PiOKIoURzOx2u6Hve8myjJmYrGiQla0Lj3+/xSILk06SRIeaQILjONb9er3qBQQzM0XzFFs/WNInTwE1h5ovpE8IYbyYIO68yOXC3P2dmP0xxiFK5H29xn4fYrvdYrlcYrfbYbPZqOY3DEOsVisd7mvXn3qEO7DQM54fiPcWYD6fi+d5WCwWmM1moPZ9XzU9juvo/M+CINCzZPwA2yvoGlsGHf4AAAAASUVORK5CYII='); background-size: cover; display: block;\"\n    ></span>\n    <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;box-shadow:inset 0px 0px 0px 400px white;\"\n        alt=\"2\"\n        title=\"\"\n        src=\"/static/7913f56e8ec1a8e1392f735128cb79a1/40fad/2.png\"\n        srcset=\"/static/7913f56e8ec1a8e1392f735128cb79a1/707e9/2.png 148w,\n/static/7913f56e8ec1a8e1392f735128cb79a1/649e0/2.png 295w,\n/static/7913f56e8ec1a8e1392f735128cb79a1/40fad/2.png 590w,\n/static/7913f56e8ec1a8e1392f735128cb79a1/b3fef/2.png 885w,\n/static/7913f56e8ec1a8e1392f735128cb79a1/301c0/2.png 1180w,\n/static/7913f56e8ec1a8e1392f735128cb79a1/ea190/2.png 1186w\"\n        sizes=\"(max-width: 590px) 100vw, 590px\"\n      />\n  </span>\n  </a></p>\n<p>Once you have figured it out, more often than not, you are invited to dance your way around Kibana, GitHub and Grafana,\ncorrelating your findings, perhaps with a touch of Consul and AWS Event Log to help you along the way, sprinkled with a\nChronograph query here and there to spice things up. Neither is it fast, nor easy, nor pretty. What’s worse, we have\nnoticed, that as our ecosystem grows, it gradually becomes harder to know what to look for and where to find it and the\nlearning curve for new hires has started growing ever steeper.</p>\n<p><strong>…. and the “what”</strong></p>\n<p>Enter the App Cockpit. In short, the Cockpit is meant as THE tool which lets concerned developers quickly find their\nbearings and gather relevant information pertaining to a particular service running in our ecosystem. Being concerned,\nactually, for us means that you care about your services and the ecosystem as a whole and you want to keep your\napplications in tip-top shape as well as you feel responsible for troubleshooting them when needed.</p>\n<p>Keeping that in mind, we’ve designed the App Cockpit to be the first place you check when you want to find out who owns\nthe service, what other services or resources it relies on, is it healthy or not and what its main software dependencies\nare. It is also meant to be the place you visit first when a service starts misbehaving to be presented with quick\ntroubleshooting aids, or, if you are the owner, to perhaps bask in glory when everything runs smoothly.</p>\n<p><a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/819dad8db10b5028167d822d8695e0db/a1751/3.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 590px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 53.18118948824343%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAAsSAAALEgHS3X78AAAB8klEQVQoz1VSy47aMBTNBgYJ6I8gpFJAIkBC4tjOO6GESqxowqKfMMNuRuq0/zq7foFPr02CmMXRffjc63t9bHmeBy5CxblAEAQGvu+Dc27Q+YwxaG6H3W4H13U7qDb+Z+33e5UXBRG8R8IdO/dWaNs2lsvlHeaMmjxAbTYbWGEYQkqpWMDgBz4CFoC1k2rf574pqH/WuF6vuL5c8fzyDBlKM72pY77iAcd2u1WWJz1KMDjCAQsZmM8M0YAu4Ckz69a/Grz+ecX7+2+8/X1DkiRwmANxCCATAY972Gz1hHGIUErwkCOOYwgh9MQQGqFAksYm73Ja3Xex3thYbVeIoggiEoj2IeI8pqYSjuvAKrICUfYdaZpAxIJsijiJkWUZ+YQsN7mSbJkXyPMcUkgztXkesxFDuzIsMw0RHhXU0Ct7Pvnt+rqBhn4eX5+3nEcYUQpSuCToRKdc9y06XxNXq5VR2taWYpumMXGL9XptYB1/HEmxWOl31Ip3f0/7+j11w9PphMvlgrqu0ZBtKG6ormmaW65p1Pl8huM4pHJaqenXb/S3FmaKxWKB6XSK+XyO2WyGyWRimldVhcPhgOp4REUKH+iye45sWZZKc63hcIgv47EajUbQvrbj8fiTPxgM0Ov10O/3b/bpCf3POaUt8T/+A9K1gDWcRDsxAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n    ></span>\n    <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;box-shadow:inset 0px 0px 0px 400px white;\"\n        alt=\"3\"\n        title=\"\"\n        src=\"/static/819dad8db10b5028167d822d8695e0db/40fad/3.png\"\n        srcset=\"/static/819dad8db10b5028167d822d8695e0db/707e9/3.png 148w,\n/static/819dad8db10b5028167d822d8695e0db/649e0/3.png 295w,\n/static/819dad8db10b5028167d822d8695e0db/40fad/3.png 590w,\n/static/819dad8db10b5028167d822d8695e0db/b3fef/3.png 885w,\n/static/819dad8db10b5028167d822d8695e0db/301c0/3.png 1180w,\n/static/819dad8db10b5028167d822d8695e0db/a1751/3.png 1446w\"\n        sizes=\"(max-width: 590px) 100vw, 590px\"\n      />\n  </span>\n  </a></p>\n<p>To achieve all that, the Cockpit needs to pull data from multiple sources, aggregate it and present it in a comfortable\nand meaningful manner to the users, not to mention being fast and efficient about it, which leads us to the heart of the\nmatter - the architecture of App Cockpit.</p>\n<p><strong>Finally, the “how”….</strong></p>\n<p>When designing App Cockpit, we were striving for what probably every software engineer worth his hide can recite even\nwhen woken up at 4 am in the morning - we wanted the architecture to be “open and easily extensible, yet simple and\nrobust at the same time\", preferably allowing polyglot extensions to let every team in the company contribute and share\nwith others if they came up with a cool feature. In order to achieve this, we have split the Cockpit into 5 logical\ncomponents distributed in 3 different layers, as depicted below, with the descriptions to follow.</p>\n<p><a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/a5fde0a614ee1d33cf9b3d2224330a72/b6c2c/diag-1.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 382px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 178.79581151832463%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAkCAYAAACJ8xqgAAAACXBIWXMAAAsSAAALEgHS3X78AAAG50lEQVRIx41WC1BU1xm+M2aySWY6iVUwMYFlQdP4qMbH8paXkIdEqVWCThIzTkybmsrE1pj4aGRZILEsAuG1PIoaiIbU2vpKUqNO2szIU4FtgsuCAcIUfAUFd/fu497z9T+XXVweyfTOfPOd+5/vfOc//3925wpB8RWqgBijKnRdrSpkZaVKHWtUqeOMquDEGtX9P1PPnaaaHjvt/oefve+BGZHTVI+s5GOKxT/kt9Q/YgfuC4gyPKCOK1d5IZChKSC2vDN0fa2ZDM0UNAfFlxNXXAmKK+sOiikY1MQW9QfHl13VxBX3BcXkX9fElfTSphZaSxrS+4AbQp1QjfAX6zAn6RCCaMyhWVmNgNgq+IWXwy9iPPwjy6GOH9V49V5wQ/vs6DJGGUqUoUwZyhSTn1hhlJet/Uje/O7n8itvn5E37fxM3kT8KvGG7afkJ5+pkgNjR7V8jRfcUIzacBSRaR+z4IRKUBBkjJ9ri7Blzz/BH5dbhluS4XJJyvvNITvCUz8GJQJNQgX4Kb0Q5iZVidv05xG98Qjjk9wwmAxnhhaDMkNX7218Y7mJrr7buPTNNXR030KzaRARaT9iOCexUnxTd44Mj04yfHnHGVy7aUU3mQ1cv4u+/w7j+4ERtHZcB5UDj68gw/gJhmQgvpV9AUmb/8q4GYfSKM/RF6w6qHBq+klEbTgCqh3mPV+tGHm14wxDKMO0t05x8ViG3knvBv4RJVi37QS062rwaGQpqBnjNh5vuLJS/N2+L7HC58i+hpxnaIuxY/9XWPPGcaUUvnOTDOkI4rbM8+My5DX0Cy/BesqK16uxfQCmzhtKUzi++HcPlqQcBl2tyTUkE/Gp56oRtr6WcSNv7aYvL8LWjC+Va2LpGVKaYekdwuANK+7anAhLrZ26y8HxRjEwpozuVQ2bm1jBNPFGhWdoP2TbdGcZ+bE7w3Y2cldkVquDyZLEXE4Xi3yxhj0RXcpCEsoZeYxB8I856Ji54iAWra3DY3GH4UfjWbGHMD3iL1iSegzbDY34/fsXkV/7LfaWXEL6/ga8rvsa6qQazIyuhn/MIcLBMQirUzJsyav3ya9uzpNS1mZKL6zZR8iQKC49l/yeFJu4VwqP2SX9dmuxnPLrLCkybrcUl7RXojXSatK9MAGCQx9oF/fNYo785bIjSyM7MgNkihEHyk5iV+ZjsutdlSx9+prsLomWXbselF36x8c0EyFYdUEOx+E02IviYM3UwKpTEweNgsb28lUQj2yGq74SzrPZEGtfga0gEtaMgFG9V+uBQEHReTwd9tJERuYENaMJ4kBmzZrD5KE+Rp1hTHIzxmSlSa7WT5l1z0xm1Qd71tyDYNOHiM6612EvjGY2T4Y2vltGIGzZT4I5rZBvWCD1X4bbfBZMckLqugDr7hmw6YMVrS+EkZx5or3uN7AWRLER/Rw2otOwkczgMXZcrGKu3kbmHuxgrr4W5vquntlP7GQjf5pN+pBRrQ8E6GY5oPMDDixi0M8GdP6EWR7Q+L1HgN0PAp9sAkqjafzQaMw7P6YdhXA6e6PtVFaadO7Dre4z77/kPp210U2xMZzKedl9Qpfq/lfVLumLvC3uk/o0ir00TuML4ZcGk7gg14QEYwdbnGdiCw3tjGLEJoWfPvAfNj/XxFI/srCo4m+VONf5ahb6QAgzNDq0uU1ILmtlEXlN0OY2gvPCnHq8WXcFA3dEXKU/2X762++9ZVO4rX8Yz5ZcxlL61dB6hObeg6A1NIlLc5vxfFkbC8trZstzmxSen93A0o91sv7bIrPcsLG+IZH13LIz8zWrgtXl7WzxB40s1NDMKKExCLRYfKOuE2sq2vkkyBAUw1PZ9djx9y7IdAvv2N2wOSUMi25YiQeHHUg2tmHxfsqK1mh9IEQcaBb3nP4OKT6GfGIJiSlr7Dl9FduPW1DdMADD+T68/Y8u/IHeo/JbsMyjnWDYIr5z8uq4DL2mS//chEUfNGKuvh5bjl7BM6Wt+EVWvRLzapZPMBXIRPwj7fqrShPTTjBcQobzcxrI8CKoZkqcGy6g2LIfM+Q13HmyGymV9zLkTAXnm6Dwq++x/1wvapsHUfJ1PwwX+pBztgcxhZeUE0w6cnRBi5h+zMKLzLt7rymUyTsnuuF9nPTlwBvEH94g3pSnp2oKzzD9b5ZxTZnK8AerC3bPp8hPGkbmt4gZn/dMuja8Tq8duYLW/hHU99xBc98wGnuHFT7X+QMSi1uVGmunyNAeX3SZrTK2yTSWyVABTcq0QJ6X3SBTY0bZA9pMXubRePVeCEo389qQXNmBiMJ2aPPbEFpAIA4raEd44dRQNFOAG5poNzNdYjNlaKZdzPRzVFiBwYPc/w//A/3PElylj3URAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n    ></span>\n    <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;box-shadow:inset 0px 0px 0px 400px white;\"\n        alt=\"diag 1\"\n        title=\"\"\n        src=\"/static/a5fde0a614ee1d33cf9b3d2224330a72/b6c2c/diag-1.png\"\n        srcset=\"/static/a5fde0a614ee1d33cf9b3d2224330a72/a384c/diag-1.png 148w,\n/static/a5fde0a614ee1d33cf9b3d2224330a72/9ca5b/diag-1.png 295w,\n/static/a5fde0a614ee1d33cf9b3d2224330a72/b6c2c/diag-1.png 382w\"\n        sizes=\"(max-width: 382px) 100vw, 382px\"\n      />\n  </span>\n  </a></p>\n<ul>\n<li>\n<p><strong>Data Collector</strong> - the component responsible for fetching data from multiple external sources, parsing, aggregating,\ntransforming and sending it on its way to the data sink with a tiny stretch it might be called the ETL of App Cockpit</p>\n</li>\n<li>\n<p><strong>Data Sink</strong> - a simplistic component with a one-track mind, whose only job is to receive data in a well-defined\nformat from the Collector, occasionally perform some simple and generic operations on it (like basic validation and\nparent id resolution) and persisting it in the data storage</p>\n</li>\n<li>\n<p><strong>Data Storage</strong> - a simple storage that holds the current snapshot of App Cockpit data</p>\n</li>\n<li>\n<p><strong>Data Provider</strong> (aka Backend For Frontend) - exposes an interface to serve everything our UI needs, both serving the\ndata “as-is” from the storage as well as applying some additional logic to further aggregate and transform it for\nspecial purposes</p>\n</li>\n<li>\n<p><strong>UI</strong> - yer plain old Front-end - by design contains no logic, it only displays the data as provided</p>\n</li>\n</ul>\n<p><strong>Sweet, but how about a model?</strong></p>\n<p>The specifics of the model run outside of our scope, however, getting it wrong could severely hobble the architecture,\nso it is a story in and of itself, which will have to wait its turn to be told in another blog entry. For our purposes,\nwe will only briefly touch upon it, mainly to establish the domain.</p>\n<p>Truth be told, App Cockpit is pretty much a simpleton, since its world consists of only two kinds of things: Readings\nand Resources and everything it does revolves around the pair.</p>\n<p><a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/620475cb60f40b22eca2eb0e91489dcd/bdb41/4.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 590px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 60.852459016393446%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAAAsSAAALEgHS3X78AAABtUlEQVQoz3VSbZabMAzkGkl+5ZVDYMDG+AvsBBfSvf9F+mpVEssub7v9MRGRRiONoLrf77/ruob6R11utxscuF6vcLlcOJ7xb4655brn/1TBB1jyUkKawBoLxhiw1sI8z5BSAu89OGc5hhA4RzXnHPMs8qdphpieRY8jkGDZXhv44EvOmUnc+HggaUd6ZliWhUVJ8PV68WDKEbCn/Hp7g2EYSqWUYhEpJU8l4oiTDG4rlQY1aNDGgdaaOVQj4aOPeiQ+O+9AYb2i9WnKuq5shYg4iaE5qncMHzhzjmeKNLAiC9u2QUQxEqTpZ0zTxCdYlifWJ97oK4dAveSCLcfHAi7M0Pc9TyFQvus6vGViUa1HeOQNBowH5wBtmH9m7qmk7GH0CbSbQTQNCCF2tAIa/D9aw1u1KO7iCqOLn5wPbgshTrtl+jEBBU3AYgMtFg+IRoD1lg/e9/jSYgaJL+nMYeCwOeH9JW8oCwmOPpYWp/1PsMNz+LTCYDzWxDeCcRdU+4bFoG3xRZAskyAdvet6sHNGYclOzpaJG+awW1ZKltF6MH4qdNQz+Bx4Q/o2z5/Hd6Aa8f8CyFeeSMaQMngAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n    ></span>\n    <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;box-shadow:inset 0px 0px 0px 400px white;\"\n        alt=\"4\"\n        title=\"\"\n        src=\"/static/620475cb60f40b22eca2eb0e91489dcd/40fad/4.png\"\n        srcset=\"/static/620475cb60f40b22eca2eb0e91489dcd/707e9/4.png 148w,\n/static/620475cb60f40b22eca2eb0e91489dcd/649e0/4.png 295w,\n/static/620475cb60f40b22eca2eb0e91489dcd/40fad/4.png 590w,\n/static/620475cb60f40b22eca2eb0e91489dcd/b3fef/4.png 885w,\n/static/620475cb60f40b22eca2eb0e91489dcd/301c0/4.png 1180w,\n/static/620475cb60f40b22eca2eb0e91489dcd/bdb41/4.png 1525w\"\n        sizes=\"(max-width: 590px) 100vw, 590px\"\n      />\n  </span>\n  </a></p>\n<p>Accordingly, a Reading is a piece of data that describes a Resource in some way, e.g. a metric value, service name,\nowning team, the version of Docker image it currently runs etc.</p>\n<p>In complement, a Resource is a concrete entity for which Readings can be collected and then served; it can be a physical\nentity, e.g. an instance of a service or a logical one (e.g. a definition of a service, e.g. “authentication-service”, a\nsoftware dependency e.g. ‘log4j”, etc). In addition, Resources can form hierarchies, since they support a\nparent-children relationship.</p>\n<p>Given all the above, the main purpose of the App Cockpit is to collect Readings for tracked Resources and present them\nto the users.</p>\n<p><strong>Getting physical.</strong></p>\n<p>Having established all the basics, we can now shift our focus to the physical application of the architecture. We will\ngo over logical components one by one and discuss how we have decided to implement it, to finally sum it all up with a\nfull diagram illustrating the complete solution.</p>\n<p><strong>UI</strong> - we have chosen to implement it using a customized version of Backstage app, built using React JS and available\nat <a href=\"https://backstage.io/\">backstage.io</a>. Since it provides many handy features readily out of the box, it has greatly\nstreamlined the UI development process. Provides a web interface for the users, communicates with Data Provider over\nHTTP via REST endpoints.</p>\n<p><strong>Data Provider</strong> - a simple, easily scalable service built in Java using Spring Boot, exposes REST endpoints for UI\nwhile fetching data from the datasource over JDBC; Apart from serving Readings and Resources it also has a concept of\n“calculations”, which come into play when returning plain entities is not enough to present the user with the desired\ndata. Calculations encapsulate any form of additional aggregation, correlation and transformation logic that is\nperformed on the data in order to enable the UI to present more complex views without placing actual logic in the UI\nitself.</p>\n<p><strong>Data Storage</strong> - nothing fancy there, while we have briefly considered using a temporal db, we have decided to fall\nback to plain old PostgreSQL, since the Cockpit is operating on relational data; the decision has paid off, though,\nsince we were able to leverage the built-in JSONB type to store heterogeneous Reading data in a single column. It is a\nsimple, yet powerful mechanism, which makes the system extremely pluggable. Since a Reading is actually a free-form JSON\nobject, all throughout the ecosystem, the only components that need to know its exact model are the Collector\nimplementation that is going to publish it and the actual UI component that is going to display it. Every other piece of\nthe system can be safely kept in the dark and will be more than happy about it.</p>\n<p><strong>Data Sink</strong> - implemented as a simple lambda function, it has a well-defined job to do; it listens to SNS (AWS'\nmessaging product) events published by the Collectors to its proprietary topic, extracts the payloads, performs simple\nvalidation logic and persists them in the storage. In addition, it is also responsible for properly resolving parent\nResources for incoming children. This piece of logic would fit in the Collectors as well, however since we have decided\nto make them stateless, it has inevitably found its way to the Data Sink.</p>\n<p><strong>Data Collector</strong> - it is the only component for which the logical diagram differs from the physical one, albeit by\ndesign. This stems from the fact that the Collector has been meant as the main extension point that other teams,\npossibly using disparate stacks, can easily plug into when adding new features. By all means, a Collector, as previously\nstated, is any component that fetches data from an arbitrary source, transforms it into Resources and/or Readings and\npushes it to the Data Sink SNS topic.</p>\n<p>In consequence, when you want to start collecting a new type of data or start collecting it from a different source, you\nhave two options - either add your implementation in one of already existing collector services, or write your own new\none, and the only requirement we superimpose on you is that when you publish to the Data Sink, you follow the format we\nhave specified. At the time this post is being written, we have 3 distinct Data Collector implementations:</p>\n<ul>\n<li>\n<p><strong>Main Collector</strong>  - a general-purpose collector, written in Java and providing data for cross-platform features,\ne.g.:</p>\n<ul>\n<li>\n<p>service ownership</p>\n</li>\n<li>\n<p>incidents</p>\n</li>\n<li>\n<p>Docker images used and their vulnerabilities</p>\n</li>\n<li>\n<p>service health and deployments</p>\n</li>\n<li>\n<p>currently running instances</p>\n</li>\n<li>\n<p>code insights (quality, PRs, contributors etc)</p>\n</li>\n</ul>\n</li>\n</ul>\n<ul>\n<li>\n<p><strong>Java Collector</strong> - yet another service written in Java, as the name suggests it collects data strictly related to\nservices written in Java, e.g.:</p>\n<ul>\n<li>\n<p>runtime information like JVM and GC being used</p>\n</li>\n<li>\n<p>selective list of JVM parameters passed to the instances</p>\n</li>\n<li>\n<p>egress dependencies for Java services (in this context, the upstream services)</p>\n</li>\n</ul>\n</li>\n<li>\n<p><strong>PHP/Golang collector</strong> - the first contribution coming from outside the original App Cockpit team, written in\nGolang, it is going to provision data for PHP and Golang services, e.g.:</p>\n<ul>\n<li>\n<p>egress dependencies</p>\n</li>\n<li>\n<p>vulnerabilities</p>\n</li>\n<li>\n<p>possibly many more to come</p>\n</li>\n</ul>\n</li>\n</ul>\n<p>With a picture being worth a thousand words, let’s have a look at a diagram that gathers all of this in one place:</p>\n<p><br><a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/f576711fa336eca6db48f2c1cb19c47c/b2341/diag-2.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 531px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 161.5819209039548%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAgCAYAAAASYli2AAAACXBIWXMAAAsSAAALEgHS3X78AAAFzklEQVRIx4WUi1PUVRTH9x9oemmpZSCogA+QeCUo78U1RVI0C8lHZaBRzvgaDQRDHuKykAgBuzxCwdGE1TEtk9GymkQRJQ3IUHuwNpGZ5ANFw0/33mWJ3ch25ju/e+8553u/53vvXY27rpyoxTuZvayW2KQ6guOqcQ4zMuWlHcx7q47Zy2uZlViLW1QZTqFGFq75iPW5R1mdXc96/VESUj5mjNbEqHATntEfoBmjNfL58Xau3+jm5s3bZBZ+hsY5h9T8o/z2+3XaLvzG6dNnGacz8ohvIY3NPyJ/PT13uXfvrhjdJ23rFzzis40JMyoloYm5SbUkpn7C6qxDpL9Xz/wVe0k21LMq8xCvrjtA7LKdjI40MiSgiPyKr+m63s0Plj+51NHFjVs9lO9p5uFnC5g4UygcHVnGE5Pf53H/IsLjq+kUqq5eu8XPHVeUFY/6FfFkYImywSm0lJHBJSxL/ZTkvGOszDqivpGLdjM8qJjxzwuFo7VlKtlDVyF2qCAm8UNefHsvs5buYlJ0OWOVd6WMCisVeaXKxxFTShgZUsrTgvypqSXq+4yYj5tegcY10qQmstBtWrlKlAaPDDHiHFnFhJnb1WZPhVTiHF6GS7hRtG9S+S4RJiVmlFgbaSOUJFKBLSCTvWZV4SnUhsbmEDinGC+hNGJuNt7RpUyMrlI5thob+hXqXqtV7DaPZGvaJWaiFlZSuzmMFUkr8dZtpn7rFBLezmF6wkHcp5UpgkEJoxPNPBM6gFCoHKO13jnvmUW4i3adIrbjO6sIl7BikWdSrToNqHmwQkHoqgpKGBFcSfSCTBa8ns7ToZVqY0nmEv6AluVldFQoCUeFlTA0sJJ1SXHkJ7/MiKkmdcqKMOIBhI7ybQcjE2RsxusfMk9cfNm6XHP9P0J5se0Iw6weykIP8c4nzdmFZ+wePKZbb4OMyU0fQGi/mxxLuISXMiTQyJL4LNLfTCUobjczltah7q3DgdgRyrfsLA5AXpeBcA0vYVhwOWuXplG6Zi1eL9QQNL960FwJp5AS8fTK0ThFVIrTLBMvYQBCyxkmDsHrhZ2EL/0E7fJ6JsbUiEMyiliFivcjpFzVDBf5Y3RVaCZPN+A7zYDfv5CHb2QOujl6YuYbCIjKsa5rxVe75Z9vlB4/XR4+UbkExxSgsWT405HiYY8N4+lYPxpL7jQ6m+rpPPsVlqIXsSS7YckKxJI52YpN/lg2TqLjnbF0JLtzOd0HzZ2K2XSnO9G9yfkfZLhyK2UIPXXLobdH/aHePZTKne3zud/ZQm/7EXovHqP38hnu/97OnR1x3NowlO4tE9CQ7wVpj8G7Q2HjECvefQI2PAzb/KG5GlrrwBgBencwvwG7FsDueNibAB+tgMIASHkIsp3R7MtejDlrEGQvYV/GAvbnJrA/7001NmfEY06LxbxxnhVynDob8yYRy1rEfn0CGs/8VjxyWxhnEMjtgxi76b/Fr/A8c2t+4JXdPxFQdJ6xehHL+06grQ/fWWFoxV3k+xS0oQnKO4G/voEAB0w2nCCioJEY4xliy5rRbjtFoFgLGCRXwm9LA6FbG9E8Z2jEV38Sv1wr/MV8QnYD8dtbuHKjh7Zfb3Lulxvc7PmL1fva8cg8ToDIseXb4CM4grc2oZlTdlZN/HIbFRRhVgOLq1vV6Uqirtv31Hit+bwgbOgjtEc/oSz02XLSLvismIcWNLFqbzspBy6S+vElVu5pI2pbE94Ouf8ifPmDbxWBLeDbp3ZSzgmlZF7FOdX+c3mn8MoRlvTl+OpPDk4YV2VPOJBU+htZeBpdcTNB+afsSP6TULbmGJTKxgsfUw9e5HDbVY5+/wfZh3/Ec/MJO7KBdf2EAYbGQQnHCfMLjnXw9aUuvrhwjeIvLUQItQt3tCjVjr73E0pvbJ4M9EaaH2P6hv3nriiFr9a0qKKwgtN2PtrypW1TJWGgIFTXxQFSpWxRHsoioSoo3947x3y5HiII/wbp3Q12i8R3IAAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n    ></span>\n    <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;box-shadow:inset 0px 0px 0px 400px white;\"\n        alt=\"diag 2\"\n        title=\"\"\n        src=\"/static/f576711fa336eca6db48f2c1cb19c47c/b2341/diag-2.png\"\n        srcset=\"/static/f576711fa336eca6db48f2c1cb19c47c/85b06/diag-2.png 148w,\n/static/f576711fa336eca6db48f2c1cb19c47c/75500/diag-2.png 295w,\n/static/f576711fa336eca6db48f2c1cb19c47c/b2341/diag-2.png 531w\"\n        sizes=\"(max-width: 531px) 100vw, 531px\"\n      />\n  </span>\n  </a><br></p>\n<p>Obviously, the actual process of data collection, as it is currently implemented, is a whole story in and of itself,\ndeserving yet another dedicated blog post, especially since we have elected to make all the collectors stateless, which\nhad its numerous consequences and challenges so keep your eye out for the next entry which is bound to come shortly.</p>\n<p><strong>Closing words and … we will be back</strong></p>\n<p>Having said, or rather written all the above, we sincerely hope that we have managed to pique your interest. Not only in\nour solution but also in actually getting “concerned” about your ecosystem, because it does not necessarily have to be\nboring, especially when you have the right tools to make your life easier. On top of that, you can have your fun\nbuilding the actual tools, deftly combining business with pleasure for a change of the usual pace.</p>\n<p>As hinted numerous times, this is only the preliminary article, meant to lay the groundwork for future additions\nexploring individual pieces in more depth… We are already looking forward to writing those, so keep your eye out!</p>","fields":{"slug":"/application-cockpit/architecture-intro/","tags":["auto1","Engineering","Architecture","Cockpit"]}}},{"node":{"id":"89a8474c-7217-53ee-bffa-b7a1d7f79b26","frontmatter":{"category":"Engineering","title":"The OpenAPI journey","date":"2021-11-22","summary":"A story on how OpenAPI helped AUTO1 Tech to move forward faster and in a more structured way.","thumbnail":null,"authorName":"Mariusz Sondecki","authorDescription":"Mariusz is an Expert Software Engineer based in our Szczecin office","authorAvatar":{"relativePath":"pages/openapi-journey/avatar.jpg","childImageSharp":{"resolutions":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAUABQDASIAAhEBAxEB/8QAGAABAQEBAQAAAAAAAAAAAAAAAAQDAQX/xAAXAQADAQAAAAAAAAAAAAAAAAABAgME/9oADAMBAAIQAxAAAAGbumAap5ikb5hWqFs3/8QAHRAAAgEEAwAAAAAAAAAAAAAAAAECAxETIhIyM//aAAgBAQABBQJ7KyiZB+eTXkVOkRpX/8QAGREAAwADAAAAAAAAAAAAAAAAAAERAhAx/9oACAEDAQE/AVIRmPHr/8QAGREAAwADAAAAAAAAAAAAAAAAAAERECFB/9oACAECAQE/AXaaHzH/xAAdEAACAgIDAQAAAAAAAAAAAAAAAQIRMUEhUWGR/9oACAEBAAY/Ar1dFxbNkpdSOHZgf0XphH//xAAcEAEAAgIDAQAAAAAAAAAAAAABABEhUTFBcZH/2gAIAQEAAT8hdJaGSDyw7NxOoAXu4myepjz9sxM4YXnC4zJPSf/aAAwDAQACAAMAAAAQsAe//8QAGBEBAQADAAAAAAAAAAAAAAAAAQAQESH/2gAIAQMBAT8QHFxNnbf/xAAYEQEAAwEAAAAAAAAAAAAAAAABABARIf/aAAgBAgEBPxBrVD2MJ//EABwQAQEAAwADAQAAAAAAAAAAAAERACExQVGB8f/aAAgBAQABPxAeZq9WVmcC80YLiXbfcFAVSC9AmMF6FjWIaILvbd795a6UQeU/MlrKKMsHZ0Fz/9k=","width":50,"height":50,"src":"/static/84204f0ce4111c333b6172133a845a85/d2d31/avatar.jpg","srcSet":"/static/84204f0ce4111c333b6172133a845a85/d2d31/avatar.jpg 1x,\n/static/84204f0ce4111c333b6172133a845a85/0b804/avatar.jpg 1.5x,\n/static/84204f0ce4111c333b6172133a845a85/753c3/avatar.jpg 2x,\n/static/84204f0ce4111c333b6172133a845a85/31ca8/avatar.jpg 3x"}}},"headerImage":null},"html":"<h2>The OpenAPI journey</h2>\n<h4>The situation</h4>\n<p>The AUTO1 microservice landscape is growing in size day by day, with new services from a spectrum of languages being erected and usually communicating with each other by using REST contracts.</p>\n<p>In a fast paced environment, such as AUTO1, often the service providing the REST API and the service consuming this REST API are developed in parallel, by independent teams. On top of that the business requirements over the lifetime of a project evolve, thus impacting the stability of the API. Having these moving parts in picture can make the development process quite challenging, especially when aiming for high productivity, zero downtime and independent development of the client and server parts. Hence, having a clearly documented and language agnostic API is vital for the success of the whole process.</p>\n<h4>The light at the end of the tunnel</h4>\n<p>After extensive research, we found a great candidate seemingly accommodating all the aforementioned requirements - OpenAPI. In short the OpenAPI specification defines a language agnostic standard allowing to describe REST APIs in a human readable form, imposing a unified structure, clearly and comprehensively aligning expectations between the consumer and provider sides.</p>\n<p>Below is an example of such an API described using the OpenAPI 3.0 standard:</p>\n<p><a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/a7f250f18c1768e91dfab8b2437f95a5/5d76c/img1.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 590px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 91.375%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAIAAADUsmlHAAAACXBIWXMAAAsSAAALEgHS3X78AAABR0lEQVQ4y41TCXKDMAzMc1Ks2xeQNjT//1RlKCFHp7AjGxm86D5NGS+Jayk555gyIoWuC/8CABbl1Bt+JiyJxj6mZCyM67d9sl+9FahJJMaYk28icpTcBahuvEYk6maEPWxk14uGa3XLeY22e8ffZGKaSpOoJKrsTov6Yv5VlycR4Yq7fvJVFNyymrAQO93FuCnmZ3I7gAgPwPV48uXVGgxTVFNZfhkWv2Av5shYFSKFJGiMql6tw9keI3ids1JW9B+FLnTHmwQhfFW59mnsk5e5hfMgO2QhnDJMlS5VchRWIkGStiPhDtm1ocS+FrPoGXe3N9l1m5rbMZdyPn8caa9Xy71Bnz3NFo7hqbcHg9tg1sgdLPV/aop2+fW8DYbCd2WP3NOtrauw5Yw3QYL55ZzFNrIPg5E4jNnKcPGmnefiTcLTfif/APHyvwWxcOnkAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n    ></span>\n    <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;box-shadow:inset 0px 0px 0px 400px white;\"\n        alt=\"img1\"\n        title=\"\"\n        src=\"/static/a7f250f18c1768e91dfab8b2437f95a5/40fad/img1.png\"\n        srcset=\"/static/a7f250f18c1768e91dfab8b2437f95a5/707e9/img1.png 148w,\n/static/a7f250f18c1768e91dfab8b2437f95a5/649e0/img1.png 295w,\n/static/a7f250f18c1768e91dfab8b2437f95a5/40fad/img1.png 590w,\n/static/a7f250f18c1768e91dfab8b2437f95a5/b3fef/img1.png 885w,\n/static/a7f250f18c1768e91dfab8b2437f95a5/301c0/img1.png 1180w,\n/static/a7f250f18c1768e91dfab8b2437f95a5/5d76c/img1.png 1600w\"\n        sizes=\"(max-width: 590px) 100vw, 590px\"\n      />\n  </span>\n  </a>\n<em>Fig 1. OpenAPI specification example</em></p>\n<h4>Design first, code later</h4>\n<p>In general, we distinguish two approaches when developing APIs. The code first approach, which is basically about developing the source code fulfilling the business requirements and afterwards, optionally, generating the API specification from it, which for OpenAPI can be done using the <a href=\"https://github.com/swagger-api/swagger-core/wiki/annotations\">swagger annotations</a>. The second approach known as design first, is all about describing the API in a human readable language first, by using for example the OpenAPI specification, and then optionally, based on this artifact generating the source code for server and/or client. Naturally, both approaches come with pros and cons.</p>\n<p>As previously mentioned, in AUTO1 it often happens that changes that are being introduced in the API on the server side need to be implemented at more or less the same time on the client side. In such a situation, if the code first approach would be practiced, the consumers would need to wait for the server side implementation to be delivered before starting their part, that would be simply inefficient. Here, for the rescue comes the design first approach, where from the moment when the API specification is agreed upon, both server and consumer side can kick-off their side of the implementation, independently. Additionally, this allows to spot misalignments already at a very early stage, and rectify them before the actual implementation from either of the sides is started, hence less expensive to fix.</p>\n<h4>The ecosystem</h4>\n<p>The OpenAPI comes with a rich ecosystem, from UI tools such as <a href=\"https://swagger.io/tools/swagger-ui/\">Swagger UI</a> allowing to visualize and test ad-hoc the specifications to <a href=\"https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-import-api.html\">AWS integration</a> providing a fast lane to expose the specification via AWS API Gateway.</p>\n<p><a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/3434af62ba0a90ef3305143d041e0a9f/5d76c/img2.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 590px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 67%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAIAAAAmMtkJAAAACXBIWXMAAAsSAAALEgHS3X78AAABWUlEQVQoz43QS0/CQBAA4P5SUVE0Gh/xYOI/860RQjx5VIgRi9SWUvb9mNktilujNytMvsMcZnZnJkJJxo/tJB4M4wEp8hL0p7cztN5qZ2Qdq5gDEznNxPABRBESVAQV9YZ5w0v7txmIUEbzERoZgZEse5XT1Iqp07Sipk7mdbwuAicyZ0XkQPEiCd+WqEtQFStKQ+tIkslpZtgYTdWss1HMxu8oKchq7PCQM7zOOBnmyRsvMqtFpDg5OT7a2d3cO9jaP9xuba41GyvN1Vqt5urGeqPVbAyen8LO4r591W1fdDuXQef2vH1z9o+769O767POzSkjeRjboObzDz+fl79mi336mYMo7C2L4WT0rEmCIgW+GIqMpi9W0upnUCRcwttAOMuXgYaGS0eASAhV2gRaGwtgARcKdYgYOe8nk0nyHVmaMsb4cvHTHMdxr9fr9/shCc10uQCAL5G0uXhSdaMzAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n    ></span>\n    <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;box-shadow:inset 0px 0px 0px 400px white;\"\n        alt=\"img2\"\n        title=\"\"\n        src=\"/static/3434af62ba0a90ef3305143d041e0a9f/40fad/img2.png\"\n        srcset=\"/static/3434af62ba0a90ef3305143d041e0a9f/707e9/img2.png 148w,\n/static/3434af62ba0a90ef3305143d041e0a9f/649e0/img2.png 295w,\n/static/3434af62ba0a90ef3305143d041e0a9f/40fad/img2.png 590w,\n/static/3434af62ba0a90ef3305143d041e0a9f/b3fef/img2.png 885w,\n/static/3434af62ba0a90ef3305143d041e0a9f/301c0/img2.png 1180w,\n/static/3434af62ba0a90ef3305143d041e0a9f/5d76c/img2.png 1600w\"\n        sizes=\"(max-width: 590px) 100vw, 590px\"\n      />\n  </span>\n  </a>\n<em>Fig 2. Swagger rendered view of an OpenAPI specification</em></p>\n<p>Another very helpful set of tools are the <a href=\"https://openapi-generator.tech/docs/generators\">code generators</a>, that can generate client side libraries and server side stubs from the OpenAPI definitions. These extendible generators support a variety of languages and frameworks, which lets one move faster, especially in a polyglot microservice environment. For our Spring Java applications we have decided to go for a <a href=\"https://openapi-generator.tech/docs/generators/spring/\">generator</a> that is very well configurable and easily customizable. It can be executed in various ways such as via cli, maven/gradle plugin, etc. Since our Java projects use maven for the build automation process, the maven openapi generator plugin was the natural choice for us.</p>\n<p><a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/aae6f743e2adb089391e73f024c93246/418da/img3.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 590px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 43.916913946587535%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAIAAAC9o5sfAAAACXBIWXMAAAsSAAALEgHS3X78AAAA+0lEQVQoz4VRi2rDMAzMb622FMcvWc7DTtKuLaP//xtTuq0wEqg5hLC5O+ncMNn7OQ05REqJcyTmFMY+eG8BTft3NOAeTdeZc43XlWud1qXMdcyZc06iJXoUbYo2hu6YLKpziZclUfTSm05M4KRAadBaKipAqcdkeRDhy5LF0PkQAsXoRAUAAY45/8gy+W0lIfuQcvLetR8KTnrzf0921khma6GpD9bZ5zFy6ZyRFZTeA3/QyEoa8TLT48qP21hrmaZpmce59HPtmVli+w0vsUB6Ij9kx+QacS9D+PrkpQRrt1S3gTVuUAjY7oAvNJKWfFUiKyG9XfIF9azf37eKwn0eyZ8AAAAASUVORK5CYII='); background-size: cover; display: block;\"\n    ></span>\n    <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;box-shadow:inset 0px 0px 0px 400px white;\"\n        alt=\"img3\"\n        title=\"\"\n        src=\"/static/aae6f743e2adb089391e73f024c93246/40fad/img3.png\"\n        srcset=\"/static/aae6f743e2adb089391e73f024c93246/707e9/img3.png 148w,\n/static/aae6f743e2adb089391e73f024c93246/649e0/img3.png 295w,\n/static/aae6f743e2adb089391e73f024c93246/40fad/img3.png 590w,\n/static/aae6f743e2adb089391e73f024c93246/b3fef/img3.png 885w,\n/static/aae6f743e2adb089391e73f024c93246/301c0/img3.png 1180w,\n/static/aae6f743e2adb089391e73f024c93246/418da/img3.png 1348w\"\n        sizes=\"(max-width: 590px) 100vw, 590px\"\n      />\n  </span>\n  </a>\n<em>Fig 3. OpenAPI generator plugin configuration example</em></p>\n<p>The code generators have become pretty fast a very prominent tool among our developers, for various reasons:</p>\n<ul>\n<li>\n<p>They immensely reduce writing boilerplate code required for setting up the communication channel with the REST APIs, hence letting the developers to focus on the business code rather than the glue code.</p>\n</li>\n<li>\n<p>They generate repeatable and consistent code of the API model and related REST client definition.</p>\n</li>\n<li>\n<p>Being highly configurable, they can be used out of the box and fine tuned without writing a single line of code in many cases. A good example here could be the Spring generator that allows us to define things such as the time API to use for the generated code, whether to wrap optional parameters in a Java Optional container or whether to use any framework specific features such as Bean Validation 2.0 from JSR 380.</p>\n</li>\n</ul>\n<p><a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/d836f12eedc71eca7c971d867e21f632/4d49e/img4.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 590px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 20.726495726495727%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAECAIAAAABPYjBAAAACXBIWXMAAAsSAAALEgHS3X78AAAAnUlEQVQI113PSQ7DIAwFUM4V5mAwQwYaSIdIvf816rSLSpHe/ztbNpsy7BVvi9/WkJPTWhujpVRcyIvhiwv1a8LA2baGZ8NXj4+GvYZWQ8TRgacQS4EAbkRvnTMeLAGwxhomlVonf+zx6PHYE/X7kXrFlDPGdKLkUnKYs0vRlXSaC9A8mxLcN6TLtyXU2dPNSinaOHDBuRj+5AU98gHBhUAhdRdZ1QAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n    ></span>\n    <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;box-shadow:inset 0px 0px 0px 400px white;\"\n        alt=\"img4\"\n        title=\"\"\n        src=\"/static/d836f12eedc71eca7c971d867e21f632/40fad/img4.png\"\n        srcset=\"/static/d836f12eedc71eca7c971d867e21f632/707e9/img4.png 148w,\n/static/d836f12eedc71eca7c971d867e21f632/649e0/img4.png 295w,\n/static/d836f12eedc71eca7c971d867e21f632/40fad/img4.png 590w,\n/static/d836f12eedc71eca7c971d867e21f632/b3fef/img4.png 885w,\n/static/d836f12eedc71eca7c971d867e21f632/4d49e/img4.png 936w\"\n        sizes=\"(max-width: 590px) 100vw, 590px\"\n      />\n  </span>\n  </a>\n<em>Fig 4. OpenAPI generator plugin configuration example</em></p>\n<h4>Retrofitting OpenAPI</h4>\n<p>Despite the vast configuration possibilities offered by the OpenAPI code generators, in order to integrate OpenAPI into our AUTO1 development world seamlessly and make the generated API and models classes adhere to our coding standards we needed to extend the default Spring generator that we’ve decided to go with in first place, to include some AUTO1 specific code structures.</p>\n<p>To be more productive, concise and spare some boilerplate code we use in AUTO1 the Lombok library, a lot, hence we couldn’t afford not having the Lombok annotations included in the generated classes as well. To follow the OpenAPI generator practices, we have added a configuration property to control enabling and disabling the usage of Lombok annotations:</p>\n<p><a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/999410ded404fcb4052d4d6c6aa41d84/01d07/img5.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 590px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 18.580375782881003%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAECAIAAAABPYjBAAAACXBIWXMAAAsSAAALEgHS3X78AAAAmUlEQVQI11WObQ7CIBBEey0FCgX2g9ZELa223v8gDqkxmsyPYcPbfd1W9TnLcuP1LjkNIfgQgrHubOyR1q07GUz+YlzfXUoCti9txWst2LVVEc4sqlq0jJmEhaeSiiARZdRWvPcdHgAAb0jVxyzINFJMBJ5FUDJl/BaKwpEoKkemocE4i5v12rRVYu+btnX91/zQ/tj+FGi/AQntQF+49FjdAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n    ></span>\n    <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;box-shadow:inset 0px 0px 0px 400px white;\"\n        alt=\"img5\"\n        title=\"\"\n        src=\"/static/999410ded404fcb4052d4d6c6aa41d84/40fad/img5.png\"\n        srcset=\"/static/999410ded404fcb4052d4d6c6aa41d84/707e9/img5.png 148w,\n/static/999410ded404fcb4052d4d6c6aa41d84/649e0/img5.png 295w,\n/static/999410ded404fcb4052d4d6c6aa41d84/40fad/img5.png 590w,\n/static/999410ded404fcb4052d4d6c6aa41d84/b3fef/img5.png 885w,\n/static/999410ded404fcb4052d4d6c6aa41d84/01d07/img5.png 958w\"\n        sizes=\"(max-width: 590px) 100vw, 590px\"\n      />\n  </span>\n  </a>\n<em>Fig 5. OpenAPI generator plugin configuration example enabling lombok annotations</em></p>\n<p>The above setting would result in generating the following annotations in the output classes:</p>\n<p><a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/e1b5aba9483f31ed3b66d79733319b8e/7a5fe/img6.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 253px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 65.61264822134387%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAIAAAAmMtkJAAAACXBIWXMAAAsSAAALEgHS3X78AAABoUlEQVQoz4WS+Y6bMBjEeZ3GxhcJZ3BYHJssMYQ7pbnarVr1/Z9gzbJdVdpEHY3mD5vx97OF1aTOr5wMgjVPOArDqj2Ol5dhvMosV1L6S4zwJPI3ySw6yRIRqxKqIpoGxHVXT0Jmu71Uu2jNeRzHYeB5gR+Gnh8EgUl/uZq0dBzTt1rh/NHkuKVNgqMoqrpxvP4cTje1y/OyPv343fRj1RqUl/7rpRm+PetKSpWuXYSJxRh1GDX5jvImw8XMEqVzzphzvq/P2BjT2WaLMfpJhD6W9f0Gr+cvQwfTFC0AM0d8nPVfWWWB9jkUKTLleI3XkXlzc3m8Wk0g91j+KQ8d6N/c1PA4gLKwywKeTwvfIwAw22aG4mG5bWDfgvzZ/vA+n1JuUaYMlL3h+NEVprIZaL7WGpqZWpsmzJSttsj0Cw3DED8abp1PdtcBqey2AXUF6xoeDvBQQp0DvV8UGrQ18Lz7w63dlqgNFtyYKIFlMllwxDeuVFEqgk2ycj2P3GtbbUJvGe1T84dR7tIhpVfF6hjxRDTDRR/6IOQxTzBCn5/+FZNLsCJTQJfiAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n    ></span>\n    <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;box-shadow:inset 0px 0px 0px 400px white;\"\n        alt=\"img6\"\n        title=\"\"\n        src=\"/static/e1b5aba9483f31ed3b66d79733319b8e/7a5fe/img6.png\"\n        srcset=\"/static/e1b5aba9483f31ed3b66d79733319b8e/0376c/img6.png 148w,\n/static/e1b5aba9483f31ed3b66d79733319b8e/7a5fe/img6.png 253w\"\n        sizes=\"(max-width: 253px) 100vw, 253px\"\n      />\n  </span>\n  </a>\n<em>Fig 6. OpenAPI generated lombok annotations</em></p>\n<p>Sometimes the need arises to define custom annotations but only on some specific classes, for that purpose we have introduced a new attribute to our OpenAPI specifications called x-extra-annotation, that hints the generator to add additional annotations to the generated code. For example:</p>\n<p><a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/3b7200d2b5bdbad6cc73dd1ec7eea01b/c59f2/img7.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 590px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 42.0654911838791%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAIAAAB2/0i6AAAACXBIWXMAAAsSAAALEgHS3X78AAAA90lEQVQY011Ri3LDIAzLdwX8DGBIclm3dv//KzOkbbbdCSL7EJHMFAC3hHfDW6GibIpZsAgQ8RwhRgwRQsQ4EJ4YHcDJxUhcitQqLdPWZK26b5ps0Sy8iDZVE04sjixiKl5mjjjESngYW7P981H3g0SAGZlI2A2QOiEvO6Tzsxx/jpgEvxseme6rWNIQ3C2cPv3EfxKvzuTL9XXBR8WPgqsl1gwos2dzAUC4ol6x+12n2AHQlTfjVu3r2Pfmd8DSHTIrk0fwXQf3ziJP22+xMo5Rgwm4EUdysYr6R31anfjeR5i1i+NL3M0DzsPS/Asx/rH9fqoz8w9383gSSHlPaAAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n    ></span>\n    <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;box-shadow:inset 0px 0px 0px 400px white;\"\n        alt=\"img7\"\n        title=\"\"\n        src=\"/static/3b7200d2b5bdbad6cc73dd1ec7eea01b/40fad/img7.png\"\n        srcset=\"/static/3b7200d2b5bdbad6cc73dd1ec7eea01b/707e9/img7.png 148w,\n/static/3b7200d2b5bdbad6cc73dd1ec7eea01b/649e0/img7.png 295w,\n/static/3b7200d2b5bdbad6cc73dd1ec7eea01b/40fad/img7.png 590w,\n/static/3b7200d2b5bdbad6cc73dd1ec7eea01b/c59f2/img7.png 794w\"\n        sizes=\"(max-width: 590px) 100vw, 590px\"\n      />\n  </span>\n  </a>\n<em>Fig 7. OpenAPI specification with java annotation hints</em></p>\n<p>The above attribute would result in generating the following annotations in the output classes:</p>\n<p><a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/15371fc83c17be4c4f2aed0b11ea5ead/49981/img8.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 239px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 80.3347280334728%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAQCAIAAACZeshMAAAACXBIWXMAAAsSAAALEgHS3X78AAACXElEQVQoz3VSaW+jMBDlr6y23Sox+MoBJQZzmJsEDIHcaqr2Q///L1i7h9R2u08jCwa/mTdvMI4HUm/aaiPDOIlEtmn7tGiTBI1bsFmb69psGx29NFcrhBD5DGMcaFa2WdnwUISxKOtN3QxRSDsJqtJKE7iurTy3VBXHwRh/JT89Ts7H221/E4XT6QSaJrBMy7IIANSydJjm+/mNqcnNxlTlA449D9s2WS5V0OUCLxaYUvI5/oXx/DQZB3DYTfsOnE/Tba/VXh8mVWmqbghRCCkmP8PopKluF7nFfRRFUAgYhfr0PcRWSJ0eQ/P5f8iqyeU0UWZuO3A6TpUxwxbI1lTllBbtcwfUtPin7sZ+BHVpJQLWlVVkylWt4i2yDGYpqkooYjSj7/hK3k+z3EozvQ8pwXoN8sIsSjPPlZGTNLkrsruAT9UKIIQIQqxs+ChhbAPymJKek44TNkPSw7uQjBz6rtuOVzk87s4vdbOX28NweBiP1yjOgzB+27iRMhLfE9/BwqOuPfcdkjAqVtR1lsznSRqlec4Dnwfc5yrBXNd2nHvyaoEBMZkAGkbgcmXD+aUdT35SVXK3O12zou7k74fLr17ejcPtMNzsdzeH/R8ILYT1j2qoAZSE5RwLfx4zm7uLxJuvnGWUZCLNPd+LBVsu5p57zxkLPT9gnmuzlcOUhQbSJhBuk6PAMoBHga45Sl1YrGXdyKJq95fnIEjqqBvKyyYZyqipRd+ljWdTIxKpml7Z97ZMFQjriZSrCvg1pdWphEphnXl1S1M0WamnnzD79jibfbzMvnyk9C8cUt6lafmjgAAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n    ></span>\n    <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;box-shadow:inset 0px 0px 0px 400px white;\"\n        alt=\"img8\"\n        title=\"\"\n        src=\"/static/15371fc83c17be4c4f2aed0b11ea5ead/49981/img8.png\"\n        srcset=\"/static/15371fc83c17be4c4f2aed0b11ea5ead/a9a92/img8.png 148w,\n/static/15371fc83c17be4c4f2aed0b11ea5ead/49981/img8.png 239w\"\n        sizes=\"(max-width: 239px) 100vw, 239px\"\n      />\n  </span>\n  </a>\n<em>Fig 8. OpenAPI generated extra annotations</em></p>\n<p>Generics is a very powerful feature that is available and widely used in the Java language for almost two decades now. Unfortunately, as of the time of writing of the article the OpenAPI does not support out of the box <a href=\"https://swagger.io/docs/specification/data-models/inheritance-and-polymorphism/\">inheritance</a> together with generics. To make it available to our developers we have introduced yet another attribute in the API specification named x-make-parent-generic specifying the genericType sub-attribute that indicates a generic type of the parent class (in this case PageDTO):</p>\n<p><a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/5ad75253da4419e8bcbaa02dd019b052/356aa/img9.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 590px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 57.06214689265536%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAIAAADwazoUAAAACXBIWXMAAAsSAAALEgHS3X78AAABMElEQVQoz4VR2Y6DMAzkb0qSScDk5Aq09JL2//9nDVRtH7ZbK4cVZTz2TKGUSqQuEeeI0eEcMHkdajVaOTaiI0mVllL9GcV+RcI94RTUNYELZYeld5fcHofoGpIf0DsYvVU/HWavE2GyGKyumpD63I1zY72U4oXY6uzVCj5thSXgGIzWphT8EbxkKcrDgRfTQuEJA8CJNoBGsT0rATM4zeTJVoZ06KjNPmUfRxcH67sm9E3Kax56287re22rtW3GQ5tAmge2tQndOC3XYZpNZaR6mxZq74A5XzNvjbDmuLer1DnS0lvv3OPv53iAOcgonpzx2apbZCF0yQJ8cundKsYLuSo3ezZMZ7Y6eGoc1fSNecv0ho9b81RXach5Oub5BOAL81MRblPsTgqOkvc/zL/yGnlteNMNWAAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n    ></span>\n    <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;box-shadow:inset 0px 0px 0px 400px white;\"\n        alt=\"img9\"\n        title=\"\"\n        src=\"/static/5ad75253da4419e8bcbaa02dd019b052/40fad/img9.png\"\n        srcset=\"/static/5ad75253da4419e8bcbaa02dd019b052/707e9/img9.png 148w,\n/static/5ad75253da4419e8bcbaa02dd019b052/649e0/img9.png 295w,\n/static/5ad75253da4419e8bcbaa02dd019b052/40fad/img9.png 590w,\n/static/5ad75253da4419e8bcbaa02dd019b052/356aa/img9.png 708w\"\n        sizes=\"(max-width: 590px) 100vw, 590px\"\n      />\n  </span>\n  </a>\n<em>Fig 9. OpenAPI specification with java generic type hints</em></p>\n<p>The above attribute would result in generating the following generic parent in the output classes:</p>\n<p><a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/c7fb92492525b6a3a247d7599896a9d1/ac3f0/img10.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 414px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 19.565217391304348%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAECAIAAAABPYjBAAAACXBIWXMAAAsSAAALEgHS3X78AAAAj0lEQVQI142N0Q7CIAxF+SNpCxOGwBhOxxY2NdmD//8jIpvvnrTNze1tysygpBZISBJJYBHwN0ycSUdlU2vuWgdlrqq4nPMyoPahKvwH1ABrjBTN8a44iF+Jlf0G9yIqWyJBFagxtkXIDvoWFs+TBed8jIPvgrXeujBe4BVgcacY++f2TnNO83obpyk/rO8+KvczSO2jpckAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n    ></span>\n    <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;box-shadow:inset 0px 0px 0px 400px white;\"\n        alt=\"img10\"\n        title=\"\"\n        src=\"/static/c7fb92492525b6a3a247d7599896a9d1/ac3f0/img10.png\"\n        srcset=\"/static/c7fb92492525b6a3a247d7599896a9d1/441d5/img10.png 148w,\n/static/c7fb92492525b6a3a247d7599896a9d1/51e4c/img10.png 295w,\n/static/c7fb92492525b6a3a247d7599896a9d1/ac3f0/img10.png 414w\"\n        sizes=\"(max-width: 414px) 100vw, 414px\"\n      />\n  </span>\n  </a>\n<em>Fig 10. OpenAPI generated extra generic parent inheritance</em></p>\n<p>Yet another limitation of the OpenAPI generator, was that the key of a generated Java API Map needed to be of type String, this was something that was not sitting well with us, hence we’ve extended the generator to support custom key types via the x-map-key attribute like so: </p>\n<p><a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/7b004dd68dfa6c4824101f30b8f6a9b6/12f07/img11.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 590px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 40.55944055944056%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAIAAAB2/0i6AAAACXBIWXMAAAsSAAALEgHS3X78AAAAy0lEQVQY05WQC2rDMBBEfa5K+5nVz3aciKSB3P8mWdmlkEChgdGyGvS0I02Xwt8z3xonQyCOn2hSGeRjlTkpEX2F+AEcImPne0Nb1jqfWBEi/Qv2RTzgrSXLJZeCZAIVQFRHr/h7MnExj823xdSKwtx9eXzk8C7y6v50nPBv2you5205nc2QlUWUoWpD4sKoejhp3yr22MTXxveZ7y1umXsd/VohBmRDgZ92BhmHrNi48YBdBc5Lq7n3a+9dfK64LyHQ0G/a0f84HvsJqAh39WRMt/4AAAAASUVORK5CYII='); background-size: cover; display: block;\"\n    ></span>\n    <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;box-shadow:inset 0px 0px 0px 400px white;\"\n        alt=\"img11\"\n        title=\"\"\n        src=\"/static/7b004dd68dfa6c4824101f30b8f6a9b6/40fad/img11.png\"\n        srcset=\"/static/7b004dd68dfa6c4824101f30b8f6a9b6/707e9/img11.png 148w,\n/static/7b004dd68dfa6c4824101f30b8f6a9b6/649e0/img11.png 295w,\n/static/7b004dd68dfa6c4824101f30b8f6a9b6/40fad/img11.png 590w,\n/static/7b004dd68dfa6c4824101f30b8f6a9b6/12f07/img11.png 858w\"\n        sizes=\"(max-width: 590px) 100vw, 590px\"\n      />\n  </span>\n  </a>\n<em>Fig 11. OpenAPI specification with custom map key definition</em></p>\n<p>The above attribute would result in generating a map with a custom key type, as depicted below:</p>\n<p><a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/226341eb51cab1bfc49da67dd191bcdb/4c1fa/img12.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 410px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 55.36585365853658%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAIAAADwazoUAAAACXBIWXMAAAsSAAALEgHS3X78AAABHklEQVQoz5WSy5KDIBBF/Z7xAc1DEBCHaKKCoib//y9DzGI2UzUJRVG94Jy+BZ3pvqk1AwDCCHy4MlZTNYh2VvoqKaeAP4Gl4VwxQoBQIB/2zu5H5eey5hhjwGfb9xXZvhVxLYIv56l8WmpcVW/DjyO/H3lcii0WS3gqprHkZ5A3Yt/LEIp9L2KCl2Ke8jV82bZE6H86Wx3EDrsGgoXQ4tvsl7iPPmhjMf59iL9hisFZlGKHuQxj7nrTXb/bXtlB20GpTrROU8pQSoIxwuhlRKc0qxBoAbHHj6G6Oe7jMXoftt2vsR8u1nXLdoxzMMZezBAusVVON2wyYET650alyRAM0uaECNkIIV9nzTljTJ41pbRmQvKGp6miINNlCj8F3oveXsuroAAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n    ></span>\n    <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;box-shadow:inset 0px 0px 0px 400px white;\"\n        alt=\"img12\"\n        title=\"\"\n        src=\"/static/226341eb51cab1bfc49da67dd191bcdb/4c1fa/img12.png\"\n        srcset=\"/static/226341eb51cab1bfc49da67dd191bcdb/cd363/img12.png 148w,\n/static/226341eb51cab1bfc49da67dd191bcdb/45083/img12.png 295w,\n/static/226341eb51cab1bfc49da67dd191bcdb/4c1fa/img12.png 410w\"\n        sizes=\"(max-width: 410px) 100vw, 410px\"\n      />\n  </span>\n  </a>\n<em>Fig 12. OpenAPI generated map with a custom key type</em></p>\n<p>As mentioned at the beginning of this article, our Java services are using the Spring Cloud stack with declarative Feign REST clients, originally the <a href=\"https://spring.io/projects/spring-cloud-netflix\">Spring Cloud Netflix Feign</a> module was used for that purpose, however, with recent upgrades to newer Spring versions it was replaced by the <a href=\"https://spring.io/projects/spring-cloud-openfeign\">Spring Cloud OpenFeign</a> module that resulted in changes in the imported packages (import org.springframework.cloud.netflix.feign.* was replaced with import org.springframework.cloud.openfeign.*). So we ended up in a situation where services use either the old Feign clients (located in their respective packages) or the new ones, yet share the same OpenAPI specification. To support both cases we made it configurable for consumers to go with either one:</p>\n<p><a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/78a40c0a233e8d409fc7e7a34f5db8bf/12d02/img14.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 590px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 12.253829321663018%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAACCAIAAADXZGvcAAAACXBIWXMAAAsSAAALEgHS3X78AAAAYUlEQVQI1xWMBwrDQAwE/TOfmlVOl+CaGP//H1FgGAYWdgqjz6bXpueq+3tBbIQNAJCYWMpVgEgIwlATExQVrc2TCj6nfXe7j7KuLwnD7hI5eqZHL9Q8nUfndMrgEf+urx/0PSGb9SaRqwAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n    ></span>\n    <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;box-shadow:inset 0px 0px 0px 400px white;\"\n        alt=\"img14\"\n        title=\"\"\n        src=\"/static/78a40c0a233e8d409fc7e7a34f5db8bf/40fad/img14.png\"\n        srcset=\"/static/78a40c0a233e8d409fc7e7a34f5db8bf/707e9/img14.png 148w,\n/static/78a40c0a233e8d409fc7e7a34f5db8bf/649e0/img14.png 295w,\n/static/78a40c0a233e8d409fc7e7a34f5db8bf/40fad/img14.png 590w,\n/static/78a40c0a233e8d409fc7e7a34f5db8bf/b3fef/img14.png 885w,\n/static/78a40c0a233e8d409fc7e7a34f5db8bf/12d02/img14.png 914w\"\n        sizes=\"(max-width: 590px) 100vw, 590px\"\n      />\n  </span>\n  </a>\n<em>Fig 13. OpenAPI generator configuration with OpenFeign code enabled</em></p>\n<p>Another shortcoming of the default OpenAPI Spring MVC generator was the lack of support for making the generated classes implement specific interfaces (using the “implements” keyword), as of version 4.3.1 only the “extends” keyword was supported. We have overcome this limitation by introducing a custom attribute x-codegen-implements allowing us to specify a number of interfaces the generated class should implement.</p>\n<p><a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/d754a293adc061f24006aedefc0d5199/d8b42/img15.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 590px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 71.93548387096774%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAIAAACgpqunAAAACXBIWXMAAAsSAAALEgHS3X78AAABh0lEQVQoz41S23KjMAzNz2zji2wDxvjKnYSk7e5D//9jKkOzaWfSaTViEGaOdI6OD0GL1cHZwdWLkxOmUozxX8aBcggV38D84iUIiadwix/AUgjKeFfzlygJKMoYo5SQIzkesfgBvE8QgHgYG1EpUWrjY+tCwoLmZnzPB2B8BACSbwr+L0Ey0ju/LKdxnINtFLBC8lLyQj6QcBBCbNrAlnk4Kn91ZNFPQf159fTi4a0TzwFGV+A64FN8TP7/jY1CbKdlje3QDlPqRzwjOSjdFkFztSe9a76hwcc0n59j28VumE6r81Hr2lpfVRX2baxvrDONqxt7p70TwdKHOM2nEFNM3Tif234MqZuWC2KwVz8t2BNPQuw+wHlhDEYDfyOsls01uVjWG4kWIsPsHM22oXlZwJ6U3CeLbWeD4WtQXKq8CM43y7NX+3rga3yhjX/RlaERUYtSCVWUSBVT14Z9c2PvYHwRBqbgVw9RS21santUiLI3kvD4knwmgzqPKJVlyuTm0nfX8x2Rk5x4tpj1LQAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n    ></span>\n    <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;box-shadow:inset 0px 0px 0px 400px white;\"\n        alt=\"img15\"\n        title=\"\"\n        src=\"/static/d754a293adc061f24006aedefc0d5199/40fad/img15.png\"\n        srcset=\"/static/d754a293adc061f24006aedefc0d5199/707e9/img15.png 148w,\n/static/d754a293adc061f24006aedefc0d5199/649e0/img15.png 295w,\n/static/d754a293adc061f24006aedefc0d5199/40fad/img15.png 590w,\n/static/d754a293adc061f24006aedefc0d5199/d8b42/img15.png 620w\"\n        sizes=\"(max-width: 590px) 100vw, 590px\"\n      />\n  </span>\n  </a>\n<em>Fig 14. OpenAPI generator configuration with custom interfaces</em></p>\n<p>The generated output for the above configuration can be found below:</p>\n<p><a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/39a7721d4f479f53c1a0c726480ea48c/3abe0/img16.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 447px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 48.32214765100671%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAIAAAA7N+mxAAAACXBIWXMAAAsSAAALEgHS3X78AAAA6klEQVQoz52QwXKEIBBE+SCJDDOI4mKMiiKg+f+/Cex6SE4pd4pDz1R1vW4YtSQEgIQ3hrVjY73RVoG4b1YdyrewxZxipXWBIkLOL+7w2fdZnWcVAz9SRXSvPMvOI/EUud94DNXqquzP+JICXuKaX/K5CmD7+pECTzsPnu87xkC9kSRBEzQIRKhUQ0hESiKqpsmCVH7lwIKFQYN/wNyKcV6dT5Ptoq3PTxke9TSYfFmcX9zaG7OFY1n97PbJjcMXMvmEaBSKUOu2IDBLvIL+6fi6wVUidzaqYAvEdssWpsWN/TR0Roj63w/7AXQofA9Nj9+NAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n    ></span>\n    <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;box-shadow:inset 0px 0px 0px 400px white;\"\n        alt=\"img16\"\n        title=\"\"\n        src=\"/static/39a7721d4f479f53c1a0c726480ea48c/3abe0/img16.png\"\n        srcset=\"/static/39a7721d4f479f53c1a0c726480ea48c/64cd7/img16.png 148w,\n/static/39a7721d4f479f53c1a0c726480ea48c/5cfb8/img16.png 295w,\n/static/39a7721d4f479f53c1a0c726480ea48c/3abe0/img16.png 447w\"\n        sizes=\"(max-width: 447px) 100vw, 447px\"\n      />\n  </span>\n  </a>\n<em>Fig 15. OpenAPI generated class implementing custom interfaces</em></p>\n<p>Teams often run into the situation where they have to use multiple OpenAPI specifications to generate the necessary contracts to communicate with the upstream services. Unfortunately, the org.openapitools:openapi-generator-maven-plugin requires a separate configuration for each specification, which was a bit too verbose and too cumbersome for us.</p>\n<p><a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/8de608c76b8f364a46c3b5bc27945bb0/b0a39/img17.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 590px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 110.11699931176875%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAWCAIAAABPIytRAAAACXBIWXMAAAsSAAALEgHS3X78AAACdklEQVQ4y41UCXKjMBDMb2JACN0HCIG4bOeq/f9rtmXjjZN1andKJSjQaHp6euZJCbolFVtujHZtsK51Tvet1JLXNW1ozSihNake2VNZVr3nb4uZorW+M9ZZ65y3xhiltNWsNQ0C4NgDZ1IRSknwfAySNQ2ldU3K5+eiKEoY9stL9TgyIQS/4A9nADY5ImNNTXaryGPIN2c8EG4d5BSlUFoIbmRd5bDFAeuwo7hZVdyQ7M7Y+5a/LuaYZOdzsgqZO9M5GTvtjKgppU02gOKsvsJ5uoLDVfj6vpq31czLHIY5pXRe+9djjL031kogkgrmdNNaBv4RfnfGNYLVx6S3EeBN19psmnWWeg0Sq8PhkNPIVh5uuD9hY+8sW0e1DHIdBAAbH2xerfeu83oMIrYiOG4U/cw5U1oRXN059r7Zl8UA/zZ3MS1DmvshrZM/Txq4Xhbk35Tf2EbCQ8dfZgXOkZJVDKz8VN7vpZqjfFshLgVJomyHn4XxwPkiEoXctNZGQ2e7Mshl/cMZW2cbkMGFlkqiHvhSVjl6eX3cGfk7MkjeRoUmQc1oFjkUQdFSgtcNJfca+6Kwq0jg876Zj6Nd16kf5yFN2zKcN8gl9KHVBn1mIX1vePT8SuensxT018nBf136PsL6KSq0evAMXV2W+UxZ7aIgX+pMCEhGtU65nuqUZGgh8DbPBu8hNmdl37LgWAeRyOYO9uUyiCRPlVHNMVc7RQeFxHEKcZxHBwj4dUoQCfvTpDthRVkJnucRIqcgx05AJ3kKYTUQDOVNfe2nOjfr3RgCmSkI9BPmieRoGFI+sOq+k3dno5rzrFFhsF1c5s5/SGu33z+Y/g5lFP7GAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n    ></span>\n    <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;box-shadow:inset 0px 0px 0px 400px white;\"\n        alt=\"img17\"\n        title=\"\"\n        src=\"/static/8de608c76b8f364a46c3b5bc27945bb0/40fad/img17.png\"\n        srcset=\"/static/8de608c76b8f364a46c3b5bc27945bb0/707e9/img17.png 148w,\n/static/8de608c76b8f364a46c3b5bc27945bb0/649e0/img17.png 295w,\n/static/8de608c76b8f364a46c3b5bc27945bb0/40fad/img17.png 590w,\n/static/8de608c76b8f364a46c3b5bc27945bb0/b3fef/img17.png 885w,\n/static/8de608c76b8f364a46c3b5bc27945bb0/301c0/img17.png 1180w,\n/static/8de608c76b8f364a46c3b5bc27945bb0/b0a39/img17.png 1453w\"\n        sizes=\"(max-width: 590px) 100vw, 590px\"\n      />\n  </span>\n  </a>\n<em>Fig 16. OpenAPI configuration with the default openapi maven plugin</em></p>\n<p>In order to circumvent this issue we have created our own maven plugin The main aim of it was to reduce the boilerplate configuration, yet keep the flexibility of the original plugin:</p>\n<p><a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/a8f9327908550a8523a8deb230d330fa/5d76c/img18.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 590px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 69.0625%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAIAAACgpqunAAAACXBIWXMAAAsSAAALEgHS3X78AAABi0lEQVQoz41T7XKDIBDs20QRETgO0USN+JHaj/d/nS7VJDP90cnOCSgue3unb1LKvrXjxXomrhv2IdSuDdZqVamylMU/eMOlq/Jj4q8l9MPF1wHsENiT8gSyyLIcyHLxCCHuZChjIqOWgbZIc2/XK8XOsCPncUbN7D27ttZ7NF57l1ISOxnI8mI42+/Vb9Fvk7+NNE/DtG7XaYlx+Fzq78V/zP5r8evokOlTeUfsCHtbZLy6RTdeu36cu2Fszl3fd/M10W4j30Y39eSsQvKJnIsisIbt98jzQIEVk0KpkrsEzFgXx00uYHSv5KFcyMK7Cqd2rTXWaUPGEjn4ZksYnbWEBVPyrFTSe5LFrziUL43R2hpjtQGeC63xHPdIqlL3Bh7VBpo6Zb5eGYCsIcAhkAE0jYU27cqVkuLeZ1lVEjX4nHx/tkg+uYWz1N00HnE3/LfPSKNvzXt0ZMrTKZXnsf0/Ds+nTNRcoVsO3wS7wJV8kQwZT6nUfWOL37NKKV9V7hqDH4NdJV/jPPADTk6hFlbPAUQAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n    ></span>\n    <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;box-shadow:inset 0px 0px 0px 400px white;\"\n        alt=\"img18\"\n        title=\"\"\n        src=\"/static/a8f9327908550a8523a8deb230d330fa/40fad/img18.png\"\n        srcset=\"/static/a8f9327908550a8523a8deb230d330fa/707e9/img18.png 148w,\n/static/a8f9327908550a8523a8deb230d330fa/649e0/img18.png 295w,\n/static/a8f9327908550a8523a8deb230d330fa/40fad/img18.png 590w,\n/static/a8f9327908550a8523a8deb230d330fa/b3fef/img18.png 885w,\n/static/a8f9327908550a8523a8deb230d330fa/301c0/img18.png 1180w,\n/static/a8f9327908550a8523a8deb230d330fa/5d76c/img18.png 1600w\"\n        sizes=\"(max-width: 590px) 100vw, 590px\"\n      />\n  </span>\n  </a>\n<em>Fig 17. Reduced OpenAPI configuration with the custom openapi maven plugin</em></p>\n<p>We have decided to keep all of the OpenAPI specifications in a single place - a GitHub repository. In order to have proper release management and versioning of the OpenAPI specs we have made it part of our Jenkins pipeline. Upon a merge to the main GitHub branch we pack and upload the changed, and automatically versioned, specification to the artifactory. From there, it can be simply imported as any other maven dependency and used to generate the required API classes.</p>\n<p><a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/7124827bd997165a9dcd229f30eb99f9/af01c/img19.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 590px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 64.93506493506493%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAIAAAAmMtkJAAAACXBIWXMAAAsSAAALEgHS3X78AAABl0lEQVQoz22Si3KsIAyG920qoosKqAvKJYBob9OZvv+7NK7dntPtZjAThD+Bj5xKSo1qX6L8WIfX2GeQ7FwRQsqbkZKS3ePGezvhV5S0berF8ecgN5CYi7GWNe2ZoTW41DU1elo+ElcVLff0NMy7fvVyic5DnKwPTm3QvaV+C7Kuq4KU9+JDf66rZHl2YgORQFmIs4FgxwDTAuMKwulOctxV/a58jbB4NCJ7AWA8wJaMs5eO93K4cCEGwfTQqKGpqz+VG1bbK7aX2Ac/9aIdRS15jcBoSegOjiJE8vfYuCC68+c2vqUBgc0XVhTF01NRXJkTQvGqGFW3M95Xxpsg0uQEFo+Wz8bq2Y5KazV63SQrYO4Oro9p4/9o+AoS2axRxSW7kGfrIPjs++wlplicGCQ7JP/Ex+GD4Qg8+SHEkLcNsc3Wq8mqSU+Iz2jMjgMmjo2E+7/vXF77BFHje6Jm0mNy3Khuz7zn/vb0iG6vdTpQ4zN85OE97x3qpxYXfxqU/u6s/+e7+NIjEo5IrG5xMFaRB438wL4ApXOao9LJCLkAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n    ></span>\n    <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;box-shadow:inset 0px 0px 0px 400px white;\"\n        alt=\"img19\"\n        title=\"\"\n        src=\"/static/7124827bd997165a9dcd229f30eb99f9/40fad/img19.png\"\n        srcset=\"/static/7124827bd997165a9dcd229f30eb99f9/707e9/img19.png 148w,\n/static/7124827bd997165a9dcd229f30eb99f9/649e0/img19.png 295w,\n/static/7124827bd997165a9dcd229f30eb99f9/40fad/img19.png 590w,\n/static/7124827bd997165a9dcd229f30eb99f9/b3fef/img19.png 885w,\n/static/7124827bd997165a9dcd229f30eb99f9/af01c/img19.png 924w\"\n        sizes=\"(max-width: 590px) 100vw, 590px\"\n      />\n  </span>\n  </a>\n<em>Fig 18. Example OpenAPI specification import</em></p>\n<p>Once having the OpenAPI spec dependencies defined in the pom file, our custom maven plugin iterates over the all available OpenAPI specs and generates code for them, honouring the defined configuration.</p>\n<p><a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/f10a02f1ddb743b1299bdff64086a94b/5d76c/img20.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 590px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 51.5%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAIAAAA7N+mxAAAACXBIWXMAAAsSAAALEgHS3X78AAABJElEQVQoz41R2ZKDIBDM3wQQBbnFKCpqzLX//zk7iLWbl63NVNdw9nQznCil26S/rm4aL67xzlnvndXcqFJwijEmhEACIHxMCClynIDMWRl7eY9qDWIJEnJjpdROaauN1Vo7K1rL/Q6nuajLg1xSinDRuvoxm/tsbpN+zHqZ2rhu43wdpnibm9dqnssB4BcFzeJJGfx0vs5nUOK1mHn0/RDDGNsutF0XB7+Nahv1dVDroC5NDZK7ckl7L+7RLEFlb+BCigrKl3AGSJGGtKIJrEpbh+3gk+fG8PMZI4TPiODdVUo/zcnLPHlvGEJEiSr2QmuplIGWQO031p9xAntwNXgx95IzVlUMmp9d/U+WkoVW9D69c/9D8onmQTaSATAuPqb8xjdB3XON5TSU2AAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n    ></span>\n    <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;box-shadow:inset 0px 0px 0px 400px white;\"\n        alt=\"img20\"\n        title=\"\"\n        src=\"/static/f10a02f1ddb743b1299bdff64086a94b/40fad/img20.png\"\n        srcset=\"/static/f10a02f1ddb743b1299bdff64086a94b/707e9/img20.png 148w,\n/static/f10a02f1ddb743b1299bdff64086a94b/649e0/img20.png 295w,\n/static/f10a02f1ddb743b1299bdff64086a94b/40fad/img20.png 590w,\n/static/f10a02f1ddb743b1299bdff64086a94b/b3fef/img20.png 885w,\n/static/f10a02f1ddb743b1299bdff64086a94b/301c0/img20.png 1180w,\n/static/f10a02f1ddb743b1299bdff64086a94b/5d76c/img20.png 1600w\"\n        sizes=\"(max-width: 590px) 100vw, 590px\"\n      />\n  </span>\n  </a>\n<em>Fig 19. Example OpenAPI maven plugin configuration</em></p>\n<p>When dealing with a large number of microservices a common case is that they share common features, hence common models, within a single bounded context. In a typical Code First approach operating in the Java ecosystem this problem would be solved by sharing a common jar which would be then included by the interested parties. We were interested in achieving similar functionality but from the OpenAPI perspective. We achieved this by simply extracting part of the common functionality into separate specification files <a href=\"https://swagger.io/docs/specification/using-ref/\">and referencing</a> them from the individual OpenAPI specifications that would like to reuse these definitions.</p>\n<p><a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/4018acea1cacb761c14c212fb99b3e8b/71150/img21.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 590px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 65.57632398753894%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAIAAAAmMtkJAAAACXBIWXMAAAsSAAALEgHS3X78AAABKklEQVQoz5VSW47CMAzkNts2dh6N82wpoAWk3fsfaCcFJGDFR62RZTUZjz3N7hj4t1LxPPSDUsCG2DHRQVgsK22YeRt5UFRHumR92lfv/dD3G8hEpKjxFw9tS8Tbxk6Ozol+qr4sOUff9f3wId7JkI2O9sLY2mBxzcbYF9hHthZK72MPimfhYzbL93VeDjHllCsQUJSaS6vXYkKXZ/11Z0Vi6BBoEoPe3VfXd694xPDfsFtg7ckzpnfBOrHOr1msHQ26q9VX9YkMw53Ruu2mbzdhfPOe1Cfz7mRcOUW6FhNzkRBZt0DGs9HaPKDvhcFz0k9kKMNzr0ZnvATwRYJfEWKUkIC1ThITjHSjh/iL8jlxTaFMexjb7M3N6jLNpc7I+IijdlrnOi34c3/dyo7FFW5PJAAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n    ></span>\n    <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;box-shadow:inset 0px 0px 0px 400px white;\"\n        alt=\"img21\"\n        title=\"\"\n        src=\"/static/4018acea1cacb761c14c212fb99b3e8b/40fad/img21.png\"\n        srcset=\"/static/4018acea1cacb761c14c212fb99b3e8b/707e9/img21.png 148w,\n/static/4018acea1cacb761c14c212fb99b3e8b/649e0/img21.png 295w,\n/static/4018acea1cacb761c14c212fb99b3e8b/40fad/img21.png 590w,\n/static/4018acea1cacb761c14c212fb99b3e8b/b3fef/img21.png 885w,\n/static/4018acea1cacb761c14c212fb99b3e8b/301c0/img21.png 1180w,\n/static/4018acea1cacb761c14c212fb99b3e8b/71150/img21.png 1284w\"\n        sizes=\"(max-width: 590px) 100vw, 590px\"\n      />\n  </span>\n  </a>\n<em>Fig 20.Example specification reusing “common types” stored in separate definition files</em></p>\n<p>The challenge in having OpenAPI specifications referencing other OpenAPI specifications was the dependency management and versioning part. It was especially hard from the consumer perspective, since consumers would need to include both specifications in their respective versions (the referencing one and the referenced one) in order for the code generator to succeed. The solution for this was building API bundling, by adding to the specification a meta attribute called x-bundle-apis we could make all referenced definitions to be included in a single final artifact that was then uploaded in the CI pipeline to artifactory. This meant, from the consumer perspective, that they just needed to include a single dependency now, making their life significantly easier.</p>\n<p>By default, when bundling the API we’ve always included the latest referenced specification. Since we have had cases where we wanted to give more control to the API owners to specify which concrete version of a “common API” they would like to reference, we’ve included another attribute x-bundle-imports which could be used as following:</p>\n<p><a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/e0131fcee2a3f97574b40e2ae71c06b3/3441b/img22.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 590px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 79.49921752738655%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAQCAIAAACZeshMAAAACXBIWXMAAAsSAAALEgHS3X78AAABd0lEQVQoz5VS2Y7bMAz058QSaYm6JTvKpt2g+9T//5yOFaQ5WmB3BzQxkDUUr6k53f188nN1FGKagcMOpZT+DFMUPm/t/bR9/OillFzXum7b8WSM/VQ/WcO11LZuZe0xZdC6Ho/97UviHvj3qnvkw2FW6mrArL+ASWuqQlmYjeA1/R3s4mDpo/KllxQ8WvUNMTMpTcnSW9AislhBuJvB0d3+Hj6Ks6NL5l/V/Gy+5YDiMS58an7FSwsnhJSF0DZn2JjFWutC9D46H8R5v/PgQxg+GiuP+omIFHESPqVl62dMGKuCmcHj9pUMn+FF3JMYaaMSt9B7IugN00j7/3hNmwaQfHNUHQbGEowEK95ItFdyfeDWs3/FGmVTC8tep/d0u0z3y0qrYXrfoUEeX/Z0TgytuLCP6BaUiOkZjEyIn8Q90qVwCRJzzbVhzXOBx+KvWPhSN+w9OH6VhpMVqru4CB0DRS9Dk+NoL1qNKMNqSDuJ4GmP65z/A+qusDEcXT6KAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n    ></span>\n    <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;box-shadow:inset 0px 0px 0px 400px white;\"\n        alt=\"img22\"\n        title=\"\"\n        src=\"/static/e0131fcee2a3f97574b40e2ae71c06b3/40fad/img22.png\"\n        srcset=\"/static/e0131fcee2a3f97574b40e2ae71c06b3/707e9/img22.png 148w,\n/static/e0131fcee2a3f97574b40e2ae71c06b3/649e0/img22.png 295w,\n/static/e0131fcee2a3f97574b40e2ae71c06b3/40fad/img22.png 590w,\n/static/e0131fcee2a3f97574b40e2ae71c06b3/b3fef/img22.png 885w,\n/static/e0131fcee2a3f97574b40e2ae71c06b3/301c0/img22.png 1180w,\n/static/e0131fcee2a3f97574b40e2ae71c06b3/3441b/img22.png 1278w\"\n        sizes=\"(max-width: 590px) 100vw, 590px\"\n      />\n  </span>\n  </a>\n<em>Fig 21 .Example specification using pinned versions of “common types”</em></p>\n<h4>Challenges ahead</h4>\n<p>Despite the vast number of improvements we have already made in order to retrofit OpenAPI and its tooling into our existing AUTO1 ecosystem and practices, there is still room for improvements. Just to name a few. Although OpenAPI specification itself is language agnostic, we have language specific generators which in some cases need to be instructed on how to generate the output code, and unfortunately these generator hints often make sense only in context of a specific language. As an example, instructing the generator to make the generated Java classes implement some specific java interface. Since the OpenAPI specifications are enriched directly with these hints, it results in obscuring and cluttering the contract definition.</p>\n<p>Yet another challenge would be to generate more complex classes resembling the structure as seen when written manually in the times from before the OpenAPI approach was adopted.</p>\n<h4>The verdict</h4>\n<p>As presented in the article, OpenAPI is a very powerful tool that enabled our AUTO1 organization to move forward faster in a more structured and unified way in terms of defining and evolving the REST APIs. It’s not a silver bullet, as the design first approach and the OpenAPI specification come with a number of challenges by themselves. However, with the talented engineering force we have we were able to resolve most of them in an efficient manner, yet every organization planning to adopt this tool needs to weigh in the benefits and the shortcomings and make the call for themselves.</p>","fields":{"slug":"/openapi-journey/","tags":["auto1","engineering","openAPI"]}}},{"node":{"id":"bf1481d7-2c1e-5f8f-9b67-0b9fec66ad62","frontmatter":{"category":"Engineering","title":"IntelliJ IDEA plugin development - focus on UI based plugins","date":"2021-07-10","summary":"This post is in addition to the previous article about plugin development but with a focus on UI based plugin implementations.","thumbnail":{"relativePath":"pages/IntelliJ IDEA plugin development - focus on UI based plugins/logo.png","childImageSharp":{"resolutions":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAAsSAAALEgHS3X78AAAEyElEQVQ4y3WVe0xTVxzHz723rfZBsVeqnc4Yw0aYFSiFFZlZxnSo4w+gSBWEglTmA59jCt4WCOUxq+J4zGwaMqfJfDBi2GbMxjJfMXMzJks0Y5ngfE0mqAwrFLHtPb+de4CKf+wkv5zfOed3Pr/vOb+Te9FAzEokNV9cLvq/Nmpew8L8DIQOANJUPEdh+wGpBB8jrSldo0hd7n0RLJry0fA4bCg2RxYw5S3zm/ISnsWt1vvi8qZMxD1KLkVvb+lmJifS7hrmpJ4lCfidAy8WAqZ8dqzPSwFzIQRN+UEy95SMbxK7MhK3umQiVlnuLVQKwxcVW//SS2O94JNFFZyja3NLHyD03JSHIN5OMxHQZ5C4Fgg0CAlFAIkOAMs6gIWbiV9sQ0cgTlMl+tW7ATSV+E64y2+R9kWVDXJR226PZZSAUvPG5mpxvP0+MfjjjfTg9eh0/Nv8TPGXBdmBS3H5cC52tS8253SffNMN0BZfHdVu7AK+tC9gIIon1MdsvkXvkKojd2aT1N02ZgXDWBnmGBbLJWM5IL4oZzhQEEOMTESsHBBiAjNzz8BrVSJEb721b3taOzdWlIQien+kECfB8gHciM8NkCHOyLLC711d+MPSUkzGIM159njE5IVJ1CfVgXnZbeKbpQ9Ey84+iCy7kxUqylB8QeQoUTeatAWumteIMhKs43m42dMDFotFAgDDMHD+/HlIT88YA7IsNmUcwWmbb4hRu+4BX9mfGQI+SSiY/SBxneeflJLHZ5NKQM7IqKofOzth1qxZMK4QOjo6CDCd+izLwNLlLXhh+R2sr3oEM4SHy8bUOYz07H0daFrQNWPw57XJQG8iIQEwxmC1WiE1NRWampqgu7sbzGYzBUqniLV9gee4B3GE6zHonAMpFAh7ZPSx+sqmH4Pa6XB5++vSHcJbixbhpsZGSEtLA6PRCK2trZCTkxNSK5m+oB2/4h6WYDjcOZgcOvLDHbxyZJfuT6ifDhc3zA8qZIqXNr5sTMiPsJ/CevcoEFgwzPnETGHPBB1VeG+TwQDV2rNnC98FBmlEhUKG1So1TJ06FeRyOchkMuA47iWgzv4t5msCQGB+ldNrDCns3b6AQgGOs42LS67PnR0J+z9pCDY3N+ODhw7i9RvW08qOW8jX2k/jaTUY1M6nI0rhaSSF9e2IRlXvXKD+paJrEbVL9varp6hBGx7m53lejNDxYrhKE6TKGAYj8tiJT4Ea+5mA1o1B5Rz2KwXvnJDClszDtNKfWw9bW7KOwrYl9bAltQGKF3sgb/k+WJpzAGIcXwYiHV/j2Y7vxAjHD4FwxznQurygqQdQunw9yrIBLYV5rEdRQ/YJCty74qujhwp/gt253/R/bP/+eJPj8vvr3JdWvld95X6Spxeiq//Gc2uegMEDoHP7Iaxy5ILKOVREjjtN2k+UIlS34hgF12UeVtRln/i02ta2aWN6q37ydy9mfQdvFK61zqu4CwZnbx8v9Ddrd95PnBxDVI455dknaE9A7OSA+lWn2Orsdi7zo05uYu5V513LTKHXMDHW12Gkcvk4pTBEi6qegLptJ2nfU9CJam1tXKWtjRFWtSND1S06b3H+yiRWXg8l1Ff8y5G3x6oELyJK0cwa6TfwmK79B0KrRX19cxThAAAAAElFTkSuQmCC","width":325,"height":325,"src":"/static/b2f976ed5fa752977d8f8f9b2516534c/b3029/logo.png","srcSet":"/static/b2f976ed5fa752977d8f8f9b2516534c/b3029/logo.png 1x,\n/static/b2f976ed5fa752977d8f8f9b2516534c/8d141/logo.png 1.5x,\n/static/b2f976ed5fa752977d8f8f9b2516534c/ee72c/logo.png 2x,\n/static/b2f976ed5fa752977d8f8f9b2516534c/5dfa8/logo.png 3x"}}},"authorName":"Vadim Shchenev","authorDescription":"Vadim is an Android Developer at AUTO1 Group.","authorAvatar":{"relativePath":"pages/IntelliJ IDEA plugin development - focus on UI based plugins/avatar.png","childImageSharp":{"resolutions":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAAsSAAALEgHS3X78AAACyElEQVQ4y4VUO2gUURR9mZmN8YcItoKVjeXuzsxu9jOzm92NkBBTqDEmjZAEgtqIpSgI1gp+uhS6kEI7wc7GQsFCLERiISGCaGHhF02yu+M5s/cujyC4cJY379573r3n3XdNvV51xsYiJ4rKbqlUyBj8wjAYyWazp4BVYB3YAraBDeAhMBcE/l76lkrFTLVachuNyCGXEbJMrVbx6ADnaWAtn88nvu8nWBMdQcJ9Auv3wCxjWq2aC9IMSF3DzCyyG1YAs9pSYkL2melmLpfT71tKGkUlz2iZJAuCgA5dEjGAwPoV0AbuAy+tfR7YkZjb5CiXR1OutEw5jWQdCfgCnEiSxNg/7LWAj+KTSiHSzBvrAtascrriPCmnDkP4AYQ0Em3TGPHf8P38ARpP/4PsHQ7aU69Hqdi4OJeI47JXLg9IX1tVbUuWCzSsygcJO+L0goGNRpySoB1colarerhEvcCn4tuxCB/TsC5ZdS3Ct2Ho75uZmRoigWbIbgCxt7Q0O8TLsgg17o2R2+JHzzJcV/1IoBlybel42SLsCcc3I6UqoaZ+lUHFYjjCzJSQa+4J4UVLKiX8ScOGVXJXDN+xd7SfZXFYS65U+n2Wz+cOw+ezHadSkfCRdVJiZdlmMG9ZtHMpgWR3Z0eMSvWExjmrbXoCbZ951dIim7Yk6u1IYtlwavChW51Pp01tXOwf01eC9RHs/Rbbnx2Hf4IUh/Q5zdol8H3KG22Pj9edOK54LF1876pd37TELhqdZ+J4MwxDHUvXgDOFQrB7YqLpjI4WdhG8GLYNbCeBK/1+TWNWRG+Pfy5Hj5Dek3IXzX9+8DkL/AIeLC/PDU1NHXdSQk5altNsDkjPAT+ArzKyFnK5bB2IxbYik4hanmfM5GTL6Q/Y2DUc25y0HLToubR8TI39cL4APJOxr/35AXgOXEJnHKQvepP6eiQj119kDrZjqLo8HAAAAABJRU5ErkJggg==","width":50,"height":50,"src":"/static/26a7a327ccc4b335712e5a7086f2b26d/45876/avatar.png","srcSet":"/static/26a7a327ccc4b335712e5a7086f2b26d/45876/avatar.png 1x,\n/static/26a7a327ccc4b335712e5a7086f2b26d/eb85b/avatar.png 1.5x,\n/static/26a7a327ccc4b335712e5a7086f2b26d/4f71c/avatar.png 2x,\n/static/26a7a327ccc4b335712e5a7086f2b26d/9ec3e/avatar.png 3x"}}},"headerImage":{"relativePath":"pages/IntelliJ IDEA plugin development - focus on UI based plugins/header.png","childImageSharp":{"resolutions":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAAsSAAALEgHS3X78AAADGklEQVQozx3R60/bVRjA8V80m2N4IVkWcfpmqyulTdd7oRYopEDbyaXlVgptobANkAzrUpwbyjZvgMpQ7CxhGCaXUTcv04mRRYMkKpB1MLYpIKkymb5S/4WvZ7745DkvnnOey5FS87qQWbqY0zWyIEzrmxkxHOFHcXZkRZCsZ0ixnmKH9TQPWV7m0eIo22q/JmjvI6ENsijyh7I62G7rYXt2F1KgpIo2TZhlbYBFkTCjDaE2Rdhn6mS36TiPC+nml9ilP0a6rQ91wxwZhxJ4ar9kMbuDdeMR+h0DyAOzyBwxpJDhMCsHAlzXBFgQ7mj8DGqaeUr3Agrt8yh0YWQiZolOq9wTuLxXcFZ/SmHNFVrKL/DKwXMcrPkcu2+aYkGKqkKsquu5rvZzQ7gf19R1nFTUo1M0Y5E3YNWGidu6mSzsQdc0j+ZwgrzgLFUVcWEKn/uiMInfPY40pPKxrvWypPFyU7ilqWZJX8dr9l4UrjFUzlFy3OJS8BqWtmVkRzeQtf/K3qNJCsT4EWeUU65+ely9HHOdQ3pR4Wa1OI8Vez637DaWiwp5tfxtIidmGbywxsilJH2xn3lneI3RyXU+iK3Q1votPu9VfP5vOOGMEbeHmXEcoregV+wwvYx4volk816SoSeZrS3lfPmbfFj2OqPeQcbqo4z7+pnwDvBxYJjJ2iFGSt8j5jhLzPUuY7ndXLREmMruZMJyHCmyq4jO3UWMGg1MO+XM5z7LkiHEDwcamVM28JM6wFpODas5Xm7omljRt3DH1Mptcxu/GFv4yNlNZ3CQPk8P14ytSG+l5XHmESund+ZzcmcuX+xx8ldmNckMD78pKthUevjHXMK/5lLuZlYIlWwpq9lSVJJUeQkFL2N77ntsHfO8URpFGk41M572DLFUI++nGDj/sJnb+0q4l1nFH8LW/yrZ2O8mKfdwVxT5/X4x4c8MN+3ip1XtGxj8X+GouYw081gW9+TlfJaiY/xBJWMPKPlkh5bEEwXc3GMnkV7Ad2nZxLepuZpqYHN/GVvisU3h76dLmDKGsTQuoK+7RJNrgP8AU8rtTZmilCkAAAAASUVORK5CYII=","width":1280,"height":720,"src":"/static/6fae10ea7503a11a8f308ac2e2a5217a/26421/header.png","srcSet":"/static/6fae10ea7503a11a8f308ac2e2a5217a/26421/header.png 1x"}}}},"html":"<p><strong>BACKGROUND</strong></p>\n<p>This post is in addition to the previous <a href=\"https://auto1.tech/intellij-plugin/\">article</a> about plugin development but with a focus on UI based plugin implementations. Sometimes it can be really useful to have an UI and make it possible to interact with it by doing some checkboxes selections or maybe to have some input areas for text. Let's investigate how to develop a simple plugin with input text area as input entry point and some new generated classes, based on input text as a result. As a source code example we will have a look at source code based on my pet <a href=\"https://github.com/robohorse/RoboPOJOGenerator\">project</a> that also was used as a development tool in AUTO1 to generate non GraphQl based POJO classes.</p>\n<p><strong>USER STORY</strong></p>\n<p>As an Android developer I need to interact with backend data. It can be usually presented as JSON data or if we can speak about new and modern practices it also can be presented as a <a href=\"https://graphql.org/\">GraphQl</a> scheme. GraphQl is a really powerful framework with its own classes generation framework. But let's go back  one step and imagine that we have to do some data presentation classes updated for the project without GraphQl support. To do it, we need to find the target class, compare its fields with new JSON fields and update it. It can be easy if we have only one field changed, but for multiple inner fields and classes with its own inner fields it can be too complicated. We can find some online services to convert JSON to POJO and copy/paste output files, but let's try to integrate this technology to our IDE! And our job will be only to copy/paste new JSON to some window input field! Like this one:</p>\n<p><a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/e5f23ade9299ab35fc67e79b19642e81/a8455/ss1.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 512px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 59.5703125%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAIAAADtbgqsAAAACXBIWXMAAAsSAAALEgHS3X78AAABp0lEQVQoz32SWY7cIBCGfZhkpMngBQx4Axsbbxiv7ZnJptwjJ4iSlzzlwKluJ61RZ/n1CSHwX1VU2UkwaVsd1zLLhJD5lc6YwY6DtV1vMpknmciETIWEPSDygjHuEBI2WqZpItKKMk4pO+BRHMXJQd12dpoK3SitZVHIIs9VSXnk3HvBqtCc+9PcxBFByPUucj33EOzLfhr3D/mwq35Jqy5WbVoZwmLHC7AQCSUe5TikBJMbQow9/fEz/vTj1frl9enr3f7tDtan70hMDmTy/QD9yvEXwfEwL9O2y6rJVJUVZ4SqQxY5yPMxxv+0nuV3djTzoprucL40e0HwX7Pv665vjU1zlQFFCQilQ+j2pWwfoQcXeoWQeysEt2ATqpKlFueyX5jBGyUJTAZmw3kcUhayWxoz7M/vHt++t/MKIc6xysPsB3bZxvU0rad526u2T3/XdiWvaii7HazuTFHViSygcwTMPiZ23oZp6YYRomxPz5AHProC4arO1P1QGzufHiFNY8Z+nHmSOvdvHshlxAGhBGrmEax/wCmLABbFFJ4GP2IUw3t/AoHwpaT67vbNAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n    ></span>\n    <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;box-shadow:inset 0px 0px 0px 400px white;\"\n        alt=\"ss1\"\n        title=\"\"\n        src=\"/static/e5f23ade9299ab35fc67e79b19642e81/a8455/ss1.png\"\n        srcset=\"/static/e5f23ade9299ab35fc67e79b19642e81/45806/ss1.png 148w,\n/static/e5f23ade9299ab35fc67e79b19642e81/ae1c8/ss1.png 295w,\n/static/e5f23ade9299ab35fc67e79b19642e81/a8455/ss1.png 512w\"\n        sizes=\"(max-width: 512px) 100vw, 512px\"\n      />\n  </span>\n  </a></p>\n<p>To make it possible, let's think about our problem and try to do small decomposition into logical steps. Lets formulate our goals by imaging simple user stories:</p>\n<ol>\n<li>\n<p>As a user I want to input JSON text into the input field.</p>\n</li>\n<li>\n<p>As a user I want to transform JSON text into POJO files.</p>\n</li>\n<li>\n<p>As a user I want to see the result notification.</p>\n</li>\n</ol>\n<p>We will skip JSON to POJO transformation for this article, but we will learn how to develop a plugin with required user interface. Let's think about option number two as about some library that we already have and can use as a part of our small project.</p>\n<p><strong>TECHNOLOGY STACK</strong></p>\n<p>Before we will start let's have a look on basis plugin implementation. There are 2 base options to develop new plugin:</p>\n<ul>\n<li>\n<p>using <a href=\"https://plugins.jetbrains.com/docs/intellij/using-dev-kit.html\">DevKit</a></p>\n</li>\n<li>\n<p>using <a href=\"https://plugins.jetbrains.com/docs/intellij/gradle-build-system.html\">gradle</a></p>\n</li>\n</ul>\n<p>We will speak about gradle implementation. Gradle is a really powerful framework and it can be really helpful if we want to simplify our building, releasing and testing. The project structure is a common <a href=\"https://plugins.jetbrains.com/docs/intellij/gradle-prerequisites.html\">structure</a> for gradle based projects:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">my_gradle_plugin\n\n├── build.gradle\n\n├── gradle\n\n│ └── wrapper\n\n│ ├── gradle-wrapper.jar\n\n│ └── gradle-wrapper.properties\n\n├── gradlew\n\n├── gradlew.bat\n\n├── settings.gradle\n\n└── src\n\n├── main\n\n│ ├── java\n\n│ └── resources\n\n│ └── META-INF\n\n│ └── plugin.xml\n\n└── test\n\n├── java\n\n└── resources\n\n  </code></pre></div>\n<p>Most important topic for us will be the plugin.xml  file. We already discussed some details in the previous article and we can be focused on some UI related topics.</p>\n<p>During the plugin development we can use Java/Kotlin and all utility tools that we want like jUnit testing and dependency injection frameworks. In our current example Koin and JUnit can be found. So, now we have and know about project structure, some utility tools, language to write the code and now we are ready to think how it can be possible to create a user interface and connect it with our IDE. Let's remember about our major goals:</p>\n<p><strong>GOAL 1</strong> -  As a user I want to input JSON text into the input field.\n<br>\n<strong>GOAL 2</strong> -  As a user I want to see the result notification.\n</p>\n<p>and see how we can implement it.</p>\n<p><strong>GOAL 1</strong></p>\n<p>First of all, let's learn how to connect our plugin with the IDE user interface. As we can see the IDE has a lot of action groups to do something (create new files for example). According to our idea to have some logic that can help us to convert JSON to POJO it would be great to have a new item in the new file list. It will be something like an action “Create new POJO file”.</p>\n<p>To connect our logic with the IDE by following this path we have to remember about the plugin.xml  file that was discussed early. We can use this configuration file to describe our plugin and how it can be used.</p>\n<p>Let's find the actions section and define <a href=\"https://github.com/robohorse/RoboPOJOGenerator/blob/master/src/main/resources/META-INF/plugin.xml#L28\">new action</a> to show our input field dialog view.</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">&lt;actions>\n\n&lt;action id=\"GeneratePOJOAction\" class=\"GeneratePOJOAction\"\n\nicon=\"/icons/pojo.png\"\n\ntext=\"Generate POJO from JSON\"\n\ndescription=\"GeneratePOJOAction\">\n\n&lt;add-to-group group-id=\"NewGroup\" anchor=\"last\"/>\n\n&lt;/action>\n\n&lt;/actions></code></pre></div>\n<p>As we can see we can use some properties to describe how users will be available to interact with our plugin. We can define a custom icon for our action, define the position inside of the items list (“NewGroup” anchor “last”) and we can define the class to execute when action will be invoked by the user.  </p>\n<p><a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/6a7a1fe33666ed623520c2623f9c6a69/2a77b/ss2.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 590px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 50.27027027027027%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAIAAAA7N+mxAAAACXBIWXMAAAsSAAALEgHS3X78AAABjElEQVQoz2VRu27cMBDUpxhx59aNT+L7oQcpUSQlnnQnnxPAQKrE8K8Evi5OFxdBfjLr0yGxEWAKYndnZ2eYXR5e2OPvD4eXi9v/8fPi8OtqOaLtR+dDSJPpeqbKgvIVmfN9ZSwiuMAIE/wWCKO2s0Qquvs0pG3n47CddW1yyjeY5oRltvfjNBvnqdI3mG4I22CWnxZDuzQtEVqlpXWe6woARWiBPiDTjU3z3rheVo0oa65LmKBCrWQoYq7CvIzTDmRV1bzWKQeWqk1GpepCrG3XtA4s1W3XdE5WNQwhxplUiMvCT9b1rY9wCDyY0uezMRdtH6zzLgw3iEB1bZyUOZhiWqvRhiG5EHVjCsoQF/gEIMtpv4S09WMC8b9JAqCVdnvwEne3fhj7OLg4Cl39SxsWwPqVRoSEU9/iVYFJbXvwHNKc5mVeDrysIVcKgQEBVoITmDtPv4OkQjrfhhhCjPDZAExJjjH87ll5zQn03ysLTFlRevP4VD38qB+ey6/P+sv3/P7IPh+v7779AQwRq7SC2ek/AAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n    ></span>\n    <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;box-shadow:inset 0px 0px 0px 400px white;\"\n        alt=\"ss2\"\n        title=\"\"\n        src=\"/static/6a7a1fe33666ed623520c2623f9c6a69/40fad/ss2.png\"\n        srcset=\"/static/6a7a1fe33666ed623520c2623f9c6a69/707e9/ss2.png 148w,\n/static/6a7a1fe33666ed623520c2623f9c6a69/649e0/ss2.png 295w,\n/static/6a7a1fe33666ed623520c2623f9c6a69/40fad/ss2.png 590w,\n/static/6a7a1fe33666ed623520c2623f9c6a69/b3fef/ss2.png 885w,\n/static/6a7a1fe33666ed623520c2623f9c6a69/2a77b/ss2.png 1110w\"\n        sizes=\"(max-width: 590px) 100vw, 590px\"\n      />\n  </span>\n  </a></p>\n<p>Custom action class should extend the abstract AnAction class with the implementation of actionPerformed() method.</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">import com.intellij.openapi.actionSystem.AnAction\n\nimport com.intellij.openapi.actionSystem.AnActionEvent\n\nclass GeneratePOJOAction : AnAction() {\n\noverride fun actionPerformed(e: AnActionEvent) { \n\n//TODO: Add your UI implementation here \n\n} \n}</code></pre></div>\n<p>Inside of actionPerformed() method implementation we can add the logic to show a dialog window with the input field for JSON text. To show dialog view we can easily use DialogBuilder from plugin development SDK and Java swing to create a user interface.</p>\n<p>More information about actions can be found on the official documentation <a href=\"https://plugins.jetbrains.com/docs/intellij/basic-action-system.html\">page</a>.</p>\n<p><strong>GOAL 2</strong></p>\n<p>Let's imagine now that we already implemented logic to show the input text dialog with some selectable options to transform this text. We also added some logic of transformation - that can be some library to work with it or maybe our own implementation. And as the result of that transformation some new POJO files were generated added into our project (We can interact directly with the project or we can use project representation, provided by the plugin development <a href=\"https://plugins.jetbrains.com/docs/intellij/virtual-file-system.html\">SDK</a>).</p>\n<p>But what about the next steps? We also need to notify the user about the result: it can be a success result notification, or maybe some error case notification. To implement it we can use default tools, provided by plugin development SDK. We can show some information to the user by using <a href=\"https://plugins.jetbrains.com/docs/intellij/popups.html\">popup</a>, <a href=\"https://plugins.jetbrains.com/docs/intellij/notifications.html#editor-hints\">notifications</a> or <a href=\"https://plugins.jetbrains.com/docs/intellij/misc-swing-components.html\">messages</a>.</p>\n<p>Let's imagine the following case: we have a text input field and we have some logic to convert/transform the text from this input field. If we can speak about JSON to POJO transformation, we have to understand that any random text cannot be converted to POJO correctly. Target text should satisfy some conditions and also should have the correct JSON structure and it means that we have to not only show some notification if text structure is not valid, but we have to block UI and break our transformation flow.</p>\n<p><a href=\"https://plugins.jetbrains.com/docs/intellij/misc-swing-components.html#messages\">Messages</a> can really help us with it! According to the official documentation:</p>\n<p>The Messages class provides a way to show simple message boxes, input dialogs (modal dialogs with a text field), and chooser dialogs (modal dialogs with a combo box). The function of different methods of the class should be clear from their names. When running on macOS, the message boxes shown by the Messages class use the native UI.</p>\n<p>Lets see the following code:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">companion object {\n\nprivate const val BUTTON_TITLE = \"OK\"\n\nprivate const val DEFAULT_OPTION_INDEX = -1\n\nprivate val DEFAULT_ICON = null\n\n}\n\nfun onPluginExceptionHandled(exception: RoboPluginException) {\n\nMessages.showDialog(\n\nexception.message, exception.title,\n\narrayOf(BUTTON_TITLE),\n\nDEFAULT_OPTION_INDEX,\n\nDEFAULT_ICON\n\n)\n\n}</code></pre></div>\n<p>As we can see we can use the show dialog method, provided by SDK. We can define some dialog parameters, like title, message, button and of course we can define our custom plugin icon. If the image is not defined, standart Java icon or IDE icon would be shown. More information about images support can be found <a href=\"https://plugins.jetbrains.com/docs/intellij/work-with-icons-and-images.html\">here</a>. Also as it was already discussed <a href=\"https://auto1.tech/intellij-plugin/\">here</a> we can add support for internationalization instead of hardcoding only english string values.</p>\n<p>And as the result we can see this amazing small UI blocking window with our message text:</p>\n<p><a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/ccbe6b5c7965f5c43ecabbe66bf5c2c8/adc68/ss3.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 590px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 59.91561181434599%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAIAAADtbgqsAAAACXBIWXMAAAsSAAALEgHS3X78AAAB9UlEQVQoz22S3W7TMBTH8zJMWtd8dCSxHefLSdw4H07SNl27cssFghcYl4hK44bxACBxz7ob1o7uYlofjbN2Kwxh/WT9j33+OsdHVs7O3t/d3a9ubta3t7BfXl39WCx+Xi8XIC4XoEFcL5fL1QqAhF/rNez3m818Plc8j2WZjJI45jxOxYeP888XX0aT6ehkOp7O2snpZPaqGrZpWQlZi0JmRZ6XRVlJPwwVTTe6R91O5/Coc6j2Xn7/+m2zWmV1k8u6qJtE5FzkLEkDFhGHIOqbvjD91ArynkUUo3esG4a2XaaNoc6bt+88FgcxD6LEDSMaRG7AiGhxMbP4+MXg/GD06WB8oXrNH7OqqjahtuMd29jxQ+IFAIgHvACJEzJ4jZmgXkiD2A25iZ5X1nTd6PUAOPkbnhWcc0oJcX0agDl0Q2YivDer2rb6f9A0mJNshm4YPzbigzl+Muu6qnbV7frX2e3C7W4EfpQAICCEWTyYj00TOxRhggjBxDFtZFr2cxDPcjkY1sM2K6uoL8D/aLYwyaomLaQoq0zWLOlDVzRgeyBkPIWEXFZJmsEUMbwczDZWbOLkW3NalFlVN+2Y5wXrp1EqdjDeT+BnVA0wmpzKYQsh/BnkuIpmGOC3ELZsbGOCHRc5FE72QGtPmsLtLgFTF4b1G06By+5CDYTEAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n    ></span>\n    <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;box-shadow:inset 0px 0px 0px 400px white;\"\n        alt=\"ss3\"\n        title=\"\"\n        src=\"/static/ccbe6b5c7965f5c43ecabbe66bf5c2c8/40fad/ss3.png\"\n        srcset=\"/static/ccbe6b5c7965f5c43ecabbe66bf5c2c8/707e9/ss3.png 148w,\n/static/ccbe6b5c7965f5c43ecabbe66bf5c2c8/649e0/ss3.png 295w,\n/static/ccbe6b5c7965f5c43ecabbe66bf5c2c8/40fad/ss3.png 590w,\n/static/ccbe6b5c7965f5c43ecabbe66bf5c2c8/b3fef/ss3.png 885w,\n/static/ccbe6b5c7965f5c43ecabbe66bf5c2c8/301c0/ss3.png 1180w,\n/static/ccbe6b5c7965f5c43ecabbe66bf5c2c8/adc68/ss3.png 1422w\"\n        sizes=\"(max-width: 590px) 100vw, 590px\"\n      />\n  </span>\n  </a></p>\n<p>It looks now that we found a solution to cover the error cases. Now we can prevent users from wrong input and show notification about it. Let's think about the success use case. Let's imagine that the input text was correct and we processed our JSON to POJO transformation as expected. Maybe some new files were generated, maybe it was only one new file. It will be a really good user experience if we can find a possibility to inform our users about it. Maybe one of the possible ways can be to show notification messages. It can be a small popup view with some text, like this one:</p>\n<p><a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/7886ad65f05e9b387cd9fcc518e532eb/a8455/ss4.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 512px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 19.7265625%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAECAIAAAABPYjBAAAACXBIWXMAAAsSAAALEgHS3X78AAAAiklEQVQI123O2Q6DIBAFUH6rspRtEOgWY9rHqoCWP+jvFy1PrcnJZO7kPgyiXArjNRilC5AavkuNCoTUu7hQyDyGa37PMYa0pDmvc8nPcRpDiuk1hNj19123rkdCA1gHrTXWGes3JbpytP7sTpca/2jTogMmDWWYsobQiq4wYaK8bh09crwVfpTmB6TCRCxGPmcyAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n    ></span>\n    <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;box-shadow:inset 0px 0px 0px 400px white;\"\n        alt=\"ss4\"\n        title=\"\"\n        src=\"/static/7886ad65f05e9b387cd9fcc518e532eb/a8455/ss4.png\"\n        srcset=\"/static/7886ad65f05e9b387cd9fcc518e532eb/45806/ss4.png 148w,\n/static/7886ad65f05e9b387cd9fcc518e532eb/ae1c8/ss4.png 295w,\n/static/7886ad65f05e9b387cd9fcc518e532eb/a8455/ss4.png 512w\"\n        sizes=\"(max-width: 512px) 100vw, 512px\"\n      />\n  </span>\n  </a></p>\n<p>and maybe we also can print some information to the event log:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">12:00  Response.java was updated.\n  \n12:00  POJO generation: Success</code></pre></div>\n<p>It looks now that we are ready to totally satisfy our user story requirements! Let's do the final steps and implement the following code:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">companion object{\n\nprivate const val MESSAGE_SUCCESS = \"POJO generation: Success\"\n\nprivate const val GROUP_ID = \"RoboPOJO Generator\"\n\n}\n\nfun showSuccessMessage() {\n\nshowMessage(\n\nproject = ProjectManager.getInstance().openProjects.first(),\n\nmessage = MESSAGE_SUCCESS,\n\ntype = NotificationType.INFORMATION,\n\n)\n\n}\n\nprivate fun showMessage(\n\nmessage: String, type: NotificationType, project: Project\n\n) = NotificationGroupManager.getInstance()\n\n.getNotificationGroup(GROUP_ID)\n\n.createNotification(message, type)\n\n.notify(project)\n\n  </code></pre></div>\n<p>As we can see we can use the create notification method, provided by SDK. Unlike dialog related logic, we also have to define the project that we want to use to show the notification. As an example let's get only the first project (most popular use case), but we have to understand that users can open not only one project in the IDE and we have to take care about it too. So, as we can see it is also possible to define message text. Also we can define the message type (it can be INFORMATION, WARNING or ERROR) and we have to take care about the <a href=\"https://plugins.jetbrains.com/docs/intellij/notifications.html#top-level-notifications-balloons\">notification group</a> that was defined inside of our plugin.xml file:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">&lt;extensions defaultExtensionNs=\"com.intellij\">\n\n&lt;notificationGroup id=\"RoboPOJO Generator\"\n\ndisplayType=\"BALLOON\"\n\nkey=\"com.robohorse.robopojogenerator\"/>\n\n&lt;/extensions></code></pre></div>\n<p><strong>FEW WORDS AT THE END</strong></p>\n<p>As we can see it was not really a big deal to develop some small and hopefully useful tools for daily use or to help your teammates. The major idea is just to understand that integration with IDE can be really simple and when we will finish with it, we can be focused on the functionality of our tool. Perhaps in the future when we will have a stable version with some really cool features we can share our tool not only with teammates that we are working with directly, but maybe it also can be helpful for some developers from some random parts of the world. And maybe together we can simplify our daily job!</p>","fields":{"slug":"/IntelliJ IDEA plugin development - focus on UI based plugins/","tags":["auto1","engineering","android","mobile","intellij","idea"]}}},{"node":{"id":"e2563427-db60-5c74-aaff-0c8c2c483f69","frontmatter":{"category":"Engineering","title":"DevoxxUA was awesome!","date":"2019-12-05","summary":"A few words about one of the biggest Java conferences and AUTO1's presence there.","thumbnail":{"relativePath":"pages/auto1-devoxx/ivan_thumb.jpg","childImageSharp":{"resolutions":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAABQABBP/EABUBAQEAAAAAAAAAAAAAAAAAAAEA/9oADAMBAAIQAxAAAAFobuDFqyL/xAAaEAABBQEAAAAAAAAAAAAAAAACAAEDEzES/9oACAEBAAEFApMKYRldXWI3bvF//8QAFREBAQAAAAAAAAAAAAAAAAAAARD/2gAIAQMBAT8BJ//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EAB0QAAEEAgMAAAAAAAAAAAAAAAABERIhAxBCUYH/2gAIAQEABj8C9H496SmExxqQx//EABsQAAMAAgMAAAAAAAAAAAAAAAABETFRIUGh/9oACAEBAAE/IWihpe8JGzIwO65PagSFoof/2gAMAwEAAgADAAAAEEgv/8QAFREBAQAAAAAAAAAAAAAAAAAAEDH/2gAIAQMBAT8Qg//EABYRAQEBAAAAAAAAAAAAAAAAAAEQIf/aAAgBAgEBPxBNn//EAB4QAQACAgIDAQAAAAAAAAAAAAEAESFBMWFRcbHh/9oACAEBAAE/EPcQfYt7YYNab5CuSAbFIzJ3xnp6mFDht8n9YZ1dVqq6n//Z","width":520,"height":325,"src":"/static/150f8a5d8b98da0a021f785cc45b217a/a2998/ivan_thumb.jpg","srcSet":"/static/150f8a5d8b98da0a021f785cc45b217a/a2998/ivan_thumb.jpg 1x,\n/static/150f8a5d8b98da0a021f785cc45b217a/99cce/ivan_thumb.jpg 1.5x,\n/static/150f8a5d8b98da0a021f785cc45b217a/6e995/ivan_thumb.jpg 2x,\n/static/150f8a5d8b98da0a021f785cc45b217a/968b1/ivan_thumb.jpg 3x"}}},"authorName":"Ivan Kozlov","authorDescription":"Ivan is the senior team lead of the AUTO1 Group Kiev engineering office.","authorAvatar":{"relativePath":"pages/auto1-devoxx/avatar.png","childImageSharp":{"resolutions":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAAsSAAALEgHS3X78AAACyElEQVQ4y4VUO2gUURR9mZmN8YcItoKVjeXuzsxu9jOzm92NkBBTqDEmjZAEgtqIpSgI1gp+uhS6kEI7wc7GQsFCLERiISGCaGHhF02yu+M5s/cujyC4cJY379573r3n3XdNvV51xsYiJ4rKbqlUyBj8wjAYyWazp4BVYB3YAraBDeAhMBcE/l76lkrFTLVachuNyCGXEbJMrVbx6ADnaWAtn88nvu8nWBMdQcJ9Auv3wCxjWq2aC9IMSF3DzCyyG1YAs9pSYkL2melmLpfT71tKGkUlz2iZJAuCgA5dEjGAwPoV0AbuAy+tfR7YkZjb5CiXR1OutEw5jWQdCfgCnEiSxNg/7LWAj+KTSiHSzBvrAtascrriPCmnDkP4AYQ0Em3TGPHf8P38ARpP/4PsHQ7aU69Hqdi4OJeI47JXLg9IX1tVbUuWCzSsygcJO+L0goGNRpySoB1colarerhEvcCn4tuxCB/TsC5ZdS3Ct2Ho75uZmRoigWbIbgCxt7Q0O8TLsgg17o2R2+JHzzJcV/1IoBlybel42SLsCcc3I6UqoaZ+lUHFYjjCzJSQa+4J4UVLKiX8ScOGVXJXDN+xd7SfZXFYS65U+n2Wz+cOw+ezHadSkfCRdVJiZdlmMG9ZtHMpgWR3Z0eMSvWExjmrbXoCbZ951dIim7Yk6u1IYtlwavChW51Pp01tXOwf01eC9RHs/Rbbnx2Hf4IUh/Q5zdol8H3KG22Pj9edOK54LF1876pd37TELhqdZ+J4MwxDHUvXgDOFQrB7YqLpjI4WdhG8GLYNbCeBK/1+TWNWRG+Pfy5Hj5Dek3IXzX9+8DkL/AIeLC/PDU1NHXdSQk5altNsDkjPAT+ArzKyFnK5bB2IxbYik4hanmfM5GTL6Q/Y2DUc25y0HLToubR8TI39cL4APJOxr/35AXgOXEJnHKQvepP6eiQj119kDrZjqLo8HAAAAABJRU5ErkJggg==","width":50,"height":50,"src":"/static/26a7a327ccc4b335712e5a7086f2b26d/45876/avatar.png","srcSet":"/static/26a7a327ccc4b335712e5a7086f2b26d/45876/avatar.png 1x,\n/static/26a7a327ccc4b335712e5a7086f2b26d/eb85b/avatar.png 1.5x,\n/static/26a7a327ccc4b335712e5a7086f2b26d/4f71c/avatar.png 2x,\n/static/26a7a327ccc4b335712e5a7086f2b26d/9ec3e/avatar.png 3x"}}},"headerImage":{"relativePath":"pages/auto1-devoxx/header.jpg","childImageSharp":{"resolutions":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAJABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAIDBf/EABQBAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhADEAAAAe21ELH/xAAZEAACAwEAAAAAAAAAAAAAAAACEQABEiD/2gAIAQEAAQUC0TZSuP/EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABcQAAMBAAAAAAAAAAAAAAAAAAAgMTL/2gAIAQEABj8CyRf/xAAaEAEAAgMBAAAAAAAAAAAAAAABADERIFEh/9oACAEBAAE/IaFO5g3PlzMEdP/aAAwDAQACAAMAAAAQAA//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/ED//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/ED//xAAbEAADAAIDAAAAAAAAAAAAAAABESEAMSBBYf/aAAgBAQABPxClqP0uMAdzbvAsCMJhXD//2Q==","width":640,"height":284,"src":"/static/cae90168dbe3b194c3406bc103d1a5f3/c8462/header.jpg","srcSet":"/static/cae90168dbe3b194c3406bc103d1a5f3/c8462/header.jpg 1x"}}}},"html":"<p><strong>Devoxx</strong>, formerly known as JavaPolis, is an international community conference which first took place in 2001 in Belgium. Since then it has developed into one of the largest Java events in Europe, with chapters in Belgium, France, UK, Poland and Ukraine, as well as an established conference in Morocco.</p>\n<p>Among the speakers at <strong>DevoxxUA</strong> (Devoxx Ukraine) 2019 I’d like to mention <strong>Josh Long</strong>, the Spring Developer Advocate at <em>Pivotal</em> and <strong>Cay Horstmann</strong> (yes, that’s him, the author of “Core Java”, “Big Java” and other great books). I got a chance to participate as a speaker on the second day of the conference, delivering a presentation on one of our latest solutions for implementing GraphQL with authorization in a microservice architecture. Was very excited to see that the talk got the highest amount of participants for that time slot and the room was packed, including people standing on their feet for the entire duration of my presentation!</p>\n<p><a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/0c7d3daa298009c0e59f41dbb964406e/c1e84/talk.jpg\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 590px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 62.5%; position: relative; bottom: 0; left: 0; background-image: url('data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAQFAQP/xAAXAQADAQAAAAAAAAAAAAAAAAAAAQID/9oADAMBAAIQAxAAAAHrjUsl0ii0/8QAGxAAAwACAwAAAAAAAAAAAAAAAAECAwQSFCL/2gAIAQEAAQUCumpnZ4nbZsrzkkdOT//EABcRAAMBAAAAAAAAAAAAAAAAAAIQERL/2gAIAQMBAT8B1Ci//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAGhAAAgIDAAAAAAAAAAAAAAAAAAIBITFhof/aAAgBAQAGPwJZZDBSdII2Uf/EABoQAAMAAwEAAAAAAAAAAAAAAAABESFRYUH/2gAIAQEAAT8htAfXCmJYPyGFX7BOV0fRpMVo/9oADAMBAAIAAwAAABAzL//EABcRAQEBAQAAAAAAAAAAAAAAAAEAESH/2gAIAQMBAT8QyiLl/8QAFxEAAwEAAAAAAAAAAAAAAAAAAAERMf/aAAgBAgEBPxDURn//xAAdEAEAAgICAwAAAAAAAAAAAAABESEAUTGBocHh/9oACAEBAAE/ECIgSshRTjrzhIK7Im3WKag5tT0Yrlo7kyJ8xS6gQlOjOzeGFWJg1Mx6z//Z'); background-size: cover; display: block;\"\n    ></span>\n    <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;box-shadow:inset 0px 0px 0px 400px white;\"\n        alt=\"talk\"\n        title=\"Full room!\"\n        src=\"/static/0c7d3daa298009c0e59f41dbb964406e/f8fb9/talk.jpg\"\n        srcset=\"/static/0c7d3daa298009c0e59f41dbb964406e/e8976/talk.jpg 148w,\n/static/0c7d3daa298009c0e59f41dbb964406e/63df2/talk.jpg 295w,\n/static/0c7d3daa298009c0e59f41dbb964406e/f8fb9/talk.jpg 590w,\n/static/0c7d3daa298009c0e59f41dbb964406e/85e3d/talk.jpg 885w,\n/static/0c7d3daa298009c0e59f41dbb964406e/d1924/talk.jpg 1180w,\n/static/0c7d3daa298009c0e59f41dbb964406e/9452e/talk.jpg 1770w,\n/static/0c7d3daa298009c0e59f41dbb964406e/c1e84/talk.jpg 4000w\"\n        sizes=\"(max-width: 590px) 100vw, 590px\"\n      />\n  </span>\n  </a></p>\n<p>All in all, it was a great experience of sharing what &#x26; how we’ve built while getting valuable feedback and interesting questions. Have to say it felt incredible to stand on stage next to all the stars of the engineering world, during the closing ceremony of the conference!</p>\n<p><a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/6a09cfcfbbf496ecd690c246c1eb193c/c1e84/stage.jpg\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 590px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 62.5%; position: relative; bottom: 0; left: 0; background-image: url('data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAIFA//EABUBAQEAAAAAAAAAAAAAAAAAAAEC/9oADAMBAAIQAxAAAAHBaTlQywM//8QAGRAAAwEBAQAAAAAAAAAAAAAAAAECEhET/9oACAEBAAEFAlDSwxzxzEmIPCD/xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAZEAEBAQADAAAAAAAAAAAAAAAAMQEiMpH/2gAIAQEABj8CjeKI6pnj/8QAHBAAAwEAAgMAAAAAAAAAAAAAABEhATFhcZHB/9oACAEBAAE/IYp10NpCAvsx4qr5LPMPyM+jH//aAAwDAQACAAMAAAAQVB//xAAYEQADAQEAAAAAAAAAAAAAAAAAARExIf/aAAgBAwEBPxCrIPeI/8QAFxEAAwEAAAAAAAAAAAAAAAAAAAEhUf/aAAgBAgEBPxC6Jn//xAAeEAEAAgEEAwAAAAAAAAAAAAABABEhMUFhkVFxgf/aAAgBAQABPxALXY7vM1LAYcd+peIuQZ51jpoKye8DVkzanMU2fIXbP//Z'); background-size: cover; display: block;\"\n    ></span>\n    <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;box-shadow:inset 0px 0px 0px 400px white;\"\n        alt=\"stage\"\n        title=\"Awesome people\"\n        src=\"/static/6a09cfcfbbf496ecd690c246c1eb193c/f8fb9/stage.jpg\"\n        srcset=\"/static/6a09cfcfbbf496ecd690c246c1eb193c/e8976/stage.jpg 148w,\n/static/6a09cfcfbbf496ecd690c246c1eb193c/63df2/stage.jpg 295w,\n/static/6a09cfcfbbf496ecd690c246c1eb193c/f8fb9/stage.jpg 590w,\n/static/6a09cfcfbbf496ecd690c246c1eb193c/85e3d/stage.jpg 885w,\n/static/6a09cfcfbbf496ecd690c246c1eb193c/d1924/stage.jpg 1180w,\n/static/6a09cfcfbbf496ecd690c246c1eb193c/9452e/stage.jpg 1770w,\n/static/6a09cfcfbbf496ecd690c246c1eb193c/c1e84/stage.jpg 4000w\"\n        sizes=\"(max-width: 590px) 100vw, 590px\"\n      />\n  </span>\n  </a></p>\n<p>Here's my entire talk:\n\n        <div class=\"embedVideo-container\">\n            <iframe\n              width=\"800\"\n              height=\"400\"\n              src=\"https://www.youtube-nocookie.com/embed/JbidXuC_0M4?rel=0\"\n              class=\"embedVideo-iframe\"\n              style=\"border:0\"\n              allowfullscreen\n            ></iframe>\n        </div></p>","fields":{"slug":"/auto1-devoxx/","tags":["auto1","engineering","java","conference","talk","devoxx"]}}}]}},"pageContext":{"slug":"/categories/Engineering","category":"Engineering","categories":["Architecture","Coding","DevOps","Engineering","ProjectManagement","QA","Social","TechRadar"]}}