{"@attributes":{"version":"2.0"},"channel":{"title":"SoftwareGarden.dev Home on SoftwareGarden.dev","link":"https:\/\/softwaregarden.dev\/en\/","description":"Recent content in SoftwareGarden.dev Home on SoftwareGarden.dev","generator":"Hugo -- gohugo.io","language":"en","copyright":"\u00a9 Piotr Przyby\u0142 SoftwareGarden.dev CC BY-NC-SA 4.0","lastBuildDate":"Fri, 01 May 2020 11:04:08 +0200","item":[{"title":"Brown Bag Lunch","link":"https:\/\/softwaregarden.dev\/en\/posts\/events\/brown-bag-lunch\/","pubDate":"Fri, 20 Feb 2026 16:00:00 +0200","guid":"https:\/\/softwaregarden.dev\/en\/posts\/events\/brown-bag-lunch\/","description":"<p>Before I started working full time as a Developer Advocate, I had never come across the term BBL. Just reading the title of this post should already disprove the theory that it belongs exclusively to the medical world. It turns out that it does not.<\/p>\n<p>So what exactly is a BBL and what is it not?<\/p>\n<p>I first heard about the concept from my older colleague and a true DevRel veteran, David Pilato. The acronym stands for Brown Bag Lunch. The name comes from the classic brown paper bag with a sandwich inside. Not a three-course lunch. Not a formal dinner. Just something simple you bring with you.<\/p>\n<figure class=\"image image right\">\n<img src=\"brown-bag-lunch.jpg\" alt=\"Brown Bag Lunch\" width=\"640\">\n<\/figure>\n\n<p>That brown paper bag is the core idea behind a BBL.<\/p>\n<p>Most live tech talks happen at conferences, evening meetups, JUG meetings, internal company trainings, or occasionally a Saturday CodeRetreat. If you cannot attend those\nevents, you simply miss out on the technical social life. Not everyone can spend five days traveling to a three-day conference. Not everyone lives in a capital city. Logistics, family, distance, work. Real life gets in the way.<\/p>\n<p>This is where the Brown Bag Lunch comes in.<\/p>\n<p>Instead of going out for lunch and scrolling through your phone while waiting for your meal, you can use that lunch break differently. Bring a sandwich. Or a salad in a box. Just please avoid reheated fish in the microwave. Then gather in the largest meeting room available in your office and attend a live tech session while eating.<\/p>\n<p>You do not travel across the country.<br>\nYou do not even need to leave your office.<br>\nIt is still a live, in person meeting.<br>\nAnd it fits into your lunch break.<\/p>\n<p>In simple terms: BBL equals a meetup hosted at your company. You do not go to the speaker. The speaker comes to you.<\/p>\n<p>How much does it cost? In the context of my current role, it is completely free. That seems like a fair price.<\/p>\n<p>What do you need to do to host one? Not much. Reach out to me. We agree on a date and a topic. That is basically it.<\/p>\n<p>The Brown Bag Lunch sessions I run while working for Elastic follow a few simple rules:<\/p>\n<ul>\n<li>I do not sign any documents, especially no NDA.<\/li>\n<li>Nobody pays anyone. It is based on mutual trust and a handshake agreement.<\/li>\n<li>It is not consulting and not formal training.<\/li>\n<li>Topics revolve around the Elastic stack: search (BM25 and vector search), AI use cases, observability, ES|QL, and related subjects.<\/li>\n<li>The session usually has two parts. First I present a topic. Then we switch to informal office hours.<\/li>\n<li>The atmosphere is relaxed. We do not record the session. A hybrid option is possible if needed.<\/li>\n<li>The minimum requirement is a meeting room provided by the host company for the duration of the talk and the lunch. If the company wants to provide food and drinks for the participants and the speaker, that is perfectly fine and sometimes happens.<\/li>\n<\/ul>\n<p>When it comes to scheduling, I cannot accept every request. Most sessions happen alongside conferences or other trips. Sometimes it is even possible to run two BBLs in the same city on the same day, since not everyone takes their lunch break at the same time. I have already hosted more than a dozen of these sessions across Poland and Europe, and some of them were described on LinkedIn.<\/p>\n<p>That is the whole idea.<\/p>\n<p>If you are hungry for knowledge from the Elastic stack and a baguette from a brown paper bag, just reach out. Let us see what we can do about it.<\/p>"},{"title":"About Java's Structured Concurrency, Elasticsearch Java client, DevEx and Developer Advocate's job","link":"https:\/\/softwaregarden.dev\/en\/posts\/varia\/sc-es-devex-and-devadv\/","pubDate":"Mon, 26 May 2025 16:00:00 +0200","guid":"https:\/\/softwaregarden.dev\/en\/posts\/varia\/sc-es-devex-and-devadv\/","description":"<p>There&rsquo;s been quite a lot happening recently, and I wasn&rsquo;t sure in which order I should tackle the issues, so I decided to cover them all in a single post. If some aspects need clarification or further detail, please DM me, and I&rsquo;ll try to sort it out somehow (perhaps in a subsequent entry).<\/p>\n<h2 id=\"revamp-of-structured-concurrency-in-java-25\">Revamp of Structured Concurrency in Java 25<\/h2>\n<p>First, let&rsquo;s start with Java 25 on the horizon. For many vendors (if not all), it&rsquo;s going to be an LTS release. And Structured Concurrency serves as a great example of why we need preview features. One could say that three preview releases are enough and the feature should be standardized. However, the OpenJDK folks decided otherwise, and I&rsquo;m very glad they did. I think I&rsquo;ll skip boring you with all the details about how Structured Concurrency will be shaped in Java 25 in every nitty-gritty detail. IMHO, reading the <a href=\"https:\/\/openjdk.org\/jeps\/505\">JEP 505<\/a> and watching <a href=\"https:\/\/youtu.be\/vLJDPmXufQw\">Nicolai&rsquo;s video<\/a> can help a lot here, in addition to my own talks, e.g. <a href=\"https:\/\/softwaregarden.dev\/en\/talks\/butcher-virtual-threads-like-a-pro\/\">Butcher virtual threads like a pr0<\/a>.<\/p>\n<p>IMHO, it&rsquo;s great that <code>throwIfFailed<\/code> is now the default, and therefore not needed, as I found throwing exceptions useful every time I tested this new feature.\nThen, sealing the <code>StructuredTaskScope<\/code> and creating new ones with <code>open()<\/code>, where you can provide auxiliary configuration, is simply great for a number of reasons:<\/p>\n<ul>\n<li>It&rsquo;s not that inheritance is always bad\u2014I think I&rsquo;ve seen a number of cases where it actually made sense and was the best option (so my point from <a href=\"https:\/\/softwaregarden.dev\/en\/talks\/context\/\">CONTEXTVS STVLTE<\/a>, that it&rsquo;s not wise to always replace inheritance with composition, still stands). However, providing configuration in the form of a subclass doesn&rsquo;t seem like a good idea to me. When I wrote my custom implementation of <code>StructuredTaskScope<\/code> (for a different success criterion), it always felt awkward. Also, if the evolution of Stream Collectors and Gatherers taught us something, it&rsquo;s that for configuration it&rsquo;s probably better to use composition.<\/li>\n<li>For me, try-with-resources\u2014meant to automatically <em>close<\/em> resources\u2014somehow works better with <em>open<\/em>. I don&rsquo;t know, I might be biased, but it just&hellip; looks better than a constructor.<\/li>\n<li>Sealing <code>StructuredTaskScope<\/code> seems to be exactly what <a href=\"https:\/\/openjdk.org\/jeps\/409\">Sealed Classes (and Interfaces)<\/a> in Java 17 were meant to be used for: easing maintainers&rsquo; lives and making sure the number of &ldquo;useful custom inventions&rdquo; stays limited.<\/li>\n<li>Being able to (re)use a custom thread pool (because virtual threads might not be the optimal choice for some kinds of tasks) or to configure other aspects is also cool.<\/li>\n<li>Last but not least, it also proves the usefulness of the release train concept and preview features: preview features might be okay to try in production as long as they&rsquo;re used in a microservice<sup id=\"fnref:1\"><a href=\"#fn:1\" class=\"footnote-ref\" role=\"doc-noteref\">1<\/a><\/sup>, and you run it in an environment you fully control\u2014but not if you can&rsquo;t control which JDK version people use to run your artifacts.<\/li>\n<\/ul>\n<p>So all in all, in Java 25, a block with Structured Concurrency\u2014where a single method is responsible within its scope for handling concurrent subtasks in a way that&rsquo;s clear to read and understand\u2014may look like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">try<\/span> (<span style=\"color:#66d9ef\">var<\/span> scope <span style=\"color:#f92672\">=<\/span> StructuredTaskScope.<span style=\"color:#a6e22e\">open<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>      StructuredTaskScope.<span style=\"color:#a6e22e\">Joiner<\/span>.<span style=\"color:#a6e22e\">awaitAllSuccessfulOrThrow<\/span>(),\n<\/span><\/span><span style=\"display:flex;\"><span>          config <span style=\"color:#f92672\">-&gt;<\/span> config\n<\/span><\/span><span style=\"display:flex;\"><span>          .<span style=\"color:#a6e22e\">withName<\/span>(<span style=\"color:#e6db74\">&#34;myStructuredConcurrency&#34;<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>          .<span style=\"color:#a6e22e\">withTimeout<\/span>(Duration.<span style=\"color:#a6e22e\">ofSeconds<\/span>(5))\n<\/span><\/span><span style=\"display:flex;\"><span>          .<span style=\"color:#a6e22e\">withThreadFactory<\/span>(sctf))) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">var<\/span> subtask1 <span style=\"color:#f92672\">=<\/span> scope.<span style=\"color:#a6e22e\">fork<\/span>(() <span style=\"color:#f92672\">-&gt;<\/span> action(...));\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">var<\/span> subtask2 <span style=\"color:#f92672\">=<\/span> scope.<span style=\"color:#a6e22e\">fork<\/span>(<span style=\"color:#66d9ef\">this<\/span>::anotherAction);\n<\/span><\/span><span style=\"display:flex;\"><span>    scope.<span style=\"color:#a6e22e\">join<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>    combineResults(subtask1.<span style=\"color:#a6e22e\">get<\/span>(), subtast2.<span style=\"color:#a6e22e\">get<\/span>());\n<\/span><\/span><span style=\"display:flex;\"><span>}<\/span><\/span><\/code><\/pre><\/div>\n<p>The pattern used for configuration emerged independently in another part of the Java ecosystem. Which brings us to the new Elasticsearch Java client ;-)<\/p>\n<h3 id=\"elasticsearch-9-from-javas-perspective\">Elasticsearch 9 from Java&rsquo;s perspective<\/h3>\n<p>After I started working for Elastic, the construction of the Java client was, let&rsquo;s be honest, one of my pet peeves. It&rsquo;s not that it wasn&rsquo;t working\u2014it was perfectly functional, flexible code. In many frameworks you wouldn&rsquo;t even need to construct the client manually, because the framework would do it for you based on environment variables or similar configuration.<\/p>\n<p>The thing is, sometimes your microservice is written properly and really is a <em>micro<\/em> one, not bloated with tons of dependencies. In such cases, you end up with many mandatory lines just to create the ES client in vanilla Java, passing effectively only two things: the URL and the API key. Not the optimal signal-to-noise ratio, if you ask me.<\/p>\n<p>Thankfully, the people I work with are not only clever, but they also listen to fellow developer advocates and implement fixes based on the feedback they hear. That&rsquo;s why Elasticsearch version 9.0 came equipped not only with many great internal features, but also with a new client version, which allows us to write this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">try<\/span> (<span style=\"color:#66d9ef\">var<\/span> esClient <span style=\"color:#f92672\">=<\/span> ElasticsearchClient.<span style=\"color:#a6e22e\">of<\/span>(c <span style=\"color:#f92672\">-&gt;<\/span> c\n<\/span><\/span><span style=\"display:flex;\"><span>    .<span style=\"color:#a6e22e\">host<\/span>(System.<span style=\"color:#a6e22e\">getenv<\/span>(<span style=\"color:#e6db74\">&#34;ES_URL&#34;<\/span>))\n<\/span><\/span><span style=\"display:flex;\"><span>    .<span style=\"color:#a6e22e\">apiKey<\/span>(System.<span style=\"color:#a6e22e\">getenv<\/span>(<span style=\"color:#e6db74\">&#34;ES_API_KEY&#34;<\/span>)))) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ use the esClient as you need<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>}<\/span><\/span><\/code><\/pre><\/div>\n<p>I&rsquo;m curious what you think about this. IMHO this is a great change:<\/p>\n<ul>\n<li>The <code>ElasticsearchClient<\/code> can finally be constructed in just a few lines, where each line is actually meaningful\u2014not just boilerplate string concatenation.<\/li>\n<li>All the underlying machinery uses default implementations, unless you explicitly provide your own (for valid reasons).<\/li>\n<li>Last but not least, it&rsquo;s also auto-closeable, so after the try block ends, the client is properly closed, resources are released, and your program exits cleanly\u2014no need for <code>System.exit()<\/code> (which we really shouldn\u2019t use anyway).<\/li>\n<\/ul>\n<h2 id=\"how-to-name-it\">How to name it?<\/h2>\n<p>As the old wisdom says, there are two big problems in Computer Science:<\/p>\n<ul>\n<li>naming<\/li>\n<li>cache invalidation<\/li>\n<li>off-by-one errors.<\/li>\n<\/ul>\n<p><figure class=\"image image right\">\n<img src=\"pattern-name-tweet-screenshot.png\" alt=\"We&#39;re looking for a name for this pattern -- where configuration is done with a lambda that transforms a configuration object.\" width=\"640\">\n<\/figure>\n\nTurns out, constructing closeable objects using factory methods with configuration passed via lambda expressions is gaining popularity. Personally, I find it neat and useful\u2014better than passing configuration via objects, implementing interfaces (with all those <code>default<\/code> methods), using subclasses, or even the classic builder pattern. However, as indicated in a tweet by Brian Goetz, we might not have a proper name for this particular pattern.<\/p>\n<p>So if you have a proposal, perhaps you could reply to <a href=\"https:\/\/x.com\/BrianGoetz\/status\/1912125351062364489\">Mr. Goetz\u2019s tweet<\/a>?<\/p>\n<h3 id=\"what-does-it-have-to-do-with-developer-advocacy\">What does it have to do with developer advocacy?<\/h3>\n<p>I think I should write a separate entry about being a developer advocate\u2014what it\u2019s like, what the pros and cons are, what we do and what we don\u2019t do (especially since I\u2019ve been asked this question on several occasions).<\/p>\n<p>In short, I&rsquo;d say: we don\u2019t sell, and we don\u2019t act as propaganda officers. What we do (among other things) is representing fellow developers from the wild world within the organisations we work for. We take the best there is to offer, and we present it using the best means we can. In other words, our job is not just to broadcast from the inside out, but also to act as a two-way relay: transmitting expectations, lessons learned, and so on, from the outside in\u2014even if that is frequently overlooked.<\/p>\n<p>In this very case, I was able to bring feedback &ldquo;from the community&rdquo; and express the need for changes internally. That\u2019s exactly why you should follow Sharat Chandler\u2019s advice to attend the Hallway Track at conferences (and annoy developer advocates\u2014they might be more effective than filing issues in public trackers ;-) )<\/p>\n<h3 id=\"devex\">DevEx!<\/h3>\n<p>Oftentimes this refers to Developer Experience, sometimes abbreviated as DevEx. You see, even when you create a high-performing piece of technology\u2014even a true gem of software engineering\u2014if people don\u2019t know how to use it, or if it makes them feel clumsy, your job isn\u2019t done. The best piece of technology is one that does all the above and doesn\u2019t require a PhD in reading manuals ;-)<\/p>\n<h2 id=\"conclusion\">Conclusion<\/h2>\n<p><figure class=\"image image left\">\n<img src=\"happy-30th-birthday-java.jpg\" alt=\"Happy 30th Birthday Java!\" width=\"320\">\n<\/figure>\n\nThat having been said, I\u2019m happy that my colleagues from the Dev Tools team made this great change, showing that getting started with Elasticsearch may now require only three or four lines. I\u2019m also happy that Java\u2019s ecosystem, despite turning 30, is still evolving\u2014accommodating new ideas in a huge ecosystem, and doing so without breaking backward compatibility.<\/p>\n<p>Java is still kicking!<\/p>\n<div class=\"footnotes\" role=\"doc-endnotes\">\n<hr>\n<ol>\n<li id=\"fn:1\">\n<p>A <em>microservice<\/em> is a <em>service<\/em> that can be completely rewritten by your team in max. 2 weeks; if the rewrite from scratch takes longer, it&rsquo;s not a <em>micro<\/em> service, just a <em>service<\/em>. Definition by me and my friends.&#160;<a href=\"#fnref:1\" class=\"footnote-backref\" role=\"doc-backlink\">&#x21a9;&#xfe0e;<\/a><\/p>\n<\/li>\n<\/ol>\n<\/div>\n"},{"title":"ES|QL FTW!","link":"https:\/\/softwaregarden.dev\/en\/talks\/esql-ftw\/","pubDate":"Thu, 10 Oct 2024 10:00:00 +0200","guid":"https:\/\/softwaregarden.dev\/en\/talks\/esql-ftw\/","description":"<p>NoSQL for years was associated with JSON. The thing is: if you&rsquo;re a hardcore backend Java developer, JSON, YAML, and other data formats might not feel native to you. Also, if you were ears-deep into debugging a query from Java code, sending the same request for visualization in Kibana using KQL wasn&rsquo;t trivial. Meet ES|QL: Elasticsearch&rsquo;s new query language, being at first glance a mixture of SQL and&hellip; Bash ;-) Works the same in Java and Kibana (and other programming languages too!) Additionally, by leveraging Project Valhalla and vector operations, ES|QL can achieve performance improvements over previous solutions. If you&rsquo;re eager to investigate the options of the ES|QL and how it makes your life easier (while also giving a feel of being a SQL DB), this talk is for you.<\/p>\n<p>So far I gave this talk at the Devoxx Belgium and few meetups too.<\/p>\n<div style=\"position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;\">\n      <iframe allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen\" loading=\"eager\" referrerpolicy=\"strict-origin-when-cross-origin\" src=\"https:\/\/www.youtube-nocookie.com\/embed\/5DOyc6l18fU?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0\" style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;\" title=\"YouTube video\"><\/iframe>\n    <\/div>\n\n"},{"title":"Elasticsearch: certificates and passwords","link":"https:\/\/softwaregarden.dev\/en\/posts\/security\/elastic-certificates-and-authorization\/","pubDate":"Thu, 18 Jul 2024 09:00:00 +0200","guid":"https:\/\/softwaregarden.dev\/en\/posts\/security\/elastic-certificates-and-authorization\/","description":"<p>If I got a dollar every time I hear &ldquo;we had to disable security and authentication in Elasticsearch because otherwise it was unusable&rdquo;, I&rsquo;d be a bit richer by now ;-)<\/p>\n<p>Honestly, I don&rsquo;t quite get where the confusion comes from. It&rsquo;s 2024, yet some of us are still surprised by &ldquo;what do you mean: certificate and password???&rdquo;<\/p>\n<p>Let me explain security in Elasticsearch in a few simple paragraphs.<\/p>\n<figure class=\"image image right\">\n<img src=\"elastic-secure-connection.jpg\" alt=\"A gloomy programmer gazing at a secure, flexible tunnel\" width=\"550\">\n<\/figure>\n\n<p>I&rsquo;ll start by saying this isn&rsquo;t just about Elasticsearch, but anything that communicates over HTTPS. It could be an HTTP server, a database, or any other system.\nTo have HTTPS instead of HTTP, you need a certificate. Normally, when we secure communication with our HTTP server (to get the padlock in the address bar), we need to obtain a certificate. Such a certificate is issued by some organization and applies to a <code>specific.server.com<\/code>.<\/p>\n<p>But how do we know that the certificate is okay? The organization is certified by someone else, who in turn might be certified by another higher authority, creating a chain of trust up to the &ldquo;highest authority&rdquo;. The certificate of the highest authority is embedded in our browser or operating system, so we don&rsquo;t have to click &ldquo;yes, this certificate and the whole chain are fine&rdquo; every time we access a secure site.<\/p>\n<p>The problem arises when we have a certificate that is not signed by a &ldquo;higher authority&rdquo;, but by ourselves. Maybe we&rsquo;re running something locally for testing, without any <code>meaningful.address.com<\/code>, and we don&rsquo;t want to pay for a certificate, but we still want HTTPS to prevent eavesdropping. For testing in production-like conditions, we use a self-signed certificate and a chain (even if it&rsquo;s just one link) that nobody known to our operating system has signed.<\/p>\n<p>Elasticsearch generates such a chain by default from version 8, if no &ldquo;official&rdquo; certificate is provided.<\/p>\n<p>For example, when we start Elasticsearch using Docker (not using Docker Hub, mind you):<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-sh\" data-lang=\"sh\"><span style=\"display:flex;\"><span>docker run --name es -p 9200:9200 -p 9300:9300 -e <span style=\"color:#e6db74\">&#34;discovery.type=single-node&#34;<\/span> docker.elastic.co\/elasticsearch\/elasticsearch:8.14.2\n<\/span><\/span><\/code><\/pre><\/div><p>Elasticsearch will generate its own chain and save it at <code>\/usr\/share\/elasticsearch\/config\/certs\/http_ca.crt<\/code>.<\/p>\n<p>Now: since this chain is not approved by our OS, we must either say &ldquo;ignore it&rdquo; (not recommended), or tell our client software &ldquo;it&rsquo;s okay, I trust THIS chain&rdquo;. And you need to provide THIS chain, simple ;-)<\/p>\n<p>With <code>curl<\/code>, you can use <code>--cacert<\/code> for this purpose.<\/p>\n<p>So, something like this (if we want to run <code>curl<\/code> inside the container with Elasticsearch running) won&rsquo;t work (because we haven&rsquo;t trusted the chain):<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-sh\" data-lang=\"sh\"><span style=\"display:flex;\"><span>docker exec es curl https:\/\/localhost:9200\n<\/span><\/span><\/code><\/pre><\/div><p>To connect to Elasticsearch, we need to do this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-sh\" data-lang=\"sh\"><span style=\"display:flex;\"><span>docker exec es curl --cacert \/usr\/share\/elasticsearch\/config\/certs\/http_ca.crt https:\/\/localhost:9200\n<\/span><\/span><\/code><\/pre><\/div><p>At this point, someone might shout &ldquo;but it still doesn&rsquo;t work, and the chain is confirmed!!!!eleven&rdquo;<\/p>\n<p>Now what we have is a secure connection, meaning no one can eavesdrop on what is being sent and received (although they can still see where the connection is going, when, and roughly how much data is being transferred). To authenticate ourselves, we need to say &ldquo;mom, it&rsquo;s me, pass the sandwich&rdquo; (again, this isn&rsquo;t just about Elasticsearch but many other systems too).<\/p>\n<p>There are various ways to do this. For tests (automated), providing a username and password in Basic Auth should suffice, so we can set the password after starting the container:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-sh\" data-lang=\"sh\"><span style=\"display:flex;\"><span>docker exec -it es elasticsearch-reset-password -u elastic --interactive\n<\/span><\/span><\/code><\/pre><\/div><p>(I also recommend <code>docker exec -it es elasticsearch-reset-password -u elastic --help<\/code> for other modes.)<\/p>\n<p>Another option is to set the password in an environment variable when starting the container, for example:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-sh\" data-lang=\"sh\"><span style=\"display:flex;\"><span>docker run --name es -p 9200:9200 -p 9300:9300 -e <span style=\"color:#e6db74\">&#34;discovery.type=single-node&#34;<\/span> -e <span style=\"color:#e6db74\">&#34;ELASTIC_PASSWORD=changeme&#34;<\/span> docker.elastic.co\/elasticsearch\/elasticsearch:8.14.2\n<\/span><\/span><\/code><\/pre><\/div><p>Once we have both a secure connection and the password set, we can send a request to Elasticsearch like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-sh\" data-lang=\"sh\"><span style=\"display:flex;\"><span>docker exec es curl --cacert \/usr\/share\/elasticsearch\/config\/certs\/http_ca.crt --user elastic:changeme https:\/\/localhost:9200\n<\/span><\/span><\/code><\/pre><\/div><ul>\n<li>Okay, but how do I connect with something other than <code>curl<\/code>?<\/li>\n<li>That depends on what you&rsquo;re connecting with and what options it has.<\/li>\n<\/ul>\n<p>You can copy the chain and somehow approve it in your client:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-sh\" data-lang=\"sh\"><span style=\"display:flex;\"><span>docker cp es:\/usr\/share\/elasticsearch\/config\/certs\/http_ca.crt .\n<\/span><\/span><\/code><\/pre><\/div><p>You can create a fingerprint and approve the chain by the fingerprint, for example:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-sh\" data-lang=\"sh\"><span style=\"display:flex;\"><span>docker exec es openssl x509 -noout -fingerprint -sha256 -inform pem -in \/usr\/share\/elasticsearch\/config\/certs\/http_ca.crt\n<\/span><\/span><\/code><\/pre><\/div><p>Recap, as there two concepts here:<\/p>\n<ul>\n<li>one thing is SSL\/TLS\/HTTPS and secured connection to the (Elasticsearch) server<\/li>\n<li>another thing is passwords and API keys<\/li>\n<\/ul>\n<p>Two final notes:<\/p>\n<ol>\n<li>It&rsquo;s worth reading the documentation, e.g., on how to connect with the Java client: <a href=\"https:\/\/www.elastic.co\/guide\/en\/elasticsearch\/client\/java-api-client\/current\/connecting.html\">Connecting with Java client<\/a><\/li>\n<li>In production, instead of passwords, I recommend using API keys: <a href=\"https:\/\/www.elastic.co\/guide\/en\/elasticsearch\/reference\/current\/security-api-create-api-key.html\">Create API key<\/a><\/li>\n<li>It doesn&rsquo;t harm to take a look at <a href=\"https:\/\/www.elastic.co\/guide\/en\/elasticsearch\/reference\/current\/security-settings.html#http-tls-ssl-settings\">HTTP TLS\/SSL settings<\/a><\/li>\n<\/ol>\n<p>Thanks and happy searching! ;-)<\/p>"},{"title":"Hunting with Stream Gatherers","link":"https:\/\/softwaregarden.dev\/en\/talks\/hunting-with-java-gatherers\/","pubDate":"Fri, 12 Jul 2024 10:00:00 +0200","guid":"https:\/\/softwaregarden.dev\/en\/talks\/hunting-with-java-gatherers\/","description":"<p>Streams were a very nice addition to Java 8, based on lambdas. They allow streamlined data processing without side effects, taking us gently towards functional style. With newer additions to Java, like records and pattern matching, they shine even more in data-driven flows.\nHowever, they don&rsquo;t come without flaws.\nFor starters, the only available extension point was collectors: if your needs for gathering data weren&rsquo;t satisfied by the whole Collectors ZOO, you could always fall back to creating your own Collector. However, if map, filter or flatMap weren&rsquo;t enough, you couldn&rsquo;t add your own intermediate operation.\nSecondly, parallel streams were limited to ForkJoin pool, effectively rendering them unusable for scenarios involving any IO.\nSince Java 22, Stream Gatherers are our extension point for intermediate operations in streams.\nIf you&rsquo;d like to comprehend how they work, find nice use cases and hunt for more performance, this talk is for you.<\/p>\n<p>So far I gave this talk at the Devoxx Poland, Devoxx Belgium and some other conferences and meetups<\/p>\n<div style=\"position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;\">\n      <iframe allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen\" loading=\"eager\" referrerpolicy=\"strict-origin-when-cross-origin\" src=\"https:\/\/www.youtube-nocookie.com\/embed\/rvW8tu1n5x4?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0\" style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;\" title=\"YouTube video\"><\/iframe>\n    <\/div>\n\n"},{"title":"GenAI, vector \/ semantic \/ hybrid search, RRF, NLP, LLM, RAG, FUD, FOMO, and other buzzwords","link":"https:\/\/softwaregarden.dev\/en\/talks\/ai-buzzwords\/","pubDate":"Thu, 11 Jul 2024 10:00:00 +0200","guid":"https:\/\/softwaregarden.dev\/en\/talks\/ai-buzzwords\/","description":"<p>Here you are: a Java developer with some experience, and everyone around seems to be talking about LLM, NLP, RAG and other AI related stuff. From one end you&rsquo;re somewhat afraid of this, because JPA is nowhere among these acronyms, and they say AI might take your job next month. OTOH you&rsquo;re also tired, because every news, every social platform is bombarding you with all flavours of AI so much that you&rsquo;re scared to open your fridge (who knows, AI might be among groceries now?)<\/p>\n<p>Wouldn&rsquo;t it be great to have the buzzwords deciphered, so that you can reason about them without having a PhD in AI or data science first?<\/p>\n<p>Certainly! Please join me for this talk, fellow Java developer, to see how technologies you already know (like Elasticsearch), and some maths, can help you tackle all this with no big fear.<\/p>\n<p>This talk has been given live at Infoshare, JavaDays Lviv and Merge-IT. Will be given at bITconf and Java Developer Days. Waiting for videos&hellip;<\/p>\n"},{"title":"Making Your Testcontainers Experience Smoother","link":"https:\/\/softwaregarden.dev\/en\/talks\/making-testcontainers-experience-smoother\/","pubDate":"Wed, 10 Jul 2024 10:00:00 +0200","guid":"https:\/\/softwaregarden.dev\/en\/talks\/making-testcontainers-experience-smoother\/","description":"<p>Integration tests are nice. We all know that and love using them, don&rsquo;t we?\nIt&rsquo;s just using all those databases, message brokers and other things as real dependencies, only wrapped by Testcontainers, might result in a really heavy CI\/CD pipeline and developers&rsquo; attitude to never run them locally, because they&rsquo;re so slooooooooooow.\nWhat if I could show you a number of techniques, mindset changes and tricks to get your integration tests shortened from quarters to seconds? Would that be interesting for you, to benefit from the confidence integrations tests give you, before you&rsquo;re able to brew a fresh coffee?\nIt&rsquo;s really not about re-inventing the wheel, but using it the smart way.<\/p>\n<p>So far this talk was hosted by JCon Europe 2024.<\/p>\n<div style=\"position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;\">\n      <iframe allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen\" loading=\"eager\" referrerpolicy=\"strict-origin-when-cross-origin\" src=\"https:\/\/www.youtube-nocookie.com\/embed\/wE3PzOHBFxU?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0\" style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;\" title=\"YouTube video\"><\/iframe>\n    <\/div>\n\n"},{"title":"The best Java 22 feature: concurrent gathering","link":"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/gatherers\/concurrent\/","pubDate":"Mon, 18 Mar 2024 16:00:00 +0200","guid":"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/gatherers\/concurrent\/","description":"<p>Java 22 is about to be released tomorrow. There are many super nice things in this release. I suspect making Project Panama&rsquo;s native\/foreign calls will make many people&rsquo;s life easier, as well as ongoing changes to concurrency, string templates and finally being able to call something before <code>super<\/code>. However, there&rsquo;s one thing I guess is going to be my (almost) hidden hero of Java 22. Folks, I introduce to you <code>Gatherers.mapConcurrent<\/code>!<\/p>\n<h3 id=\"streams-are-unparallel-hero-of-java-8\">Streams are (un)parallel hero of Java 8<\/h3>\n<p>Java 8 was a big milestone in Java&rsquo;s revolution at its time. I remember the vibes, after relatively small release of Java 7, version 8 was a BIG ONE. Introduction of lambdas allowed Stream API to co-exist in Java 8 (without our eyes bleeding, that is).\nIMHO it pushed Java towards declarative and functional way of thinking of data processing: instead of loops with intermediate calls and wrapping up results in a single object, we could finally express the intent in more, well, functional way.<\/p>\n<p>Stream API had IMHO at least two bigger flaws at the time it was introduced, effectively preventing its usage in many critical path data processing scenarios.<\/p>\n<h4 id=\"extend-only-once\">Extend only once<\/h4>\n<p>In very simplified way stream&rsquo;s lifecycle could be summarised like this:<\/p>\n<ul>\n<li>creation of the stream<\/li>\n<li>a number of intermediate operations, like <code>filter<\/code>, <code>map<\/code>, or <code>flatMap<\/code> (or <code>peek<\/code>, but this was only for debugging, right? RIGHT???)<\/li>\n<li>a single call to collect the results.<\/li>\n<\/ul>\n<p>Let&rsquo;s start from the end: collectors. If you weren&rsquo;t happy with simple <code>joining<\/code>, <code>reduce<\/code> or such, you could go for even simpler <code>toList<\/code> (since Java 16 if I remember correctly), or <code>teeing<\/code> (since Java 12), if you needed to pass the streamed objects to two or more collectors. Or, if you had really fancy needs, you could unveil all dark powers you obtained in your SQL 101 class and compose collectors with <code>mapping<\/code>, <code>filtering<\/code>, <code>groupingBy<\/code>, <code>paritioningBy<\/code>, <code>collectingAndThen<\/code>, etc., etc.<\/p>\n<p>If that still wasn&rsquo;t enough, you could write your own collector here. And that&rsquo;s the first limitation: it was AFAICT the only extension point in the StreamAPI. If you needed something special, you either had to introduce weird intermediate data structures to handle that in intermediate operations (look for &ldquo;nice&rdquo; examples in <a href=\"https:\/\/openjdk.org\/jeps\/461\">JEP 461<\/a>), or you had to de-facto deffer that until collecting phase. Which was kind of odd, because that neglected the whole purpose of expressing the data processing steps using intermediate operations before collection step. Or you could do that in a loop, in good ol&rsquo; imperative style.<\/p>\n<h4 id=\"where-are-my-cores\">Where are my cores?<\/h4>\n<p>So you have 8 cores in your machine. And, let&rsquo;s say, 64 items in your stream. You figured out, that making your stream <code>.parallel()<\/code> might make the whole pipeline like 8 times faster in some cases. You even verified that in <code>jshell<\/code>, and yeap, 8 times faster, so quickly copy-n-paste in many places, and we can <code>git push --force<\/code> ;-)<\/p>\n<p>And then we all discover, that (almost) all the threads in parallel streams are from the same pool. And worse, that they are blocking on IO. (And here we skip the whole history of reactive stack and holy wars between reactive vs. virtual threads. I&rsquo;m not in a mood for a holy war today, sorry).<\/p>\n<p>For these reasons (and more) in the past we used to switch to reactive stack to have unblocked parallel processing. Or when we could deal with the parallelism in the collecting phase, we used <a href=\"https:\/\/github.com\/pivovarit\/parallel-collectors\">parallel-collectors<\/a> by Grzegorz Piwowarek &amp; Co. Or really devoted vanilla Java folks used CompletableFutures.<\/p>\n<h3 id=\"hunting-with-gatherers\">Hunting with Gatherers<\/h3>\n<p>Java 22 in JEP 461 has introduced another extension point to StreamAPI: Stream Gatherers. In short: if you&rsquo;re not happy with the intermediate stream operations that are already there, you can employ gatherer(s).<\/p>\n<p>Apart from being just an extension, they can also allow slicing, scanning, and so on. For example, in this code:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span>Stream.<span style=\"color:#a6e22e\">of<\/span>(<span style=\"color:#e6db74\">&#34;ene&#34;<\/span>, <span style=\"color:#e6db74\">&#34;due&#34;<\/span>, <span style=\"color:#e6db74\">&#34;rabe&#34;<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>    .<span style=\"color:#a6e22e\">gather<\/span>(Gatherers.<span style=\"color:#a6e22e\">windowSliding<\/span>(2))\n<\/span><\/span><span style=\"display:flex;\"><span>    .<span style=\"color:#a6e22e\">filter<\/span>(l <span style=\"color:#f92672\">-&gt;<\/span> Math.<span style=\"color:#a6e22e\">abs<\/span>(l.<span style=\"color:#a6e22e\">getFirst<\/span>().<span style=\"color:#a6e22e\">length<\/span>() <span style=\"color:#f92672\">-<\/span> l.<span style=\"color:#a6e22e\">getLast<\/span>().<span style=\"color:#a6e22e\">length<\/span>()) <span style=\"color:#f92672\">&gt;<\/span> 1)\n<\/span><\/span><span style=\"display:flex;\"><span>    .<span style=\"color:#a6e22e\">forEach<\/span>(System.<span style=\"color:#a6e22e\">out<\/span>::println);<\/span><\/span><\/code><\/pre><\/div>\n<figure class=\"image image right\">\n<img src=\"data-hunter.jpeg\" alt=\"data hunter\" width=\"640\">\n<\/figure>\n\n<p>we gather words like <code>&quot;ene&quot;, &quot;due&quot;, &quot;rabe&quot;<\/code> into windows (which are lists, hence <code>getFirst()<\/code> and <code>getLast()<\/code>): <code>[&quot;ene&quot;, &quot;due&quot;]<\/code> and <code>[&quot;due&quot;, &quot;rabe&quot;]<\/code>. And then we can check if subsequent words differ in length by more than one character. (If they did, we&rsquo;d see them printed).<\/p>\n<p>Very nice and very needed extension point, and very nice predefined gatherers. One of them starts really shining when you extract it from the JEP.<\/p>\n<h3 id=\"gatherersmapconcurrent-gets-from-me-the-method-of-java-22-award\">Gatherers.mapConcurrent gets from me &ldquo;the method of Java 22&rdquo; award<\/h3>\n<p>I very much like how Tomek Nurkiewicz opened his <a href=\"https:\/\/nurkiewicz.com\/2019\/03\/mapmerge-one-method-to-rule-them-all.html\">post about <code>Map.merge()<\/code><\/a>. For me, this entry (after long intro) is about <a href=\"https:\/\/cr.openjdk.org\/~vklang\/gatherers\/api\/java.base\/java\/util\/stream\/Gatherers.html#mapConcurrent(int,java.util.function.Function)\"><code>Gatherers.mapConcurrent()<\/code><\/a>.<\/p>\n<p>In JEP 461 it&rsquo;s mentioned only once, here it goes:<\/p>\n<blockquote>\n<p>mapConcurrent is a stateful one-to-one gatherer which invokes a supplied function for each input element concurrently, up to a supplied limit<\/p>\n<\/blockquote>\n<p>And that&rsquo;s it! That&rsquo;s really it!<\/p>\n<p>What it doesn&rsquo;t mention in plain English, is that it&rsquo;s using virtual threads under the hood. So what&rsquo;s the big deal, you may ask. Well, let me show you what I think is missing in this JEP ;-)<\/p>\n<h3 id=\"enriching-data\">Enriching data<\/h3>\n<p>Let&rsquo;s say you receive some events. In this example we&rsquo;re going to receive 100 integers, just to Keep Things Simple\u2122. And for each event we need to call an external service, which will return us enriched event. Over network, mind you! And to Keep Things Simple\u2122 again, let&rsquo;s assume enriching each event takes one second.<\/p>\n<p>Question: how long will this code execute?<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">var<\/span> evens <span style=\"color:#f92672\">=<\/span> IntStream.<span style=\"color:#a6e22e\">range<\/span>(0, 100).<span style=\"color:#a6e22e\">boxed<\/span>()\n<\/span><\/span><span style=\"display:flex;\"><span>    .<span style=\"color:#a6e22e\">parallel<\/span>().<span style=\"color:#a6e22e\">map<\/span>(ExternalService::enrichEvent)\n<\/span><\/span><span style=\"display:flex;\"><span>    .<span style=\"color:#a6e22e\">toArray<\/span>();<\/span><\/span><\/code><\/pre><\/div>\n<p>You&rsquo;re smart, so you&rsquo;ll respond: it depends. <br>\nIf you&rsquo;re super smart, you&rsquo;ll respond: it depends on many things, like: how many idle CPU cores do you have (with default config), if the network is running smoothly, and (most importantly perhaps) how many other parallel streams are running at the same time.<\/p>\n<p>Assuming that we have 16 cores which have absolutely nothing else to do, it will last 100 tasks \/ 1 second \/ 16 worker threads = ceiling(6.25 seconds), which is like 7 seconds: for the first second we enhance 16 events, then next 16 events, and so on, and in the last second we process remaining 4.<\/p>\n<p>But we&rsquo;re using very little CPU, we&rsquo;re just waiting for the data to come back over the wire. If only there was a simple way to do these intermediate mapping using virtual threads, which aren&rsquo;t blocked by IO <a href=\"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/loom\/misusing-virtual-threads\/\">if used properly<\/a>&hellip;<\/p>\n<p>And there is! It&rsquo;s <code>Gatherers.mapConcurrent()<\/code>!<\/p>\n<p>In the first parameter it (more or less) ask us how many virtual threads can we run. And since this is a very CPU-lightweight operation, let&rsquo;s say 100. In the second parameter it takes&hellip; a mapping function ;-)<\/p>\n<p>So we have:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">var<\/span> events <span style=\"color:#f92672\">=<\/span> IntStream.<span style=\"color:#a6e22e\">range<\/span>(0, 100).<span style=\"color:#a6e22e\">boxed<\/span>()\n<\/span><\/span><span style=\"display:flex;\"><span>    .<span style=\"color:#a6e22e\">gather<\/span>(Gatherers.<span style=\"color:#a6e22e\">mapConcurrent<\/span>(100, ExternalService::enrichEvent))\n<\/span><\/span><span style=\"display:flex;\"><span>    .<span style=\"color:#a6e22e\">toArray<\/span>();<\/span><\/span><\/code><\/pre><\/div>\n<p>Let&rsquo;s repeat the question: how long will it take this time?\nYes, you guessed it right: it depends on the network. But this time we have 100 concurrent virtual threads, and if things go smoothly, we have the enriched events right after 1 second. Yes, one second.<\/p>\n<h3 id=\"gatherers-not-only-for-gardeners\">Gatherers not only for Gardeners<\/h3>\n<p>As a self-proclaimed Software Gardener, I suspect Gatherers might be something for me. And who knows, maybe for you too?<\/p>\n<p>Finally, I see something, a simple method call, that (combined with underlying technology of virtual threads) is addressing the shortcomings of processing data with just StreamAPI. Super nice and simple paradigm, vanilla Java, nothing more. From tomorrow Java Streams are really parallel.<\/p>\n"},{"title":"Java 21 and 22. What's new and noteworthy??","link":"https:\/\/softwaregarden.dev\/en\/talks\/java-22-new-and-noteworthy\/","pubDate":"Thu, 22 Feb 2024 20:00:00 +0200","guid":"https:\/\/softwaregarden.dev\/en\/talks\/java-22-new-and-noteworthy\/","description":"<p>Let&rsquo;s talk about Java 21 and have a sneak-peek into Java 22, and things like:\nJava was supposed &ldquo;to be slow&rdquo;. However, Java turns out to evolve so fast, that next releases aren&rsquo;t just version bumps, but might significantly change the rules of the game. That&rsquo;s a good reason to check out what&rsquo;s new in Java.\nTo name a few changes:<\/p>\n<ul>\n<li>Virtual Threads (and some traps),<\/li>\n<li>Pattern Matching and Record Patterns,<\/li>\n<li>Structured Concurrency,<\/li>\n<li>String Templates,<\/li>\n<li>Stream Gatherers,<\/li>\n<li>changes around main() method,<\/li>\n<li>what&rsquo;s gone and what will be gone,<\/li>\n<li>and other things.\nIf you find them interesting, let&rsquo;s dive deep together into new interesting stuff!<\/li>\n<\/ul>\n<p>This talk has been given for Silesia JUG only, no recording.<\/p>\n"},{"title":"Shorter Java scripts thanks to JEP 445","link":"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/scripts\/shorter-scrips-jep-445\/","pubDate":"Sun, 22 Oct 2023 16:00:00 +0200","guid":"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/scripts\/shorter-scrips-jep-445\/","description":"<p>In the past I wrote two posts about <a href=\"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/scripts\/java-scripts\/\">Java sripts<\/a> and their portability using <a href=\"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/scripts\/more-on-shebang\/\">shebang<\/a>.<\/p>\n<p>As far as I can tell everything in these two installments is still valid, only now, in Java 21, thanks to <a href=\"https:\/\/openjdk.org\/jeps\/445\">JEP-445<\/a> things can be even simpler. In this post I&rsquo;ll try to describe fist the changes introduced by this JEP, then go deeper on how they relate to the &ldquo;scripts in Java&rdquo;.<\/p>\n<p>I&rsquo;m going to cover how you can simplify your <code>main<\/code> method, get rid of the class surrounding it, and even show you when it won&rsquo;t work.<\/p>\n<h3 id=\"is-main-really-bloated\">Is <code>main<\/code> really bloated?<\/h3>\n<p>I started programming in Java in 2003. And Java wasn&rsquo;t my first C-derived language I knew. Before Java I had learned Turbo Pascal and C++, so the concept of <code>int main()<\/code> as the entry point wasn&rsquo;t entirely new to me. On the other hand I was also quite efficient PHP 3 coder (because scholarship wasn&rsquo;t enough), so I was also exposed to the concept of <code>main<\/code>-less programming language. (Yes, I think PHP is a programming language and deserves respect when due.)<\/p>\n<p>In fact at that time Java was the very first language to hardly anyone, we already knew some languages with <code>main<\/code>. Sure, <code>String[] args<\/code> was some ceremony, but that was okay. What was somewhat more confusing, and on the &ldquo;trust me, you&rsquo;ll understand that later&rdquo; side of things, was the class surrounding the <code>main<\/code>. And so we went into <code>class Klass<\/code> to understand it later, unless we were already familiar with object-oriented C++.<\/p>\n<p>Thing is, this was 20 years ago, when Java was perceived somewhat as a new-kid-in-the-block. These days we have more and more newcomers to Java, who come from <code>main<\/code>-less languages or even don&rsquo;t have any experience at all. Therefore, I quite like what JEP-445 helped us to achieve, i.e. skip a lot of the ceremony, when you&rsquo;re only about a simple, single-file programme, because you&rsquo;re learning all those &ldquo;variables&rdquo; and &ldquo;loops&rdquo;, and maybe even &ldquo;methods&rdquo;.<\/p>\n<p>If you&rsquo;re okay with <code>--enable-preview<\/code> features, and you don&rsquo;t need arguments, instead of:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">PublicStaticVoidMainWithArguments<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#66d9ef\">static<\/span> <span style=\"color:#66d9ef\">void<\/span> <span style=\"color:#a6e22e\">main<\/span>(String<span style=\"color:#f92672\">[]<\/span> _ignored) {\n<\/span><\/span><span style=\"display:flex;\"><span>        System.<span style=\"color:#a6e22e\">out<\/span>.<span style=\"color:#a6e22e\">println<\/span>(<span style=\"color:#e6db74\">&#34;Good old public static main.&#34;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>}<\/span><\/span><\/code><\/pre><\/div>\n<p>You can simply go for:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">void<\/span> <span style=\"color:#a6e22e\">main<\/span>() {\n<\/span><\/span><span style=\"display:flex;\"><span>    System.<span style=\"color:#a6e22e\">out<\/span>.<span style=\"color:#a6e22e\">println<\/span>(<span style=\"color:#e6db74\">&#34;The new main.&#34;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>}<\/span><\/span><\/code><\/pre><\/div>\n<p>Now, thanks to JEP-445 we can:<\/p>\n<ul>\n<li>skip the class declaration entirely,<\/li>\n<li>skip the <code>String[] args<\/code> as well (unless you still need them, then you can still use them, of course),<\/li>\n<li>skip <code>static<\/code> from the <code>main<\/code> method, so it can be an instance method,<\/li>\n<li>in fact, you can also use any access modifier, including the default one (just like above), except <code>private<\/code>.<\/li>\n<\/ul>\n<h3 id=\"precedence-of-main-methods\">Precedence of <code>main<\/code> methods<\/h3>\n<p>&lsquo;Okay&rsquo; you may ask, &lsquo;in Java I may overload the methods. What happens if I have <code>public static void main(String args[])<\/code> and <code>void main()<\/code>?&rsquo;<\/p>\n<p>Well, don&rsquo;t worry. If the code compiles and you have two <code>main<\/code> metods, only one will be called and the precedence is strict.<\/p>\n<ul>\n<li>First the method having <code>String[] args<\/code> will have precedence over an <code>args<\/code>-less method.<\/li>\n<li>Then <code>static<\/code> is preferred over instance.<\/li>\n<li>Last, the more <code>public<\/code>, the higher it goes.<\/li>\n<\/ul>\n<p>BTW I&rsquo;d argue if having such a puzzle with more than one <code>main<\/code> method in your file (or class) is really sane approach. Don&rsquo;t do that to yourself and people around you. ;-)<\/p>\n<h3 id=\"is-this-the-class-less-approach\">Is this the class-less approach?<\/h3>\n<p>Not really. The class is still there. It&rsquo;s so-called unnamed class, generated for us automatically under the hood.<\/p>\n<p>You don&rsquo;t have to trust me, you can trust the code. Please try to put the following in a file that has a <code>.java<\/code> extension and run it:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">void<\/span> <span style=\"color:#a6e22e\">main<\/span>() {\n<\/span><\/span><span style=\"display:flex;\"><span>    System.<span style=\"color:#a6e22e\">out<\/span>.<span style=\"color:#a6e22e\">println<\/span>(<span style=\"color:#e6db74\">&#34;New instance main in unnamed class, without arg(s).&#34;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    System.<span style=\"color:#a6e22e\">out<\/span>.<span style=\"color:#a6e22e\">println<\/span>(<span style=\"color:#e6db74\">&#34;Is the class unnamed? &#34;<\/span> <span style=\"color:#f92672\">+<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">getClass<\/span>().<span style=\"color:#a6e22e\">isUnnamedClass<\/span>());\n<\/span><\/span><span style=\"display:flex;\"><span>    System.<span style=\"color:#a6e22e\">out<\/span>.<span style=\"color:#a6e22e\">println<\/span>(<span style=\"color:#e6db74\">&#34;The class name is &#34;<\/span> <span style=\"color:#f92672\">+<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">getClass<\/span>().<span style=\"color:#a6e22e\">getName<\/span>() <span style=\"color:#f92672\">+<\/span> <span style=\"color:#e6db74\">&#34;...?&#34;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    System.<span style=\"color:#a6e22e\">out<\/span>.<span style=\"color:#a6e22e\">println<\/span>(<span style=\"color:#e6db74\">&#34;And the modifiers are [&#34;<\/span> <span style=\"color:#f92672\">+<\/span> java.<span style=\"color:#a6e22e\">lang<\/span>.<span style=\"color:#a6e22e\">reflect<\/span>.<span style=\"color:#a6e22e\">Modifier<\/span>.<span style=\"color:#a6e22e\">toString<\/span>(<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">getClass<\/span>().<span style=\"color:#a6e22e\">getModifiers<\/span>())<span style=\"color:#f92672\">+<\/span><span style=\"color:#e6db74\">&#34;]&#34;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    System.<span style=\"color:#a6e22e\">out<\/span>.<span style=\"color:#a6e22e\">println<\/span>(<span style=\"color:#e6db74\">&#34;(The package name is [&#34;<\/span> <span style=\"color:#f92672\">+<\/span><span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">getClass<\/span>().<span style=\"color:#a6e22e\">getPackage<\/span>().<span style=\"color:#a6e22e\">getName<\/span>()<span style=\"color:#f92672\">+<\/span><span style=\"color:#e6db74\">&#34;])&#34;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>}<\/span><\/span><\/code><\/pre><\/div>\n<p>If you wonder how you can run this code (e.g. because your IDE doesn&rsquo;t show you the nice green &ldquo;play&rdquo; button), you can always run this as per JEP-330:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-text\" data-lang=\"text\"><span style=\"display:flex;\"><span>$ java --source 21 --enable-preview yourFileName.java<\/span><\/span><\/code><\/pre><\/div>\n<p>You shall see, that the class is <code>final<\/code>, it resides in the default (&ldquo;nameless&rdquo;) package, you can now check if it <code>isUnnamedClass()<\/code> and&hellip; it has a name!\nIts name is derived from the name of the file. The funny thing is, that as an &ldquo;implementation detail&rdquo;, the class actually has a name, derived from the name of the file&hellip;<\/p>\n<p>Therefore, if you had named your file like e.g. <code>your-file-name.java<\/code>, you will see an error. Again, you don&rsquo;t have to trust me, run and have some fun ;-)<\/p>\n<p>In case you can&rsquo;t, due to whatever reason, it looks more or less like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-text\" data-lang=\"text\"><span style=\"display:flex;\"><span>your-file-name.java:44: error: bad file name: your-file-name\n<\/span><\/span><span style=\"display:flex;\"><span>    void main() {\n<\/span><\/span><span style=\"display:flex;\"><span>         ^<\/span><\/span><\/code><\/pre><\/div>\n<p>So currently the name of the file can&rsquo;t be just <em>any<\/em> name, it still needs to be a valid class name if the file name ends with <code>.java<\/code>. (Or you have to wrap it into a non-public class.) I&rsquo;m not quite sure if this is very fortunate TBH, because there&rsquo;s a consequence.<\/p>\n<h3 id=\"consequence-no-class-less-scripts\">Consequence: no class-less scripts<\/h3>\n<p>After JEP-330 we were able to write &ldquo;Java scripts&rdquo; using <code>#!shebang<\/code>.<\/p>\n<p>So we might be tempted to put the <code>main<\/code> method showed above into e.g. <code>java.script<\/code> and just on top add a line like:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-bash\" data-lang=\"bash\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">#!\/usr\/bin\/env -S java --enable-preview --source 21<\/span><\/span><\/span><\/code><\/pre><\/div>\n<p>Only&hellip; it doesn&rsquo;t work. The file-name-to-class-name mechanism applies only if we run <code>java --source effectivelyAKlass.java<\/code>. If we&rsquo;re into shebang, it won&rsquo;t work. Again, because <code>bad file name<\/code> error. We need to wrap the &ldquo;simplified&rdquo; <code>main<\/code> into a class, so it looks e.g. like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-text\" data-lang=\"text\"><span style=\"display:flex;\"><span>#!\/usr\/bin\/env -S java --enable-preview --source 21\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>\/\/ In GNU\/Linux the -S can be used since env version 8.30\n<\/span><\/span><span style=\"display:flex;\"><span>\/\/ for other OSes and older env versions you may need to use absolute shebang\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>class OwningClass {\n<\/span><\/span><span style=\"display:flex;\"><span>     void main() {\n<\/span><\/span><span style=\"display:flex;\"><span>        System.out.println(&#34;This is Java Script! \ud83d\udc7f&#34;);\n<\/span><\/span><span style=\"display:flex;\"><span>        System.out.println(&#34;Hello from &#34;+ Runtime.version());\n<\/span><\/span><span style=\"display:flex;\"><span>        System.out.println(&#34;New instance main in unnamed class, without arg(s).&#34;);\n<\/span><\/span><span style=\"display:flex;\"><span>        System.out.println(&#34;Is the class unnamed? &#34; + this.getClass().isUnnamedClass());\n<\/span><\/span><span style=\"display:flex;\"><span>        System.out.println(&#34;The class name is &#34; + this.getClass().getName() + &#34;...?&#34;);\n<\/span><\/span><span style=\"display:flex;\"><span>        System.out.println(&#34;And the modifiers are [&#34; + java.lang.reflect.Modifier.toString(this.getClass().getModifiers())+&#34;]&#34;);\n<\/span><\/span><span style=\"display:flex;\"><span>        System.out.println(&#34;(The package name is [&#34; +this.getClass().getPackage().getName()+&#34;])&#34;);\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>}<\/span><\/span><\/code><\/pre><\/div>\n<p>And apparently we can&rsquo;t get rid of this OwningClass if we want things to work in the script&hellip;<\/p>\n<h3 id=\"do-i-like-this-aspect-of-jep-445\">Do I like this aspect of JEP-445?<\/h3>\n<p>Honestly, I&rsquo;m not so sure if I quite like this &ldquo;implementation detail&rdquo;, effectively forcing us to have proper names for <code>.java<\/code> files or still declaring <code>class Klass<\/code> in shebang scripts.<\/p>\n<p>I am of course well aware that this is an extreme rare case, corner of a corner, useful mostly for the connoisseurs of the recruitment interviews (when inverting binary trees isn&rsquo;t enough). And it might well be that I&rsquo;m missing some serious arguments making this approach the best one&hellip;<\/p>\n<p>Still, maybe this &ldquo;implementation detail&rdquo; is too strict? Maybe the automatically generated class could have an empty name &quot;&quot; just like the default package, if this doesn&rsquo;t require changing the JVM too much? And if this would be too much of a breaking change, then maybe at least it could have a totally random name? Or maybe asking for the name of an unnamed class should throw an exception, just like <code>addFirst(...)<\/code> on unmodifiable collection? (Although I&rsquo;m really not sure if it would be a good approach.)<\/p>\n<p>I&rsquo;m just slightly afraid that this implementation detail not only might be too constraining, but some people might abuse it, even if the documentation says not to use the name of the UnnamedClass. (Does <code>sun.misc.Unsafe<\/code> ring a bell? ;-))<\/p>\n<p>The future will show.<\/p>\n<h3 id=\"and-its-much-better-anyway\">And it&rsquo;s much better anyway<\/h3>\n<figure class=\"image image right\">\n<img src=\"old-book.png\" alt=\"Old script\" width=\"440\">\n<\/figure>\n\n<p>Sure, if we want to write a &ldquo;decent Java script,&rdquo; we still need to use a class or have the right file name, but it&rsquo;s still better. At least it&rsquo;s much easier to start an adventure with Java now.<\/p>\n<p>I don&rsquo;t have any particularly big illusions that such scripts will be popular in production in the era of native images. But they should be just right for learning, because you don&rsquo;t have to understand everything right away (or take it on faith) and struggle with <code>javac<\/code> and <code>java<\/code>. <br>\nAnd this is not the last word in Java scripts, as there is a proposal for another <a href=\"https:\/\/openjdk.org\/jeps\/458\">JEP-458<\/a>!<\/p>\n"},{"title":"The Curious Case of JEP 443 got solved","link":"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/curious-case-of-jep443-solved\/","pubDate":"Wed, 18 Oct 2023 20:00:00 +0100","guid":"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/curious-case-of-jep443-solved\/","description":"<p>As I wrote in my <a href=\"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/curious-case-of-jep443\/\">previous post<\/a> I had issues running code using JEP 443 using tools like Maven, Gradle or IntelliJ IDEA. Thanks to the one and only <a href=\"https:\/\/twitter.com\/tagir_valeev\">Tagir Valeev<\/a> the solution is quite simple.<\/p>\n<h1 id=\"upgrade-to-jdk-2101\">Upgrade to JDK 21.0.1.<\/h1>\n<p>And that&rsquo;s it ;-)<\/p>\n<p>No need to touch anything else.\nIf you fancy more explanation, please <a href=\"https:\/\/x.com\/tagir_valeev\/status\/1714598179981656095?s=20\">follow on this Twitter thread<\/a>.<\/p>\n<p>And we shall all remember that upgrading is a good thing, because we&rsquo;re not going to stay on Java 8 forever, right? ;-)<\/p>\n<figure class=\"image image center\">\n<img src=\"sdkman-21.0.1.png\" alt=\"keep upgrading\" width=\"450\">\n<\/figure>\n\n"},{"title":"The Curious Case of JEP 443","link":"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/curious-case-of-jep443\/","pubDate":"Thu, 21 Sep 2023 10:00:00 +0100","guid":"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/curious-case-of-jep443\/","description":"<h3 id=\"update\">Update<\/h3>\n<p>The issue has been solved, please go to <a href=\"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/curious-case-of-jep443-solved\/\">the post with solution<\/a>.<\/p>\n<p><em>Note: I&rsquo;m leaving the original post below in case someone bumps to a similar issue in the future. Sometimes it&rsquo;s easier to search using the problem ;-)<\/em><\/p>\n<p>While preparing my <a href=\"https:\/\/softwaregarden.dev\/en\/talks\/java-21-new-and-noteworthy\/\">Deep Dive talk on Java 21<\/a> for friendly Java User Groups, I&rsquo;ve noticed a curious case of <a href=\"https:\/\/openjdk.org\/jeps\/443\">JEP 443: Unnamed Patterns and Variables (Preview)<\/a>. I&rsquo;ve managed to create a reproducer, so I&rsquo;d like to share the findings here.<\/p>\n<p>I assembled a simple demo of the JEP. It&rsquo;s obviously very nice and for sure it will improve Java&rsquo;s abilities to shine in data-first coding scenarios.<\/p>\n<p>However, this JEP is not only about <code>switch<\/code> and <code>if<\/code>s, it&rsquo;s also about lambdas, <code>catch<\/code> blocks and so on. Let&rsquo;s take a look at the following code to show you what I mean&hellip;<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1<\/span><span>String s <span style=\"color:#f92672\">=<\/span> <span style=\"color:#e6db74\">&#34;abc&#34;<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">2<\/span><span><span style=\"color:#66d9ef\">try<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">3<\/span><span>    <span style=\"color:#66d9ef\">int<\/span> i <span style=\"color:#f92672\">=<\/span> Integer.<span style=\"color:#a6e22e\">parseInt<\/span>(s);\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">4<\/span><span>    System.<span style=\"color:#a6e22e\">out<\/span>.<span style=\"color:#a6e22e\">println<\/span>(<span style=\"color:#e6db74\">&#34;Parsed &#34;<\/span> <span style=\"color:#f92672\">+<\/span> i);\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">5<\/span><span>} <span style=\"color:#66d9ef\">catch<\/span> (NumberFormatException _ignored) {\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">6<\/span><span>    System.<span style=\"color:#a6e22e\">out<\/span>.<span style=\"color:#a6e22e\">println<\/span>(<span style=\"color:#e6db74\">&#34;Bad number: &#34;<\/span> <span style=\"color:#f92672\">+<\/span> s);\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">7<\/span><span>}<\/span><\/span><\/code><\/pre><\/div>\n<p>As we can see, in line 5 we&rsquo;re trying to clearly say that we don&rsquo;t care about the actual exception we received. We only care about its type. But as we all know, even naming things seriously won&rsquo;t stop others from (mis)using it (I&rsquo;m looking at you, <code>sun.misc.Unsafe<\/code> fanbois!)<\/p>\n<p>Therefore, we decide to play it safe and put JEP 443 into action, and write <code>catch (NumberFormatException _)<\/code>. This way the compiler will ensure nobody will call <code>_ignored.printStackTrace();<\/code> or something&hellip; And the code looks like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1<\/span><span>String s <span style=\"color:#f92672\">=<\/span> <span style=\"color:#e6db74\">&#34;abc&#34;<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">2<\/span><span><span style=\"color:#66d9ef\">try<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">3<\/span><span>    <span style=\"color:#66d9ef\">int<\/span> i <span style=\"color:#f92672\">=<\/span> Integer.<span style=\"color:#a6e22e\">parseInt<\/span>(s);\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">4<\/span><span>    System.<span style=\"color:#a6e22e\">out<\/span>.<span style=\"color:#a6e22e\">println<\/span>(<span style=\"color:#e6db74\">&#34;Parsed &#34;<\/span> <span style=\"color:#f92672\">+<\/span> i);\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">5<\/span><span>} <span style=\"color:#66d9ef\">catch<\/span> (NumberFormatException _) {\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">6<\/span><span>    System.<span style=\"color:#a6e22e\">out<\/span>.<span style=\"color:#a6e22e\">println<\/span>(<span style=\"color:#e6db74\">&#34;Bad number: &#34;<\/span> <span style=\"color:#f92672\">+<\/span> s);\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">7<\/span><span>}<\/span><\/span><\/code><\/pre><\/div>\n<p>So I prepared this code, hit <code>Run<\/code> in the IDE, and&hellip; it didn&rsquo;t work the way I expected. I was expecting, obviously:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-text\" data-lang=\"text\"><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1<\/span><span>Bad number: abc<\/span><\/span><\/code><\/pre><\/div>\n<p>And what I got, was<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-text\" data-lang=\"text\"><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1<\/span><span>Error: LinkageError occurred while loading main class [class.name.here]\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">2<\/span><span>java.lang.ClassFormatError: Illegal field name &#34;&#34; in class [class\/name\/here]<\/span><\/span><\/code><\/pre><\/div>\n<p>Excuse me?<\/p>\n<figure class=\"image image center\">\n<img src=\"sxv-wtf.gif\" alt=\"curious case of a button\" width=\"450\">\n<\/figure>\n\n<p>Lucky me, my very first IDE when I started learning Java in 2003 was <code>notepad.exe<\/code>, so I basically run:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-shell\" data-lang=\"shell\"><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1<\/span><span>java --enable-preview --source <span style=\"color:#ae81ff\">21<\/span> .\/src\/main\/java\/all\/packages\/of\/JEP443Demo.java<\/span><\/span><\/code><\/pre><\/div>\n<p>&hellip; and this works as expected! I saw:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-text\" data-lang=\"text\"><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1<\/span><span>Bad number: abc<\/span><\/span><\/code><\/pre><\/div>\n<p>(along with a warning about preview features, of course.)<\/p>\n<p>Also in jshell it works like a charm:<\/p>\n<figure class=\"image image center\">\n<img src=\"jshell.png\" alt=\"jshell\" width=\"970\">\n<\/figure>\n\n<p>So apparently it seems that JEP 443 doesn&rsquo;t like to work in this case with&hellip; Maven and Gradle. I still don&rsquo;t know what&rsquo;s the actual cause and what tool to blame.<\/p>\n<p>Whenever I try <code>MAVEN_OPTS=&quot;--enable-preview&quot; .\/mvnw clean compile exec:java<\/code> or <code>.\/gradlew clean compileJava run<\/code> in <a href=\"https:\/\/github.com\/pioorg\/jep443demo\">my tiny repro project<\/a>, it always ends with the error mentioned above.<\/p>\n<p>Creating the jar with <code>.\/mvnw package<\/code> or <code>.\/gradlew assemble<\/code> works, the build finishes successfully (as in &ldquo;no errors reported&rdquo;).<br>\nAnd then trying to use it with <code>java --enable-preview -jar .\/path\/to\/artifact.jar<\/code> ends up with the same error.<\/p>\n<p>Even when I get rid of build tools like Maven or Gradle, and just rely on IntelliJ IDEA, the result is still the same: <code>java.lang.ClassFormatError: Illegal field name &quot;&quot; in class ...<\/code>.<\/p>\n<p>Manual execution of <code>javac<\/code> and <code>java<\/code> works without any issues, but any kind of automation doesn&rsquo;t work.<\/p>\n<p>I&rsquo;m puzzled&hellip;<\/p>\n<p>[To be continued.]<\/p>\n"},{"title":"Butcher Virtual Threads like a pro!","link":"https:\/\/softwaregarden.dev\/en\/talks\/butcher-virtual-threads-like-a-pro\/","pubDate":"Wed, 20 Sep 2023 11:00:00 +0200","guid":"https:\/\/softwaregarden.dev\/en\/talks\/butcher-virtual-threads-like-a-pro\/","description":"<p>Java\u2122 21 is real now. And so are virtual threads.\nEveryone got excited about them, yet you prefer to keep your Java 8 job forever, and you already have a nice plan to &ldquo;accidentally&rdquo; derail the migration to 21 by using virtual threads in a very, very unfortunate way. What a pity&hellip;<\/p>\n<p>So you decided to come for this talk to look for some inspiration ;-)<\/p>\n<p>Okay, please join us to learn how NOT to use virtual threads, and see the potential performance pitfalls of using them the wrong way.<\/p>\n<p>This talk has been given at JFall Netherlands, jPrime Bulgaria, Devoxx France, Devoxx Greece, GeeCON Poland.<\/p>\n<div style=\"position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;\">\n      <iframe allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen\" loading=\"eager\" referrerpolicy=\"strict-origin-when-cross-origin\" src=\"https:\/\/www.youtube-nocookie.com\/embed\/DVTx82--cVc?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0\" style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;\" title=\"YouTube video\"><\/iframe>\n    <\/div>\n\n"},{"title":"Testcontainers: needed, simple, powerful","link":"https:\/\/softwaregarden.dev\/en\/talks\/testcontainers-needed-simple-powerful\/","pubDate":"Wed, 20 Sep 2023 10:00:00 +0200","guid":"https:\/\/softwaregarden.dev\/en\/talks\/testcontainers-needed-simple-powerful\/","description":"<p>Spoiler alert: this is a &ldquo;from zero to hero&rdquo; session. Assuming you&rsquo;re familiar with programming (hopefully in Java), after this session you should be able to explain why Testcontainers are needed, simple and powerful \ud83d\ude09<\/p>\n<p>The pyramids in Egypt were built in ancient times. We still admire them today, appreciating the craftsmanship and hard work of their builders. However, do we build houses from giant stone blocks today? Not likely, current times bring other needs and offer other technologies.<\/p>\n<p>Pyramids of testing were also built some time ago. We admire legacy projects with a rich set of tests, but do we create projects today the same way we did 10-15-20 years ago? If not, why do we still want to test them the same way?<\/p>\n<p>Maybe the shape of today\u2019s projects&rsquo; tests should no longer resemble a pyramid? Our needs are different, and the possibilities, thanks to the Testcontainers, have also advanced a lot.<\/p>\n<p>If you have a feeling that integration testing can bring a lot to your project, but somehow you haven\u2019t had the chance to get acquainted with Testcontainers so far, or you\u2019re afraid that it\u2019s just &ldquo;magic for top developers&rdquo;, this lecture is for you.<\/p>\n<p>First, we&rsquo;ll see why integration tests are mandatory for any modern system and what benefits they give your team and your product.<\/p>\n<p>Next, we&rsquo;ll see why Testcontainers is a perfect tool for this job: we&rsquo;ll grasp some key concepts, debunk myths, to finish with more sophisticated scenarios and optimisation techniques.<\/p>\n<p>So far this talk was hosted by Devoxx Belgium 2023.<\/p>\n<div style=\"position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;\">\n      <iframe allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen\" loading=\"eager\" referrerpolicy=\"strict-origin-when-cross-origin\" src=\"https:\/\/www.youtube-nocookie.com\/embed\/bali16KUnOI?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0\" style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;\" title=\"YouTube video\"><\/iframe>\n    <\/div>\n\n"},{"title":"Java 21. What's new and noteworthy??","link":"https:\/\/softwaregarden.dev\/en\/talks\/java-21-new-and-noteworthy\/","pubDate":"Tue, 19 Sep 2023 20:00:00 +0200","guid":"https:\/\/softwaregarden.dev\/en\/talks\/java-21-new-and-noteworthy\/","description":"<p>Hey, there are two major Java versions released every year! We don\u2019t have to wait 3 years or so for new features anymore. Isn\u2019t that cool? \ud83d\ude09<\/p>\n<p>Java was supposed &ldquo;to be slow&rdquo;. However, Java turns out to evolve so fast, that next releases aren&rsquo;t just version bumps, but might significantly change the rules of the game. That&rsquo;s a good reason to check out what&rsquo;s new in Java.<\/p>\n<p>To name a few changes:<\/p>\n<ul>\n<li>Virtual Threads,<\/li>\n<li>Pattern Matching for switch,<\/li>\n<li>Record Patterns,<\/li>\n<li>Structured Concurrency,<\/li>\n<li>String Templates,<\/li>\n<li>what&rsquo;s gone and what will be gone,<\/li>\n<li>and other stuff.<\/li>\n<\/ul>\n<p>If you find them interesting, let\u2019s dive deep together into new interesting stuff.<\/p>\n<p>So far this talk has been given (in a not-so-deep-deep-dive format) at Warszawa JUG and Wroclaw JUG.<\/p>\n<div style=\"position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;\">\n      <iframe allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen\" loading=\"eager\" referrerpolicy=\"strict-origin-when-cross-origin\" src=\"https:\/\/www.youtube-nocookie.com\/embed\/Om8dIt3cJIU?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0\" style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;\" title=\"YouTube video\"><\/iframe>\n    <\/div>\n\n"},{"title":"Don't look at virtual threads, or else...!","link":"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/loom\/dont-look-at-virtual-threads\/","pubDate":"Sat, 19 Aug 2023 10:00:00 +0100","guid":"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/loom\/dont-look-at-virtual-threads\/","description":"<p>Let me start this entry with a dad joke.<\/p>\n<figure class=\"image image right\">\n<img src=\"featured.jpg\" alt=\"Simplified atom model\" width=\"450\">\n<\/figure>\n\n<blockquote>\n<p>An electron rides a motorcycle. Suddenly, a police officer stops the electron and says:<\/p>\n<p>&lsquo;I had to stop you, because you were speeding, driving exactly 178 and half kilometres per hour.&rsquo;<\/p>\n<p>&lsquo;Well, THANK YOU VERY MUCH, officer!&rsquo; the electron says, &lsquo;Now I have absolutely no idea where I am!!!&rsquo;<\/p>\n<\/blockquote>\n<p>Some dad jokes are terrible, and don&rsquo;t worry if you don&rsquo;t get this one. It boils down to the <a href=\"https:\/\/en.wikipedia.org\/wiki\/Uncertainty_principle\">uncertainty principle<\/a>. In extremely oversimplified version: some things in the universe can&rsquo;t be observed in all their aspects. If you have an apple, you can measure it&rsquo;s mass, volume, size, (and if falls on your head) velocity, all at the same time. Without affecting the apple itself. <br>\nHowever, if you&rsquo;re interested in electrons, the more accurately you know its speed, the less you know its location, and vice versa, hence <a href=\"https:\/\/en.wikipedia.org\/wiki\/Atomic_orbital\">atomic orbital<\/a>. (Gosh, will atomic things stop chasing me? \ud83d\ude05)<\/p>\n<h3 id=\"taking-a-step-back\">Taking a step back<\/h3>\n<p>Before we go for the virtual threads (because that&rsquo;s what lured you here in the first place), let&rsquo;s take a step back and discuss what we already know, when it comes to Java.<\/p>\n<p>What you might already know is that <a href=\"https:\/\/docs.oracle.com\/en\/java\/javase\/17\/docs\/api\/java.base\/java\/util\/stream\/BaseStream.html#parallel()\"><code>Stream.parallel()<\/code><\/a> is discouraged in many situations and <a href=\"https:\/\/docs.oracle.com\/en\/java\/javase\/17\/docs\/api\/java.base\/java\/util\/concurrent\/CompletableFuture.html\"><code>CompletableFuture<\/code><\/a> is usually the preferred solution, if you need to squeeze a lot of juice from all the CPU cores you have. It&rsquo;s because there&rsquo;s no way to provide your own thread pool to <code>parallel()<\/code>, hence you&rsquo;re limited to the <a href=\"https:\/\/docs.oracle.com\/en\/java\/javase\/17\/docs\/api\/java.base\/java\/util\/concurrent\/ForkJoinPool.html#commonPool()\">common pool<\/a>.<\/p>\n<p>An example of this behaviour might look like this. First, we have a method which handles a task (and the task itself is computation heavy):<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#66d9ef\">static<\/span> <span style=\"color:#66d9ef\">void<\/span> <span style=\"color:#a6e22e\">handleTask<\/span>(<span style=\"color:#66d9ef\">int<\/span> id) {\n<\/span><\/span><span style=\"display:flex;\"><span>    startedTasks.<span style=\"color:#a6e22e\">incrementAndGet<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>    hardWork(5_000);\n<\/span><\/span><span style=\"display:flex;\"><span>    logger.<span style=\"color:#a6e22e\">info<\/span>(() <span style=\"color:#f92672\">-&gt;<\/span> <span style=\"color:#e6db74\">&#34;FINISHED %3d %s&#34;<\/span>.<span style=\"color:#a6e22e\">formatted<\/span>(id, Thread.<span style=\"color:#a6e22e\">currentThread<\/span>()));\n<\/span><\/span><span style=\"display:flex;\"><span>    finishedTasks.<span style=\"color:#a6e22e\">incrementAndGet<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>}<\/span><\/span><\/code><\/pre><\/div>\n<p>The actual heavy-lifting takes place only in <code>hardWork<\/code>, obviously. And, as you could guess, it will take more or less five seconds. The rest is here just to allow us easily run our experiment (with vanilla Java and no 3rd party tools).<\/p>\n<p>And it&rsquo;s declared like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">static<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    System.<span style=\"color:#a6e22e\">setProperty<\/span>(<span style=\"color:#e6db74\">&#34;java.util.logging.SimpleFormatter.format&#34;<\/span>, <span style=\"color:#e6db74\">&#34;[%1$tF %1$tT %1$tZ] [%4$-7s] %5$s %n&#34;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">static<\/span> AtomicInteger startedTasks <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> AtomicInteger(0);\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">static<\/span> AtomicInteger finishedTasks <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> AtomicInteger(0);<\/span><\/span><\/code><\/pre><\/div>\n<p>Let&rsquo;s say we have:<\/p>\n<ul>\n<li>six seconds to complete as many tasks as we possibly can<\/li>\n<li><code>OpenJDK Runtime Environment (build 21-ea+34-2500)<\/code><\/li>\n<li>16 CPU cores<\/li>\n<\/ul>\n<p>And we&rsquo;re using <code>Stream.parallel()<\/code>, because reasons. The first approach is like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span>Thread.<span style=\"color:#a6e22e\">ofPlatform<\/span>().<span style=\"color:#a6e22e\">daemon<\/span>(<span style=\"color:#66d9ef\">true<\/span>).<span style=\"color:#a6e22e\">name<\/span>(<span style=\"color:#e6db74\">&#34;stream-1&#34;<\/span>).<span style=\"color:#a6e22e\">start<\/span>(() <span style=\"color:#f92672\">-&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    System.<span style=\"color:#a6e22e\">out<\/span>.<span style=\"color:#a6e22e\">println<\/span>(<span style=\"color:#e6db74\">&#34;Started &#34;<\/span> <span style=\"color:#f92672\">+<\/span> Thread.<span style=\"color:#a6e22e\">currentThread<\/span>() <span style=\"color:#f92672\">+<\/span> <span style=\"color:#e6db74\">&#34; to do some work&#34;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    IntStream.<span style=\"color:#a6e22e\">range<\/span>(0, 100).<span style=\"color:#a6e22e\">parallel<\/span>().<span style=\"color:#a6e22e\">forEach<\/span>(UncertaintyPrincipleOfVirtualThreads::handleTask);\n<\/span><\/span><span style=\"display:flex;\"><span>});\n<\/span><\/span><span style=\"display:flex;\"><span>Thread.<span style=\"color:#a6e22e\">sleep<\/span>(Duration.<span style=\"color:#a6e22e\">ofSeconds<\/span>(6));\n<\/span><\/span><span style=\"display:flex;\"><span>logger.<span style=\"color:#a6e22e\">info<\/span>(<span style=\"color:#e6db74\">&#34;Tasks: started [%d], finished [%d]&#34;<\/span>.<span style=\"color:#a6e22e\">formatted<\/span>(startedTasks.<span style=\"color:#a6e22e\">get<\/span>(), finishedTasks.<span style=\"color:#a6e22e\">get<\/span>()));<\/span><\/span><\/code><\/pre><\/div>\n<p>What results are you expecting? I&rsquo;m putting some white space here, so you can guess, before scrolling down.<\/p>\n<p><br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\nThe result logged at the end looks like this:<\/p>\n<p><div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-text\" data-lang=\"text\"><span style=\"display:flex;\"><span>Started Thread[#30,stream-1,5,main] to do some work\n<\/span><\/span><span style=\"display:flex;\"><span>[tasks finish here]\n<\/span><\/span><span style=\"display:flex;\"><span>Tasks: started [32], finished [16]<\/span><\/span><\/code><\/pre><\/div>\n<br>\nAnd it makes sense, right? If each tasks takes ~5s, and we can use our cores for max. 6s, and because the common pool grows to its maximum in this scenario, we are able to complete 16 tasks and start (without completing) another 16. (If you run this on your machine, the results may vary. I don&rsquo;t know how many CPU cores you have.)<\/p>\n<p>Now, if it takes one cow to deliver one calf in ~280 days, surely two cows will deliver two calves in ~280 days, right? ;-)\n<br>\nLet&rsquo;s see what this code can produce:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span>Thread.<span style=\"color:#a6e22e\">ofPlatform<\/span>().<span style=\"color:#a6e22e\">daemon<\/span>(<span style=\"color:#66d9ef\">true<\/span>).<span style=\"color:#a6e22e\">name<\/span>(<span style=\"color:#e6db74\">&#34;stream-1&#34;<\/span>).<span style=\"color:#a6e22e\">start<\/span>(() <span style=\"color:#f92672\">-&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    System.<span style=\"color:#a6e22e\">out<\/span>.<span style=\"color:#a6e22e\">println<\/span>(<span style=\"color:#e6db74\">&#34;Started &#34;<\/span> <span style=\"color:#f92672\">+<\/span> Thread.<span style=\"color:#a6e22e\">currentThread<\/span>() <span style=\"color:#f92672\">+<\/span> <span style=\"color:#e6db74\">&#34; to do some work&#34;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    IntStream.<span style=\"color:#a6e22e\">range<\/span>(0, 100).<span style=\"color:#a6e22e\">parallel<\/span>().<span style=\"color:#a6e22e\">forEach<\/span>(UncertaintyPrincipleOfVirtualThreads::handleTask);\n<\/span><\/span><span style=\"display:flex;\"><span>});\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>Thread.<span style=\"color:#a6e22e\">ofPlatform<\/span>().<span style=\"color:#a6e22e\">daemon<\/span>(<span style=\"color:#66d9ef\">true<\/span>).<span style=\"color:#a6e22e\">name<\/span>(<span style=\"color:#e6db74\">&#34;stream-2&#34;<\/span>).<span style=\"color:#a6e22e\">start<\/span>(() <span style=\"color:#f92672\">-&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    System.<span style=\"color:#a6e22e\">out<\/span>.<span style=\"color:#a6e22e\">println<\/span>(<span style=\"color:#e6db74\">&#34;Started &#34;<\/span> <span style=\"color:#f92672\">+<\/span> Thread.<span style=\"color:#a6e22e\">currentThread<\/span>() <span style=\"color:#f92672\">+<\/span> <span style=\"color:#e6db74\">&#34; to do some OTHER work&#34;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    IntStream.<span style=\"color:#a6e22e\">range<\/span>(100, 200).<span style=\"color:#a6e22e\">parallel<\/span>().<span style=\"color:#a6e22e\">forEach<\/span>(UncertaintyPrincipleOfVirtualThreads::handleTask);\n<\/span><\/span><span style=\"display:flex;\"><span>});<\/span><\/span><\/code><\/pre><\/div>\n<p>And we can see:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-text\" data-lang=\"text\"><span style=\"display:flex;\"><span>Started Thread[#30,stream-1,5,main] to do some work\n<\/span><\/span><span style=\"display:flex;\"><span>Started Thread[#31,stream-2,5,main] to do some OTHER work\n<\/span><\/span><span style=\"display:flex;\"><span>[tasks finish here]\n<\/span><\/span><span style=\"display:flex;\"><span>Tasks: started [34], finished [17]<\/span><\/span><\/code><\/pre><\/div>\n<p>Wait, WAT? We doubled the amount of parallel streams and instead of doubling the results, 2\u00a0\u00d7\u00a016 = 32, we get only one, just ONE more task finished?<\/p>\n<p>It&rsquo;s time to see how tasks actually finished in both cases.\nFor a single stream it may look like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-text\" data-lang=\"text\"><span style=\"display:flex;\"><span>FINISHED  65 Thread[#30,stream-1,5,main] \n<\/span><\/span><span style=\"display:flex;\"><span>FINISHED  48 Thread[#37,ForkJoinPool.commonPool-worker-7,5,main] \n<\/span><\/span><span style=\"display:flex;\"><span>FINISHED  32 Thread[#31,ForkJoinPool.commonPool-worker-1,5,main] \n<\/span><\/span><span style=\"display:flex;\"><span>FINISHED  42 Thread[#40,ForkJoinPool.commonPool-worker-10,5,main]\n<\/span><\/span><span style=\"display:flex;\"><span>FINISHED  40 Thread[#35,ForkJoinPool.commonPool-worker-5,5,main] \n<\/span><\/span><span style=\"display:flex;\"><span>FINISHED  90 Thread[#34,ForkJoinPool.commonPool-worker-4,5,main] \n<\/span><\/span><span style=\"display:flex;\"><span>FINISHED  28 Thread[#38,ForkJoinPool.commonPool-worker-8,5,main] \n<\/span><\/span><span style=\"display:flex;\"><span>FINISHED  38 Thread[#36,ForkJoinPool.commonPool-worker-6,5,main] \n<\/span><\/span><span style=\"display:flex;\"><span>FINISHED  15 Thread[#32,ForkJoinPool.commonPool-worker-2,5,main] \n<\/span><\/span><span style=\"display:flex;\"><span>FINISHED  22 Thread[#41,ForkJoinPool.commonPool-worker-11,5,main]\n<\/span><\/span><span style=\"display:flex;\"><span>FINISHED  43 Thread[#42,ForkJoinPool.commonPool-worker-12,5,main]\n<\/span><\/span><span style=\"display:flex;\"><span>FINISHED   7 Thread[#39,ForkJoinPool.commonPool-worker-9,5,main] \n<\/span><\/span><span style=\"display:flex;\"><span>FINISHED  47 Thread[#44,ForkJoinPool.commonPool-worker-14,5,main]\n<\/span><\/span><span style=\"display:flex;\"><span>FINISHED  57 Thread[#45,ForkJoinPool.commonPool-worker-15,5,main]\n<\/span><\/span><span style=\"display:flex;\"><span>FINISHED  44 Thread[#33,ForkJoinPool.commonPool-worker-3,5,main] \n<\/span><\/span><span style=\"display:flex;\"><span>FINISHED  82 Thread[#43,ForkJoinPool.commonPool-worker-13,5,main]<\/span><\/span><\/code><\/pre><\/div>\n<p>And when using two parallel streams, the result is as following:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-text\" data-lang=\"text\"><span style=\"display:flex;\"><span>FINISHED  97 Thread[#43,ForkJoinPool.commonPool-worker-12,5,main]\n<\/span><\/span><span style=\"display:flex;\"><span>FINISHED  65 Thread[#30,stream-1,5,main] \n<\/span><\/span><span style=\"display:flex;\"><span>FINISHED 115 Thread[#35,ForkJoinPool.commonPool-worker-4,5,main] \n<\/span><\/span><span style=\"display:flex;\"><span>FINISHED  82 Thread[#37,ForkJoinPool.commonPool-worker-6,5,main] \n<\/span><\/span><span style=\"display:flex;\"><span>FINISHED 190 Thread[#39,ForkJoinPool.commonPool-worker-8,5,main] \n<\/span><\/span><span style=\"display:flex;\"><span>FINISHED  78 Thread[#44,ForkJoinPool.commonPool-worker-13,5,main]\n<\/span><\/span><span style=\"display:flex;\"><span>FINISHED 144 Thread[#42,ForkJoinPool.commonPool-worker-11,5,main]\n<\/span><\/span><span style=\"display:flex;\"><span>FINISHED 107 Thread[#36,ForkJoinPool.commonPool-worker-5,5,main] \n<\/span><\/span><span style=\"display:flex;\"><span>FINISHED  15 Thread[#38,ForkJoinPool.commonPool-worker-7,5,main] \n<\/span><\/span><span style=\"display:flex;\"><span>FINISHED 132 Thread[#33,ForkJoinPool.commonPool-worker-2,5,main] \n<\/span><\/span><span style=\"display:flex;\"><span>FINISHED  32 Thread[#32,ForkJoinPool.commonPool-worker-1,5,main] \n<\/span><\/span><span style=\"display:flex;\"><span>FINISHED  85 Thread[#46,ForkJoinPool.commonPool-worker-15,5,main]\n<\/span><\/span><span style=\"display:flex;\"><span>FINISHED  90 Thread[#34,ForkJoinPool.commonPool-worker-3,5,main] \n<\/span><\/span><span style=\"display:flex;\"><span>FINISHED  57 Thread[#45,ForkJoinPool.commonPool-worker-14,5,main]\n<\/span><\/span><span style=\"display:flex;\"><span>FINISHED 122 Thread[#40,ForkJoinPool.commonPool-worker-9,5,main] \n<\/span><\/span><span style=\"display:flex;\"><span>FINISHED 165 Thread[#31,stream-2,5,main] \n<\/span><\/span><span style=\"display:flex;\"><span>FINISHED  44 Thread[#41,ForkJoinPool.commonPool-worker-10,5,main]<\/span><\/span><\/code><\/pre><\/div>\n<p>Despite running two parallel streams, we still have the same common worker pool. The one extra result came from <code>stream-2<\/code> thread. And we can see (because some finished tasks are &gt;= <code>100<\/code>, that the second stream is actually &ldquo;stealing&rdquo; workers) from the pool before there first stream can make them busy.<\/p>\n<p>If we go a little wild and separate both streams by <code>Thread.sleep(10)<\/code> (which is something we never do in prod code, right? RIGHT?!?), most likely we will see only one task &gt;= <code>100<\/code> processed. The overall number won&rsquo;t change, because the first stream makes all workers from the common pool busy, before the second can handle only one with its own <code>stream-2<\/code>.<\/p>\n<p>So the parallel streams can&rsquo;t grow linearly, no matter how many you&rsquo;ll toss.<\/p>\n<p>Wait a second, but there&rsquo;s this new thing in Java 21, even your boss heard about it, so they tell you:<\/p>\n<h2 id=\"virtual-threads-to-the-rescue-just-use-them\">Virtual threads to the rescue, just use them!<\/h2>\n<p>Sadly, you didn&rsquo;t have a chance to attend <a href=\"https:\/\/softwaregarden.dev\/en\/talks\/java-19-20-new-and-noteworthy\/\">this talk<\/a> from that funny Polish guy, so you all keep hoping, virtual threads are going to squeeze more juice from your CPU!<\/p>\n<p>And the team adds some feature flags, and hides behind them a new implementation, which is more or less the following:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">for<\/span> (<span style=\"color:#66d9ef\">int<\/span> i <span style=\"color:#f92672\">=<\/span> 0; i <span style=\"color:#f92672\">&lt;<\/span> 100; i<span style=\"color:#f92672\">++<\/span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">int<\/span> taskId <span style=\"color:#f92672\">=<\/span> i;\n<\/span><\/span><span style=\"display:flex;\"><span>    Thread.<span style=\"color:#a6e22e\">ofVirtual<\/span>().<span style=\"color:#a6e22e\">start<\/span>(() <span style=\"color:#f92672\">-&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>        handleTask(taskId);\n<\/span><\/span><span style=\"display:flex;\"><span>    });\n<\/span><\/span><span style=\"display:flex;\"><span>}<\/span><\/span><\/code><\/pre><\/div>\n<p>And now, because virtual threads are so lightweight, you hope to get at hand more results than 16! How many will we get this time?<\/p>\n<p><br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\nNo way. This can&rsquo;t be. Two sprints spent on the rewrite only to get:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-text\" data-lang=\"text\"><span style=\"display:flex;\"><span>Tasks: started [32], finished [16]<\/span><\/span><\/code><\/pre><\/div>\n<p>WTF? Okay, we spent two weeks on coding, because it was much easier to code than to read the manual for one hour. And <a href=\"https:\/\/openjdk.org\/jeps\/444\">the manual<\/a> says that under the hood the virtual threads are using ForkJoin pool! And it also says, that <em>by default it is equal to the number of available processors<\/em>!<\/p>\n<p>Not all is lost, it can also be tuned, but before tuning, we decide to take a closer look at the actual task handling implementation, to measure its progress, and maybe shave some time. After all, making it run faster than 5 seconds will make everything work faster, virtual threads or not. So we fall back to good ol&rsquo; <code>log(&quot;ONE&quot;)<\/code> and <code>log(&quot;TWO&quot;)<\/code> to trace the progress. We split the task into smaller steps and put some <del><code>trace<\/code><\/del> <code>fine<\/code> statements. So now our tasks are handled like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#66d9ef\">static<\/span> <span style=\"color:#66d9ef\">void<\/span> <span style=\"color:#a6e22e\">handleTask<\/span>(<span style=\"color:#66d9ef\">int<\/span> id) {\n<\/span><\/span><span style=\"display:flex;\"><span>    startedTasks.<span style=\"color:#a6e22e\">incrementAndGet<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>    report(id, <span style=\"color:#e6db74\">&#34;1&#34;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    hardWork(1_000);\n<\/span><\/span><span style=\"display:flex;\"><span>    report(id, <span style=\"color:#e6db74\">&#34;2&#34;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    hardWork(1_000);\n<\/span><\/span><span style=\"display:flex;\"><span>    report(id, <span style=\"color:#e6db74\">&#34;3&#34;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    hardWork(1_000);\n<\/span><\/span><span style=\"display:flex;\"><span>    report(id, <span style=\"color:#e6db74\">&#34;4&#34;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    hardWork(1_000);\n<\/span><\/span><span style=\"display:flex;\"><span>    report(id, <span style=\"color:#e6db74\">&#34;5&#34;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    hardWork(1_000);\n<\/span><\/span><span style=\"display:flex;\"><span>    logger.<span style=\"color:#a6e22e\">info<\/span>(() <span style=\"color:#f92672\">-&gt;<\/span> <span style=\"color:#e6db74\">&#34;FINISHED %3d %s&#34;<\/span>.<span style=\"color:#a6e22e\">formatted<\/span>(id, Thread.<span style=\"color:#a6e22e\">currentThread<\/span>()));\n<\/span><\/span><span style=\"display:flex;\"><span>    finishedTasks.<span style=\"color:#a6e22e\">incrementAndGet<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#66d9ef\">static<\/span> <span style=\"color:#66d9ef\">void<\/span> <span style=\"color:#a6e22e\">report<\/span>(<span style=\"color:#66d9ef\">int<\/span> taskId, String stage) {\n<\/span><\/span><span style=\"display:flex;\"><span>    logger.<span style=\"color:#a6e22e\">fine<\/span>(() <span style=\"color:#f92672\">-&gt;<\/span> <span style=\"color:#e6db74\">&#34;STEP %s %3d %s&#34;<\/span>.<span style=\"color:#a6e22e\">formatted<\/span>(stage, taskId, Thread.<span style=\"color:#a6e22e\">currentThread<\/span>()));\n<\/span><\/span><span style=\"display:flex;\"><span>}<\/span><\/span><\/code><\/pre><\/div>\n<p>And obviously, we can&rsquo;t forget to increase the logging precision, so in the static init block:\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span>logger.<span style=\"color:#a6e22e\">setLevel<\/span>(java.<span style=\"color:#a6e22e\">util<\/span>.<span style=\"color:#a6e22e\">logging<\/span>.<span style=\"color:#a6e22e\">Level<\/span>.<span style=\"color:#a6e22e\">FINE<\/span>);<\/span><\/span><\/code><\/pre><\/div><\/p>\n<p>We&rsquo;re super excited, we hit the run button and&hellip;<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-text\" data-lang=\"text\"><span style=\"display:flex;\"><span>FINISHED  26 VirtualThread[#58]\/runnable@ForkJoinPool-1-worker-8\n<\/span><\/span><span style=\"display:flex;\"><span>FINISHED  21 VirtualThread[#52]\/runnable@ForkJoinPool-1-worker-4\n<\/span><\/span><span style=\"display:flex;\"><span>FINISHED  30 VirtualThread[#62]\/runnable@ForkJoinPool-1-worker-2\n<\/span><\/span><span style=\"display:flex;\"><span>Tasks: started [100], finished [3] <\/span><\/span><\/code><\/pre><\/div>\n<p>Wait, what? WT <em>actual<\/em> F? WHERE MY PERFORMANCE??!!!1one<\/p>\n<p>Just to be sure we didn&rsquo;t break things accidentally, we flip the feature flag back and check the results with two parallel streams. And it&rsquo;s just like it was before: <code>Tasks: started [34], finished [17]<\/code>.<\/p>\n<p>Well, it seems that virtual threads behaved exactly like the electron. We wanted to take a closer look at them, and instead they&rsquo;re&hellip; gone? What is this nonsense? Have they<\/p>\n<h2 id=\"introduced-quantum-mechanics-to-java\">Introduced Quantum Mechanics to Java?<\/h2>\n<p>First things first. Why don&rsquo;t we see the <code>FINE<\/code> statements at all? Well, that&rsquo;s <a href=\"https:\/\/letmegooglethat.com\/?q=Why+I+don%27t+see+FINE+statements+in+Java+util+logging%3F\">not so difficult to figure out<\/a> ;-)<\/p>\n<p>Seeing the logged <code>STEP<\/code>s is helpful, although not mandatory.\nAfter initial <code>STEP 1<\/code>, we start seeing something like:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-text\" data-lang=\"text\"><span style=\"display:flex;\"><span>STEP 1 27 VirtualThread[#61]\/runnable@ForkJoinPool-1-worker-9 \n<\/span><\/span><span style=\"display:flex;\"><span>STEP 2 10 VirtualThread[#43]\/runnable@ForkJoinPool-1-worker-6 \n<\/span><\/span><span style=\"display:flex;\"><span>STEP 2 15 VirtualThread[#48]\/runnable@ForkJoinPool-1-worker-11 \n<\/span><\/span><span style=\"display:flex;\"><span>STEP 1 30 VirtualThread[#64]\/runnable@ForkJoinPool-1-worker-11 \n<\/span><\/span><span style=\"display:flex;\"><span>STEP 2 16 VirtualThread[#49]\/runnable@ForkJoinPool-1-worker-9 \n<\/span><\/span><span style=\"display:flex;\"><span>STEP 2 19 VirtualThread[#53]\/runnable@ForkJoinPool-1-worker-3 \n<\/span><\/span><span style=\"display:flex;\"><span>STEP 1 28 VirtualThread[#62]\/runnable@ForkJoinPool-1-worker-6 <\/span><\/span><\/code><\/pre><\/div>\n<p>and if we keep scrolling, even such output is revealed to our eyes:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-text\" data-lang=\"text\"><span style=\"display:flex;\"><span>STEP 1 47 VirtualThread[#81]\/runnable@ForkJoinPool-1-worker-11\n<\/span><\/span><span style=\"display:flex;\"><span>STEP 4 20 VirtualThread[#54]\/runnable@ForkJoinPool-1-worker-15\n<\/span><\/span><span style=\"display:flex;\"><span>STEP 2 21 VirtualThread[#55]\/runnable@ForkJoinPool-1-worker-9 \n<\/span><\/span><span style=\"display:flex;\"><span>STEP 5  8 VirtualThread[#41]\/runnable@ForkJoinPool-1-worker-12 \n<\/span><\/span><span style=\"display:flex;\"><span>STEP 5  5 VirtualThread[#38]\/runnable@ForkJoinPool-1-worker-14 \n<\/span><\/span><span style=\"display:flex;\"><span>STEP 1 29 VirtualThread[#63]\/runnable@ForkJoinPool-1-worker-14<\/span><\/span><\/code><\/pre><\/div>\n<p>That may look strange&hellip; in the streams approach things are &ldquo;as expected&rdquo;, and the steps are processed in sort of batches&hellip; First we see 17 tasks in <code>STEP 1<\/code>, then they all move to <code>STEP 2<\/code>, and so on, and after <code>FINISH<\/code>ing, the workers pick next tasks in <code>STEP 1<\/code>. So as long as a task is running, the workers from the underlying ForkJoin pool keep working on their tasks, from the beginning until completion.<\/p>\n<p>However, this is clearly not the case of the VirtualThreads&hellip; In the very first output we saw this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;display:grid;\"><code class=\"language-text\" data-lang=\"text\"><span style=\"display:flex; background-color:#3c3d38\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1<\/span><span>STEP 1 27 VirtualThread[#61]\/runnable@ForkJoinPool-1-worker-9 \n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">2<\/span><span>STEP 2 10 VirtualThread[#43]\/runnable@ForkJoinPool-1-worker-6 \n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">3<\/span><span>STEP 2 15 VirtualThread[#48]\/runnable@ForkJoinPool-1-worker-11 \n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">4<\/span><span>STEP 1 30 VirtualThread[#64]\/runnable@ForkJoinPool-1-worker-11 \n<\/span><\/span><span style=\"display:flex; background-color:#3c3d38\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">5<\/span><span>STEP 2 16 VirtualThread[#49]\/runnable@ForkJoinPool-1-worker-9 \n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">6<\/span><span>STEP 2 19 VirtualThread[#53]\/runnable@ForkJoinPool-1-worker-3 \n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">7<\/span><span>STEP 1 28 VirtualThread[#62]\/runnable@ForkJoinPool-1-worker-6 <\/span><\/span><\/code><\/pre><\/div>\n<p>Task #27 was taken to <code>STEP 1<\/code> by <code>Virtual Thread[#61]<\/code>, using <code>worker-9<\/code>. Then instead of carrying this very task #27 further, <code>worker-9<\/code> got assigned to <code>VirtualThread[#49]<\/code>, handling <code>STEP 2<\/code> of task #16. According to the output, the same happened to <code>worker-6<\/code> and <code>worker-11<\/code>. And I guess it&rsquo;s quite safe to say that statistically this happened to every task and virtual thread. The three tasks which got completed were lucky winners, which were taken through all five steps by some workers, not necessarily the same workers from <code>STEP 1<\/code> to <code>STEP 5<\/code>.<\/p>\n<p>What we see here in action is<\/p>\n<h2 id=\"the-very-purpose-of-virtual-threads\">The Very Purpose Of Virtual Threads<\/h2>\n<p>Whenever they encounter an IO operation, they unmount the carrier thread. This way the carrier thread can pick up another virtual thread to carry and keep carrying it as long as the other virtual thread doesn&rsquo;t call an IO operation.<\/p>\n<p>It&rsquo;s pretty much like with taxis or shared rides. Once you got into the car (you previously summoned somehow), the driver doesn&rsquo;t kick you out, until you reach your destination. And the drivers don&rsquo;t care if it&rsquo;s a subsequent ride for you that day, or the first one. <br>\nUber driver won&rsquo;t prefer you just because earlier tonight someone from Uber drove you to the restaurant, and now you want to change your location. Statistically, everyone is equal here. So the solution is not to let the taxi go, but keep it and pay for it. Or simply don&rsquo;t exit the car ;-)<\/p>\n<p>In our example that means: don&rsquo;t call unnecessary IO \/ logging, because this splits your journey into smaller trips. Now, the total mileage for all persons \/ tasks will be more or less the same. But if you prefer some people \/ tasks to actually <em>complete the whole journey<\/em>, this is what you have to take into account.<\/p>\n<p>It&rsquo;s just important to remember what virtual threads are meant for and good at. If you have some IO operations (not only logging, but also, or maybe even predominantly, DB queries, file operations, network calls), they allow switching CPU power to other tasks, instead of waiting needlessly. <br>\nPretty much like with taxi cars: if you get into a restaurant to have dinner with your friends, you hardly ever tell the driver &lsquo;Please park here and keep the engine running, I&rsquo;ll pay for that&rsquo;. Instead, you release the taxi and call it when you actually have to go back home and in the meantime other people can use the taxi, which is a costly resource.<\/p>\n<p>However, good luck calling a taxi after a huge concert ;-)<\/p>\n<p>It&rsquo;s also true that virtual threads are threads, and you can easily verify it on your own:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span>Thread.<span style=\"color:#a6e22e\">ofVirtual<\/span>().<span style=\"color:#a6e22e\">start<\/span>(() <span style=\"color:#f92672\">-&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">if<\/span>(Thread.<span style=\"color:#a6e22e\">currentThread<\/span>() <span style=\"color:#66d9ef\">instanceof<\/span> Thread) {\n<\/span><\/span><span style=\"display:flex;\"><span>        System.<span style=\"color:#a6e22e\">out<\/span>.<span style=\"color:#a6e22e\">println<\/span>(<span style=\"color:#e6db74\">&#34;virtual thread is a thread&#34;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>});<\/span><\/span><\/code><\/pre><\/div>\n<p>Therefore, we can use virtual threads in all places, libraries and frameworks, where we used good ol&rsquo; Threads so far. Only please be aware, that IO calls will chop your journeys into smaller segments. And that there&rsquo;s this pool &ldquo;which can be tuned&rdquo;, but (at the moment of writing) using our own pool for virtual threads is not allowed. For this we have to stick to Completable Futures.<\/p>\n<h4 id=\"hey-but-i-can-force-my-virtual-thread-not-to-leave-the-cab\">Hey, but I can force my virtual thread not to leave the cab!<\/h4>\n<p>Sure you can, because we could make the whole task <code>synchronized<\/code>. And perhaps in our case that maybe could work without paying too much performance penalty (because we&rsquo;re just logging to local console).<\/p>\n<p>For now, because this mechanism may change in future Java versions. And if the <code>report<\/code> operation takes longer (say, a blocking remote logging is in place), then it will needlessly pin the carrier thread. Usually it&rsquo;s one of these <em>Really Bad Ideas\u2122<\/em>, which I described <a href=\"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/loom\/testing-virtual-threads\/\">here<\/a> and <a href=\"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/loom\/misusing-virtual-threads\/\">here<\/a>.<\/p>\n<p>I would suggest monitoring the progress of tasks without relying on IO called <em>inside<\/em> virtual threads. And, as demonstrated, <code>log(&quot;HERE&quot;)<\/code> counts as one.<\/p>\n<h4 id=\"different-pools\">Different pools<\/h4>\n<p>There&rsquo;s one more thing to finish this entry. In case someone didn&rsquo;t pay attention both to the manual, both to the output&hellip;<\/p>\n<p>This happens with streams:\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-text\" data-lang=\"text\"><span style=\"display:flex;\"><span>FINISHED  48 Thread[#37,ForkJoinPool.commonPool-worker-7,5,main]<\/span><\/span><\/code><\/pre><\/div><\/p>\n<p>and this happens with virtual threads (now):\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-text\" data-lang=\"text\"><span style=\"display:flex;\"><span>FINISHED  26 VirtualThread[#58]\/runnable@ForkJoinPool-1-worker-8<\/span><\/span><\/code><\/pre><\/div><\/p>\n<p>Yes, these are two different Fork Join pools. Hence, we can get rid of the feature flag and run the tasks in both streams and virtual threads (without <code>FINE<\/code> logging).<\/p>\n<p>And therefore we can see then any of these results:\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-text\" data-lang=\"text\"><span style=\"display:flex;\"><span>Tasks: started [60], finished [18]\n<\/span><\/span><span style=\"display:flex;\"><span>Tasks: started [60], finished [19]\n<\/span><\/span><span style=\"display:flex;\"><span>Tasks: started [50], finished [7]\n<\/span><\/span><span style=\"display:flex;\"><span>Tasks: started [66], finished [30]<\/span><\/span><\/code><\/pre><\/div>\nWhy? Well, it&rsquo;s yet another entry to write. TL;DR: there are reasons behind &ldquo;thread per core&rdquo;.<\/p>\n<p><br>\nWhoa, this turned out to be longer than I expected ;-) You&rsquo;re more than welcome to discuss in social media. Links in the footer.<\/p>\n"},{"title":"Java 19 & 20. What's new and noteworthy??","link":"https:\/\/softwaregarden.dev\/en\/talks\/java-19-20-new-and-noteworthy\/","pubDate":"Mon, 24 Jul 2023 10:00:00 +0200","guid":"https:\/\/softwaregarden.dev\/en\/talks\/java-19-20-new-and-noteworthy\/","description":"<p>Hey, there are two major Java versions released every year! We don\u2019t have to wait 3 years or so for new features anymore. Isn\u2019t that cool? \ud83d\ude09<\/p>\n<p>Java was supposed &ldquo;to be slow&rdquo;. However, Java turns out to evolve so fast, that next releases aren&rsquo;t just version bumps, but might significantly change the rules of the game. That&rsquo;s a good reason to check out what&rsquo;s new in Java.<\/p>\n<p>To name a few changes:<\/p>\n<ul>\n<li>Pattern Matching for switch,<\/li>\n<li>Record Patterns,<\/li>\n<li>Virtual Threads,<\/li>\n<li>Calling native stuff,<\/li>\n<li>what&rsquo;s gone and what will be gone,<\/li>\n<li>and other stuff.<\/li>\n<\/ul>\n<p>If you find them interesting, let\u2019s dive deep together into new interesting stuff.<\/p>\n<p>So far I had the pleasure to give this talk at <a href=\"https:\/\/devoxx.fr\/\">Devoxx France<\/a>, <a href=\"https:\/\/devoxx.pl\/\">Devoxx Poland<\/a>, VoxxedDays Luxembourg, Szczecin JUG and Zielona G\u00f3ra JUG.<\/p>\n<div style=\"position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;\">\n      <iframe allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen\" loading=\"eager\" referrerpolicy=\"strict-origin-when-cross-origin\" src=\"https:\/\/www.youtube-nocookie.com\/embed\/sTsiuydysiA?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0\" style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;\" title=\"YouTube video\"><\/iframe>\n    <\/div>\n\n"},{"title":"IT workshops for charity: the how and the why","link":"https:\/\/softwaregarden.dev\/en\/posts\/events\/charity-workshops\/","pubDate":"Tue, 23 May 2023 22:30:00 +0200","guid":"https:\/\/softwaregarden.dev\/en\/posts\/events\/charity-workshops\/","description":"<p>I don&rsquo;t always run public open trainings, but when I do, I try to run them as charity events. I believe this approach is meaningful and necessary. In this article, I will explain why I find it useful and important. However, let me begin by outlining some rules.<\/p>\n<p>Feel free to adopt this idea if you find it appealing.<\/p>\n<h3 id=\"rules\">Rules<\/h3>\n<p>When running an IT charity workshop, I establish the following rules. It is crucial to adhere to all of them, as disregarding any could lead to complications.<\/p>\n<ol>\n<li>Participants should RSVP as &ldquo;will come&rdquo; (e.g., using Meetup) as their first step.<\/li>\n<li>Within 24 to 48 hours, they must provide proof of a charity donation they made; otherwise, their seat will be released back to the pool of available seats.<\/li>\n<li>Proof of donation should be submitted in advance and cannot be presented at the door when the workshop starts.<\/li>\n<li>The donation must be made to a legally recognized organization (ideally state-recognized, if applicable). In Poland, for example, we have a list of officially registered foundations\/NGOs. It should not be a donation made to just anyone to cover personal expenses. Our intention is to assist those in genuine need, rather than supporting dubious causes.<\/li>\n<li>The donation should be of a minimum amount, usually around 10 EUR (even students can afford the equivalent of two or three beers or coffees). However, there is no upper limit, and that&rsquo;s the beauty of this approach (and trust me, people often donate more).<\/li>\n<li>The workshop&rsquo;s webpage should not provide a simple button to &ldquo;send ten bucks with PayPal to organization ABC.&rdquo; Each participant must:\n<ul>\n<li>Find someone who needs help.<\/li>\n<li>Send money directly to them via bank transfer or the organization&rsquo;s website.<\/li>\n<li>Submit proof of donation to the workshop organizers.<\/li>\n<\/ul>\n<\/li>\n<li>Sponsors can provide a venue, drinks, and other support, but they should not cover the cost of tickets. Each participant must bear the expenses themselves. No one, including sponsors, employers, or training budgets, can pay on behalf of participants. Each individual must contribute their own funds.<\/li>\n<\/ol>\n<h3 id=\"reasons\">Reasons<\/h3>\n<ul>\n<li>I&rsquo;m not a rock star who can give a charity concert. The closest thing I can do, related to my professional activities, is to run a workshop where all the &ldquo;fees&rdquo; are donated to those in need, while I cover my own expenses.<\/li>\n<li>Knowledge is not free. While you can visit a library and read a book &ldquo;for free,&rdquo; someone had to print that book. Someone has to pay the librarian. Someone had to build the library building. Someone had to manufacture the table where you sit to read the book. The same applies to &ldquo;free YouTube courses&rdquo;; they were created by individuals who invested their time (and trust me, it&rsquo;s not easy-peasy). When there is a small cost involved, it serves as a reminder of the effort behind it.<\/li>\n<li>IT professionals are generally in a privileged position. Some even consider us part of an IT aristocracy. I see no reason why individuals in such an above-average position couldn&rsquo;t be encouraged to help those who genuinely require assistance.<\/li>\n<li>In non-commercial workshops (i.e., free workshops), I have often witnessed all seats being booked, with people on the waiting list. However, when the workshop begins, approximately one-third of the seats remain empty because some individuals simply clicked &ldquo;yeah, I wanna come&rdquo; but didn&rsquo;t show up, wasting venue capacity and the trainer&rsquo;s time. Since there was no commitment required on their part other than clicking &ldquo;reserve your seat,&rdquo; those who genuinely wanted to attend were unable to do so because the &ldquo;low-committers&rdquo; didn&rsquo;t bother to update their RSVP. It pains me to see this happen.<\/li>\n<li>Furthermore, even if they do attend the workshop, they may not value it as much because it was free. They may skip pre-work or arrive late because they feel they have nothing to lose. The mindset of &ldquo;I paid for it, so I have to take it seriously&rdquo; works effectively.<\/li>\n<\/ul>\n<figure class=\"image image right\">\n<img src=\"give-and-take.jpg\" alt=\"Give and take\" width=\"640\">\n<\/figure>\n\n<p>It should require effort to search for someone in need and then visit the bank&rsquo;s website or the foundation\/NGO&rsquo;s page to send the donation. People learn best through hands-on experiences. If they discover that they don&rsquo;t need volunteers to show up at their door on a Saturday morning but can independently find someone to help and send money directly <strong>themselves<\/strong>, this knowledge is more likely to resonate with them. Who knows, perhaps next time they will consider donating their time to a charity foundation?<\/p>\n<p>This is actually the aspect that potential participants find most challenging. After attending the workshop, they admit with laughter that this is the most demanding part of the entire process. If there was a simple button, like those found in major e-commerce sites, saying &ldquo;take my money and let me in,&rdquo; it would be easy. However, the fact that it requires <strong>effort<\/strong> to help and participate serves as a valuable lesson, teaching them that a) they can help others in a similar manner, and b) the trainer&rsquo;s time and knowledge are not free.<\/p>\n<p>Picture by <a href=\"https:\/\/pixabay.com\/users\/geralt-9301\/?utm_source=link-attribution&amp;utm_medium=referral&amp;utm_campaign=image&amp;utm_content=556151\">Gerd Altmann<\/a> from <a href=\"https:\/\/pixabay.com\/\/?utm_source=link-attribution&amp;utm_medium=referral&amp;utm_campaign=image&amp;utm_content=556151\">Pixabay<\/a>.<\/p>\n"},{"title":"How to shorten builds using Testcontainers","link":"https:\/\/softwaregarden.dev\/en\/posts\/testcontainers\/parallel-start-with-prepulling\/","pubDate":"Tue, 23 May 2023 10:30:00 +0200","guid":"https:\/\/softwaregarden.dev\/en\/posts\/testcontainers\/parallel-start-with-prepulling\/","description":"<p>Some people complain that they&rsquo;re not doing integration tests &ldquo;because they take too much time.&rdquo; All right, the interaction with real dependencies sometimes can&rsquo;t be made shorter, but there are surely ways to start the databases, message brokers, and so on faster if you happen to use Testcontainers for that.<\/p>\n<p>In this entry, I&rsquo;ll be using Java. However, since Testcontainers is (from a certain angle) a convenient way to interoperate with Docker-compatible containers using the programming language you know, this should apply to other technology stacks as well. I&rsquo;m pretty sure that after grasping the idea, one should be able to translate it to Go or C#.<\/p>\n<p>And quite naturally, this post will have some numbers, sorry.<\/p>\n<h3 id=\"how-many-times-start-the-container\">How many times start the container?<\/h3>\n<p>Testcontainers can be perceived as an Infrastructure-as-a-Code (IaaC) tool. How many times do you usually start your databases or other dependencies of your infrastructure for your tests when doing that, for example, manually or in a Bash script? Do you do that before every <code>@Test<\/code> or rather start once and let the whole suite (or as many as you need) run? Exactly. For that reason, (re-)starting containers before individual test cases should be an exception rather than the default practice.<\/p>\n<p>If you control your containers&rsquo; lifecycle manually, in Java, it&rsquo;s usually enough to call <code>container.start()<\/code> in a static method, usually annotated with <code>@BeforeAll<\/code>.<\/p>\n<p>It might be less obvious if you&rsquo;re relying on a testing framework integration, like annotating your JUnit test class with <code>@Testcontainers<\/code> and the container fields with <code>@Container<\/code>. Then instead of doing this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;display:grid;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1<\/span><span><span style=\"color:#a6e22e\">@Testcontainers<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">2<\/span><span><span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">IntegrationTests<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">3<\/span><span>    <span style=\"color:#a6e22e\">@Container<\/span>\n<\/span><\/span><span style=\"display:flex; background-color:#3c3d38\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">4<\/span><span>    <span style=\"color:#66d9ef\">final<\/span> PosgreSQLContainer postgres <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> ...\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">5<\/span><span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">6<\/span><span>    <span style=\"color:#75715e\">\/\/ tests go here<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">7<\/span><span>}<\/span><\/span><\/code><\/pre><\/div>\n<p>make sure the annotated field is static:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;display:grid;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1<\/span><span><span style=\"color:#a6e22e\">@Testcontainers<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">2<\/span><span><span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">IntegrationTests<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">3<\/span><span>    <span style=\"color:#a6e22e\">@Container<\/span>\n<\/span><\/span><span style=\"display:flex; background-color:#3c3d38\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">4<\/span><span>    <span style=\"color:#66d9ef\">static<\/span> <span style=\"color:#66d9ef\">final<\/span> PosgreSQLContainer postgres <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> ...\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">5<\/span><span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">6<\/span><span>    <span style=\"color:#75715e\">\/\/ tests go here<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">7<\/span><span>}<\/span><\/span><\/code><\/pre><\/div>\n<p>Because of that, it will be started only once.<\/p>\n<h3 id=\"how-many-cpu-cores-do-you-have\">How many CPU cores do you have?<\/h3>\n<p>The short answer is: many. So, there&rsquo;s no need to start your containers one by one in a waterfall-like approach. Instead, you can start them in parallel. For example, if in your tests, you need two external dependencies (let&rsquo;s say PostgreSQL and Kafka) starting in 20s and 30s respectively, in the flow I&rsquo;ve seen most of the time, the whole <code>@BeforeAll<\/code> will take around 50 seconds because (pseudocode ahead):<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;display:grid;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1<\/span><span><span style=\"color:#66d9ef\">final<\/span> <span style=\"color:#66d9ef\">static<\/span> PosgreSQLContainer postgres <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> ...\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">2<\/span><span><span style=\"color:#66d9ef\">final<\/span> <span style=\"color:#66d9ef\">static<\/span> KafkaContainer kafka <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> ...\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">3<\/span><span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">4<\/span><span><span style=\"color:#a6e22e\">@BeforeAll<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">5<\/span><span><span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#66d9ef\">void<\/span> <span style=\"color:#a6e22e\">setupRealDependencies<\/span>() {\n<\/span><\/span><span style=\"display:flex; background-color:#3c3d38\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">6<\/span><span>    postgres.<span style=\"color:#a6e22e\">start<\/span>(); <span style=\"color:#75715e\">\/\/ this is blocking the execution for 20 seconds<\/span>\n<\/span><\/span><span style=\"display:flex; background-color:#3c3d38\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">7<\/span><span>    kafka.<span style=\"color:#a6e22e\">start<\/span>(); <span style=\"color:#75715e\">\/\/ and after 20s, this call is blocking for yet another 30 seconds<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">8<\/span><span>}<\/span><\/span><\/code><\/pre><\/div>\n<p>If your CPU is capable of running multiple processes at the same time, why not utilise it properly? In a way, such an enqueued startup sequence is just a waste of your processing power (unless you&rsquo;re using it for something else, but who&rsquo;s scrolling Facebook during cloud CI builds?)<\/p>\n<p>This hint is simple: try starting the containers ASAP and start them all at once (unless, of course, your test scenario involves chaos engineering, retrials, and such&hellip;)<\/p>\n<p>If you control your containers manually, in Java something like this should do:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;display:grid;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1<\/span><span><span style=\"color:#66d9ef\">static<\/span> <span style=\"color:#66d9ef\">final<\/span> PosgreSQLContainer postgres <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> ...\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">2<\/span><span><span style=\"color:#66d9ef\">static<\/span> <span style=\"color:#66d9ef\">final<\/span> KafkaContainer kafka <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> ...\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">3<\/span><span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">4<\/span><span><span style=\"color:#a6e22e\">@BeforeAll<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">5<\/span><span><span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#66d9ef\">void<\/span> <span style=\"color:#a6e22e\">setupRealDependencies<\/span>() {\n<\/span><\/span><span style=\"display:flex; background-color:#3c3d38\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">6<\/span><span>    Stream.<span style=\"color:#a6e22e\">of<\/span>(postgres, kafka).<span style=\"color:#a6e22e\">parallel<\/span>().<span style=\"color:#a6e22e\">forEach<\/span>(GenericContainer::start); <span style=\"color:#75715e\">\/\/ this call takes max(20s,30s)<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">7<\/span><span>}<\/span><\/span><\/code><\/pre><\/div>\n<p>Of course, sometimes there are joys of ForkJoin Pool affecting Stream.parallel(), in such case maybe you&rsquo;d like to use instead:<\/p>\n<p><code>Startables.deepStart(postgres, kafka).join();<\/code><\/p>\n<p>It does virtually the same, only sometimes it takes a few moments more to grasp it (e.g. for new team members).<\/p>\n<p>If you&rsquo;re relying on JUnit integration by applying <code>@Testcontainers<\/code> and <code>@Container<\/code> annotations, then (starting in version 1.18.0) Testcontainers can start the containers for you in parallel too, by using <code>@Testcontainers(parallel = true)<\/code>, like this<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;display:grid;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex; background-color:#3c3d38\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1<\/span><span><span style=\"color:#a6e22e\">@Testcontainers<\/span>(parallel <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">true<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">2<\/span><span><span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">IntegrationTests<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">3<\/span><span>    <span style=\"color:#a6e22e\">@Container<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">4<\/span><span>    <span style=\"color:#66d9ef\">static<\/span> <span style=\"color:#66d9ef\">final<\/span> PosgreSQLContainer postgres <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> ...\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">5<\/span><span>    <span style=\"color:#a6e22e\">@Container<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">6<\/span><span>    <span style=\"color:#66d9ef\">static<\/span> <span style=\"color:#66d9ef\">final<\/span> KafkaContainer kafka <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> ...\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">7<\/span><span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">8<\/span><span>    <span style=\"color:#75715e\">\/\/ tests go here<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">9<\/span><span>}<\/span><\/span><\/code><\/pre><\/div>\n<h3 id=\"charge-your-stuff-in-advance\">Charge your stuff in advance<\/h3>\n<p>If you&rsquo;re staying home, it usually doesn&rsquo;t bother you whether your laptop is charged or not because it can be charged at any time, and you can still work while charging it. However, if you&rsquo;re going on a long trip, you might wish to charge your electric car in advance to avoid unnecessary delays along the way.<\/p>\n<p>Something similar applies to Testcontainers too because the fuel they use is Docker images.<\/p>\n<p>If you&rsquo;re working on your own machine and run Testcontainers-powered tests from time to time (as you should be, by the way!), then it&rsquo;s easy to forget that there&rsquo;s no magic involved in starting the containers, but serious engineering. To <code>start()<\/code> a container, the library must first have the image in the local storage, so it fetches it or <code>docker pull<\/code>s if you will.<\/p>\n<p>On desktop, it&rsquo;s not a big deal because it usually happens only the very first time, and then the image stays, so <code>aContainer.start()<\/code> doesn&rsquo;t involve pulling the image when called the second time and later on.<\/p>\n<p>However, in cloud CIs, this is very often not the case. Your build is running on a freshly assigned, ephemeral worker that doesn&rsquo;t keep images used in previous runs. That is unless you configure your pipeline to cache them, like the <code>.jar<\/code> files from dependencies.<\/p>\n<p>In case you can&rsquo;t cache them (JARs, Docker images, or both), the following pre-charging technique might be quite handy. The concept is quite simple: instead of pulling the images when containers are <code>start()<\/code>ed (directly or indirectly, that doesn&rsquo;t matter), we shall pull them in advance. So that when Testcontainers requires them, they&rsquo;re already loaded, and our tests are then blocked only for the period needed to start the container, not pull the image plus start the container.<\/p>\n<p>The question is: when to pull the images.<\/p>\n<p>If you decide to pull them in the Java code, then it might be somewhat late because if we start the containers in a static method, there might be some gains, but not huge. Sometimes even negligible, in fact.<\/p>\n<p>How often do you profile or observe telemetry in your build pipeline? I mean, with a proper profiler and such, to check CPU, RAM, IO, and network, and push them to the limits? I used to do that, so let me share some lessons learned: you don&rsquo;t want to choke any of these when they&rsquo;re already saturated, but instead, you may do some pre-computation or pre-downloading when it doesn&rsquo;t affect the other actions in your build. When your pipeline is downloading half of the internet (especially with <code>npm<\/code>), you don&rsquo;t want it to download the other half right that instant.<\/p>\n<p>Therefore, an optimization like:<\/p>\n<ul>\n<li>pull Docker images, and<\/li>\n<li>pull all the dependencies using Gradle or Maven<\/li>\n<\/ul>\n<p><em>at the very same time<\/em><\/p>\n<p>might not give much gain or worse: actually slow your build down. Unless you have a remote container environment configured, then it&rsquo;s fine because it will be somebody else&rsquo;s network busy downloading the 1.3GB Localstack image ;-).<\/p>\n<p>Therefore, the following approach (in pseudo-shell) might not be the best in your pipeline:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-bash\" data-lang=\"bash\"><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1<\/span><span>docker pull -q postgres:version &amp;\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">2<\/span><span>docker pull -q confluentinc\/cp-kafka:version &amp;\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">3<\/span><span>.\/gradlew build<\/span><\/span><\/code><\/pre><\/div>\n<p>because they might start competing for the same resource: network. What Gradle or Maven usually start the build with is resolving the build&rsquo;s dependencies, which results in fetching the JARs. Yes, using the same network that connects you to Docker Hub.<\/p>\n<p>What we might want to do instead is:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-bash\" data-lang=\"bash\"><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1<\/span><span>.\/gradlew dependencies\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">2<\/span><span>docker pull -q postgres:version &amp;\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">3<\/span><span>docker pull -q confluentinc\/cp-kafka:version &amp;\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">4<\/span><span><span style=\"color:#75715e\"># or whatever containers you will need later<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">5<\/span><span>.\/gradlew build<\/span><\/span><\/code><\/pre><\/div>\n<p>The first (blocking call) of <code>.\/gradlew dependencies<\/code> will de-facto download all the JARs needed to compile and test the project. Then, when it exits, we can happily start downloading\/pulling the images that we know will be later used in the <code>test<\/code> when its turn inside the <code>build<\/code> task takes place. Usually, the <code>build<\/code> isn&rsquo;t network-heavy after fetching the dependencies, so we can use the network (and little CPU and IO) to pre-pull images, making them available locally when needed later. Therefore, <code>aContainer.start()<\/code> won&rsquo;t be waiting for the network (usually Docker Hub), but will be ready to start <code>start()<\/code>ing the container immediately.<\/p>\n<p>Please pay attention to details and make sure you finish all <code>docker pull ...<\/code> commands with <code>&amp;<\/code> in Bash, otherwise, they will block the compilation (and others in the <code>build<\/code> task), and therefore there will be no performance improvements.<\/p>\n<figure class=\"image image right\">\n<img src=\"stream-cascade.jpg\" alt=\"Avoid cascade\" width=\"640\">\n<\/figure>\n\n<h2 id=\"recap\">Recap<\/h2>\n<p>I was hoping to explain that some things with Testcontainers (which is IaaC) should not be done in a sequential\/cascade\/waterfall mode but in a parallel mode (if the underlying infrastructure permits).<\/p>\n<p>That applies to starting the containers and pulling the images too.<\/p>\n<p>Here is a relaxing photo of what not to do. ;-)<\/p>\n<p>Picture by <a href=\"https:\/\/pixabay.com\/pl\/users\/mherfurt-8814055\/?utm_source=link-attribution&amp;utm_medium=referral&amp;utm_campaign=image&amp;utm_content=7859362\">Martin Herfurt<\/a> from <a href=\"https:\/\/pixabay.com\/pl\/\/?utm_source=link-attribution&amp;utm_medium=referral&amp;utm_campaign=image&amp;utm_content=7859362\">Pixabay<\/a>.<\/p>\n"},{"title":"Integration tests are needed and simple","link":"https:\/\/softwaregarden.dev\/en\/talks\/integration-tests-are-needed-and-simple\/","pubDate":"Tue, 16 May 2023 18:00:00 +0200","guid":"https:\/\/softwaregarden.dev\/en\/talks\/integration-tests-are-needed-and-simple\/","description":"<p>The pyramids in Egypt were built in ancient times. We still admire them today, appreciating the craftsmanship and hard work of their builders. However, do we build houses from giant stone blocks today? Not likely, current times bring other needs and offer other technologies.<\/p>\n<p>Pyramids of testing were also built some time ago. We admire legacy projects with a rich set of tests, but do we create projects today the same way we did 10-15-20 years ago? If not, why do we still want to test them the same way?<\/p>\n<p>Maybe the shape of today&rsquo;s projects&rsquo; tests should no longer resemble a pyramid? Our needs are different, and the possibilities, thanks to the Testcontainers family of libraries, have also advanced a lot.<\/p>\n<p>If you have a feeling that integration testing can bring a lot to your project, but somehow you haven&rsquo;t had the chance to get acquainted with Testcontainers so far, or you&rsquo;re afraid that it&rsquo;s just &ldquo;magic for top developers&rdquo;, this lecture is for you.<\/p>\n<p>We will quickly, easily and pleasantly rearrange the pyramids of our times \ud83d\ude09<\/p>\n<p>I was able to give this talk few events already, like: GeeCON Poland, Devoxx UK, Devoxx Poland, JNation, etc. More conferences and events will follow ;-)<\/p>\n<p>I&rsquo;m also pleased and honoured that this talk made it to <a href=\"https:\/\/www.linkedin.com\/pulse\/best-rated-devoxx-uk-sessions-devoxx-united-kingdom\/\">TOP10 talks at Devoxx UK 2023<\/a>.<\/p>\n<p>Recording from Devoxx UK:\n<div style=\"position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;\">\n      <iframe allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen\" loading=\"eager\" referrerpolicy=\"strict-origin-when-cross-origin\" src=\"https:\/\/www.youtube-nocookie.com\/embed\/6hHoZN9xRdY?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0\" style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;\" title=\"YouTube video\"><\/iframe>\n    <\/div>\n<\/p>\n<p>Recording from JNation PT:\n<div style=\"position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;\">\n      <iframe allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen\" loading=\"eager\" referrerpolicy=\"strict-origin-when-cross-origin\" src=\"https:\/\/www.youtube-nocookie.com\/embed\/VnayYJIlep0?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0\" style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;\" title=\"YouTube video\"><\/iframe>\n    <\/div>\n<\/p>\n"},{"title":"SDKMAN! - more","link":"https:\/\/softwaregarden.dev\/en\/posts\/tools\/sdkman-more\/","pubDate":"Thu, 23 Mar 2023 22:00:00 +0100","guid":"https:\/\/softwaregarden.dev\/en\/posts\/tools\/sdkman-more\/","description":"<p>During my trainings and lectures, I get asked &ldquo;but how do you switch Java so fast?&rdquo; or even &ldquo;it&rsquo;s possible to have several versions of Java on your computer at the same time?!&rdquo; Sure it is!<\/p>\n<p>The way is very simple: use <a href=\"https:\/\/sdkman.io\/\">SDKMAN!<\/a> I use it almost every day, it comes in handy not only during lectures about the latest versions of Java, but in ordinary daily work when you need to check &ldquo;how it works on another version&rdquo;.<\/p>\n<p>To make the life of my students easier, as a prework for my &ldquo;Modern Java&rdquo; training \/ workshop, I recorded a short mini-tutorial about the SDK Manager. (Un)fortunately, it is encrypted in Polish, therefore I published it in <a href=\"https:\/\/softwaregarden.dev\/pl\/posts\/tools\/sdkman-more\/\">the Polish part of my page<\/a>. Maybe it&rsquo;s still useful with the automatic translation, who knows? ;-)<\/p>\n<p>[ I was pretty sure the second part was published a few months ago. Well, apparently it wasn&rsquo;t. ]<\/p>\n"},{"title":"SDKMAN! - the beginning","link":"https:\/\/softwaregarden.dev\/en\/posts\/tools\/sdkman-basics\/","pubDate":"Thu, 29 Dec 2022 10:00:00 +0100","guid":"https:\/\/softwaregarden.dev\/en\/posts\/tools\/sdkman-basics\/","description":"<p>During my trainings and lectures, I get asked &ldquo;but how do you switch Java so fast?&rdquo; or even &ldquo;it&rsquo;s possible to have several versions of Java on your computer at the same time?!&rdquo; Sure it is!<\/p>\n<p>The way is very simple: use <a href=\"https:\/\/sdkman.io\/\">SDKMAN!<\/a> I use it almost every day, it comes in handy not only during lectures about the latest versions of Java, but in ordinary daily work when you need to check &ldquo;how it works on another version&rdquo;.<\/p>\n<p>To make the life of my students easier, as a prework for my &ldquo;Modern Java&rdquo; training \/ workshop, I recorded a short mini-tutorial about the SDK Manager. (Un)fortunately, it is encrypted in Polish, therefore I published it in <a href=\"https:\/\/softwaregarden.dev\/pl\/posts\/tools\/sdkman-basics\/\">the Polish part of my page<\/a>. Maybe it&rsquo;s still useful with the automatic translation, who knows? ;-)<\/p>\n"},{"title":"Testing (if there are no) pinned Virtual Threads","link":"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/loom\/testing-pinned-virtual-threads\/","pubDate":"Tue, 20 Dec 2022 10:00:00 +0100","guid":"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/loom\/testing-pinned-virtual-threads\/","description":"<p>In the <a href=\"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/loom\/misusing-virtual-threads\/\">previous post<\/a> we were testing if Java&rsquo;s Virtual Threads aren&rsquo;t used in a way that makes them pinned. It&rsquo;s because we want our Platform Threads (especially those in the ForkJoin Pool Co.) to keep carrying more and more new Virtual Threads, instead of keeping the engine running while VTs are pinned. (At least as long as we can&rsquo;t provide our own thread pools to carry VTs.)<br>\nSpoiler alert: we&rsquo;re going to use <a href=\"https:\/\/www.testcontainers.org\/\">Testcontainers<\/a> and <a href=\"https:\/\/github.com\/Shopify\/toxiproxy\">Toxiproxy<\/a> today!<\/p>\n<h3 id=\"the-why\">The &ldquo;WHY&rdquo;<\/h3>\n<p>Things can be tested in many ways usually. There&rsquo;s no &ldquo;one-size-fits-all&rdquo; solution here. Sometimes unit tests are just enough, sometimes we need something more. How we tested for pinned Virtual Threads using <a href=\"https:\/\/github.com\/moditect\/jfrunit\">JfrUnit<\/a> is a nice approach, but there might be times, where something more opaque might be needed. And something resembling actual production environment much better. So today we&rsquo;re going to achieve a similar effect using Testcontainers, for the sake of education and some fun!<\/p>\n<p>Previous approach with unit test had two obvious flaws.<\/p>\n<p>First, it&rsquo;s using a fixed port 8080. There have been quite a few posts and talks explaining why this is one of these Really Bad Ideas\u2122. I shall say: if you haven&rsquo;t encountered issues while testing something and using a fixed port for that, chances are you haven&rsquo;t been testing things for real and at bigger scale. Just one hint: have you considered parallel builds on the same machine? Will that work? Okay, another one: what if you discover (hopefully not Friday afternoon), that you can&rsquo;t run the system with the same port in production environment and oopsies, there&rsquo;s no way to configure our system to do so?<br>\nLuckily for us, Testcontainers supports port randomization by default.<\/p>\n<p>Second, the network. We all know that a) it&rsquo;s always the DNS, and b) the latency is never zero. (And we also know a few other things about networks, don&rsquo;t we? ;-)) Let&rsquo;s be honest, the idea of enforcing the latency using heavy calculation like <code>random.ints(15_000_000).sum()<\/code> is really dumb and wasteful. When was the last time when you could control the latency by adding and removing millions of ints here and there in real production system? Exactly&hellip;<br>\nAnd in case you&rsquo;re tempted for <code>Thread.sleep()<\/code>, ask yourself the same question.<br>\nFor emulating there&rsquo;s-always-some-latency network we&rsquo;re going to use something more clever, which is Toxiproxy.<\/p>\n<p>There are also more benefits of using Testcontainers, of course. The most important one might be relying on Docker <em>from within the code<\/em>! Basically, instead of manually creating a server, or installing a 3rd party solution at every developer&rsquo;s machine and every CI environment (and daemons know where else), we can simply declare (via our code): &ldquo;hey, fetch system ABC, add some files, attach it to network, set the latency to be more or less this&rdquo; and then use this whole sophisticated machinery to test our stuff.<\/p>\n<p>In the test, we&rsquo;re going to use three test containers. We will write our test relying on the awesome JUnit 5 library, but despite the &ldquo;unit&rdquo; in its name, it&rsquo;s not going to be a unit test. Basically, we&rsquo;re only going to drive our test using JUnit. To make things somewhat simpler to our friends from non-Java ecosystems, let&rsquo;s try not to rely on the <a href=\"https:\/\/www.testcontainers.org\/test_framework_integration\/junit_5\/\">JUnit integration<\/a>, that already exists in Testcontainers.<\/p>\n<h3 id=\"preparation\">Preparation<\/h3>\n<p>The first container we&rsquo;re going to use is going to be nginx. Yes, instead of creating an HTTP server &ldquo;manually&rdquo;, let&rsquo;s use a solution that&rsquo;s already out there. Also, to host something, let&rsquo;s create a simple <code>test\/resources\/index.html<\/code> file (in modern Java ecosystem it&rsquo;s a resource that&rsquo;s going to be used only while testing). Then we&rsquo;re going to use this file as follows to copy it to a container later on:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">var<\/span> index <span style=\"color:#f92672\">=<\/span> MountableFile.<span style=\"color:#a6e22e\">forClasspathResource<\/span>(<span style=\"color:#e6db74\">&#34;index.html&#34;<\/span>);\n<\/span><\/span><\/code><\/pre><\/div><p>Declaring the nginx container can look like this, we&rsquo;re going to use <code>&quot;nginx:1.23.1&quot;<\/code> version (it&rsquo;s good to be specific), we&rsquo;re going to copy the <code>index.html<\/code> file to <code>\/usr\/share\/nginx\/html\/<\/code> (because that&rsquo;s where nginx hosts files from), we&rsquo;re also going to tell Testcontainers that the <code>nginx<\/code> is not fully ready to be used in testing, until the response code for requests sent to <code>index<\/code> isn&rsquo;t <code>200<\/code>: for this we&rsquo;ll be <code>waitingFor<\/code>.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">var<\/span> nginx <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> NginxContainer<span style=\"color:#f92672\">&lt;&gt;<\/span>(<span style=\"color:#e6db74\">&#34;nginx:1.23.1&#34;<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>    .<span style=\"color:#a6e22e\">withCopyFileToContainer<\/span>(index, <span style=\"color:#e6db74\">&#34;\/usr\/share\/nginx\/html\/index.html&#34;<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>    .<span style=\"color:#a6e22e\">waitingFor<\/span>(<span style=\"color:#66d9ef\">new<\/span> HttpWaitStrategy());\n<\/span><\/span><\/code><\/pre><\/div><p>One of the reasons I joined AtomicJar was to be close to Testcontainers, because this library made my life so much easier&hellip; (And <em>would make<\/em> in all those places where I couldn&rsquo;t use it, because reasons.) However, somehow I managed to &ldquo;avoid&rdquo; Toxiproxy in Testcontainers. That is, until Oleg showed it to me ;-)<\/p>\n<p>So let me show it to you and let&rsquo;s use it, which isn&rsquo;t difficult:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">var<\/span> toxiproxy <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> ToxiproxyContainer(<span style=\"color:#e6db74\">&#34;ghcr.io\/shopify\/toxiproxy:2.5.0&#34;<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>    .<span style=\"color:#a6e22e\">withNetworkAliases<\/span>(<span style=\"color:#e6db74\">&#34;toxiproxy&#34;<\/span>)\n<\/span><\/span><\/code><\/pre><\/div><p>As you can see, we&rsquo;re still specifying the version (because it&rsquo;s good) and we can even grab images not from <a href=\"https:\/\/hub.docker.com\/\">Docker Hub<\/a>, we also alias this very container as <code>toxiproxy<\/code> (for now think of it as of the host name).<\/p>\n<p>Next we&rsquo;re going to start the containers. And to make things happen faster, let&rsquo;s start both at the same time:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span>Stream.<span style=\"color:#a6e22e\">of<\/span>(nginx, toxiproxy).<span style=\"color:#a6e22e\">parallel<\/span>().<span style=\"color:#a6e22e\">forEach<\/span>(GenericContainer::start);\n<\/span><\/span><\/code><\/pre><\/div><p>(Here we could use some JUnit integration, like <code>@Container<\/code> or even something darker, if you&rsquo;re using JDBC&hellip; If you use that in your tests already, there&rsquo;s no need to touch this.)\n<figure class=\"image image left\">\n<img src=\"featured.jpg\" alt=\"Fun will now commence\" width=\"450\">\n<\/figure>\n<\/p>\n<h3 id=\"now-its-time-to-be-toxic-to-commence-the-fun\">Now it&rsquo;s time <del>to be toxic<\/del> to commence the fun!<\/h3>\n<p>Let&rsquo;s intoxicate the connection that our System Under Test is going to utilise:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">var<\/span> proxy <span style=\"color:#f92672\">=<\/span> toxiProxy.<span style=\"color:#a6e22e\">getProxy<\/span>(nginx, 80);\n<\/span><\/span><span style=\"display:flex;\"><span>proxy.<span style=\"color:#a6e22e\">toxics<\/span>()\n<\/span><\/span><span style=\"display:flex;\"><span>    .<span style=\"color:#a6e22e\">latency<\/span>(<span style=\"color:#e6db74\">&#34;latency&#34;<\/span>, ToxicDirection.<span style=\"color:#a6e22e\">DOWNSTREAM<\/span>, 500)\n<\/span><\/span><span style=\"display:flex;\"><span>    .<span style=\"color:#a6e22e\">setJitter<\/span>(50);\n<\/span><\/span><\/code><\/pre><\/div><p>This way we&rsquo;re making the connection between the client and nginx last ~500ms +\/- 50ms.<\/p>\n<h3 id=\"container-izing-our-stuff\">Container-izing our stuff<\/h3>\n<p>The artifact we&rsquo;d like to release to the world (so the world could admire our creation) after the build is in <code>target\/concurrency-1.0-SNAPSHOT.jar<\/code> directory (that&rsquo;s Maven&rsquo;s standard). We could simply run it, of course, because we&rsquo;re trying to migriate our system to Java 19, so we, the developers, have this version of Java installed. However, the CI\/CD systems might not (because &ldquo;LTS only policy blah blah blah yadda yadda&rdquo; or because having many Java versions might be tricky). Also, to make sure that the kraken we&rsquo;re about to release doesn&rsquo;t change even in a single bit, we might want to build it before testing and test exactly that in an isolated container.<\/p>\n<p>Therefore, we&rsquo;re going to create yet another container, just to container-ize our gem, and make sure it can run using Java 19:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">var<\/span> container <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> GenericContainer<span style=\"color:#f92672\">&lt;&gt;<\/span>(<span style=\"color:#e6db74\">&#34;eclipse-temurin:19-alpine&#34;<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>.<span style=\"color:#a6e22e\">withCopyFileToContainer<\/span>(jar, <span style=\"color:#e6db74\">&#34;\/tmp\/test.jar&#34;<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>.<span style=\"color:#a6e22e\">withExposedPorts<\/span>(8000)\n<\/span><\/span><span style=\"display:flex;\"><span>.<span style=\"color:#a6e22e\">withCommand<\/span>(<span style=\"color:#e6db74\">&#34;jwebserver&#34;<\/span>)\n<\/span><\/span><\/code><\/pre><\/div><p>We&rsquo;re copying our gem to <code>\/tmp\/test.jar<\/code>, to call it later. The last two lines aren&rsquo;t going to be used in our test directly, this way we can tell this Java container not to exit immediately after starting, which happens like this: <code>container.start();<\/code> because <code>jwebserver<\/code> will keep running and Testcontainers won&rsquo;t exit the <code>start()<\/code> before the <code>jwebserver<\/code> is listening on this port <em>inside<\/em> the container.<br>\nTo put it in other words: there&rsquo;s no magic here. Testcontainers needs to know when the container it&rsquo;s starting can be considered as <em>started<\/em>. There are various <a href=\"https:\/\/www.testcontainers.org\/features\/startup_and_waits\/\"><code>WaitStrategy<\/code><\/a> implementations, exposing a port is a trick which makes TC wait for that port.<br>\nFinally, we&rsquo;re composing our stuff without <strong>Y<\/strong>elling <strong>A<\/strong>t <strong>M<\/strong>y <strong>L<\/strong>aptop\u2122 ;-)<\/p>\n<h3 id=\"telling-out-client-to-call-over-intoxicated-network\">Telling out client to call over intoxicated network<\/h3>\n<p>Before we tell our client that it should call somewhere, we need to know the <em>where<\/em>. The whole idea is not to call the <code>nginx<\/code> from the <code>container<\/code> directly, but over the intoxicated network. Therefore, the URI to call should be:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">var<\/span> uriFromContainer <span style=\"color:#f92672\">=<\/span> String.<span style=\"color:#a6e22e\">format<\/span>(<span style=\"color:#e6db74\">&#34;http:\/\/%s:%d\/&#34;<\/span>, <span style=\"color:#e6db74\">&#34;toxiproxy&#34;<\/span>, proxy.<span style=\"color:#a6e22e\">getOriginalProxyPort<\/span>());\n<\/span><\/span><\/code><\/pre><\/div><p>Okay, now we can call the client (it was copied to <code>\/tmp\/test.jar<\/code>), tell it to connect to <code>uriFromContainer<\/code>, and let&rsquo;s not forget about the most important thing, to log if any of the Virtual Threads has been pinned! As per <a href=\"https:\/\/openjdk.org\/jeps\/425\">JEP-425<\/a>, if we tell our Java process to log the occurrences of pinned VTs using <code>-Djdk.tracePinnedThreads=full<\/code>, we shall expect full stack traces in the standard output, telling us where it took place exactly.<\/p>\n<p>So this is how we run our artifact inside the Java <code>container<\/code>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">var<\/span> result <span style=\"color:#f92672\">=<\/span> container\n<\/span><\/span><span style=\"display:flex;\"><span>    .<span style=\"color:#a6e22e\">execInContainer<\/span>(<span style=\"color:#e6db74\">&#34;java&#34;<\/span>, <span style=\"color:#e6db74\">&#34;--enable-preview&#34;<\/span>, <span style=\"color:#e6db74\">&#34;-Djdk.tracePinnedThreads=full&#34;<\/span>, <span style=\"color:#e6db74\">&#34;-jar&#34;<\/span>, <span style=\"color:#e6db74\">&#34;\/tmp\/test.jar&#34;<\/span>, uriFromContainer);\n<\/span><\/span><\/code><\/pre><\/div><p>After the process exits, we can assert that the exit code of our program was still zero (i.e. the process exited normally):<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span>Assertions.<span style=\"color:#a6e22e\">assertEquals<\/span>(0, result.<span style=\"color:#a6e22e\">getExitCode<\/span>());\n<\/span><\/span><\/code><\/pre><\/div><p>And that there was no <code>onPinned<\/code> in the standard output (which would appear, if any of our Virtual Threads got, well, pinned):<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span>MatcherAssert.<span style=\"color:#a6e22e\">assertThat<\/span>(result.<span style=\"color:#a6e22e\">getStdout<\/span>(), not(containsString(<span style=\"color:#e6db74\">&#34;onPinned&#34;<\/span>)));\n<\/span><\/span><\/code><\/pre><\/div><h3 id=\"and-thats-really-it\">And that&rsquo;s really it!<\/h3>\n<p>Let&rsquo;s recap the whole setup, which is really quite simple: we build our programme, then tell it to call an HTTP service via a Proxy, which is guaranteed to be toxic.<\/p>\n<p>One could ask: was it really worth it? I&rsquo;d say that in some cases: definitely YES.<\/p>\n<p>Okay, this example might seem quite simple (if not simplistic), because our <em>external<\/em> dependency (the HTTP service) was really trivial and easy to spin in some mock\/stub\/fake fashion. But what if that wasn&rsquo;t the case? What if it was a more sophisticated thing: a queue, a message broker, a database, some cache, another microservice of ours? Sure, we could keep spending more and more time to make our mocks\/stubs\/fakes more and more sophisticated, to write this &ldquo;one more unit test&rdquo;. And then we could maintain them, updating their behaviour to mimic the real dependency, based on every documented change. Oh, and undocumented too ;-) (If you haven&rsquo;t yet wasted two weeks of your life due to undocumented 3rd party change, I &ldquo;envy&rdquo; you the journeys ahead!)<br>\nDid I also mention that testing your stuff against <em>many different<\/em> versions of external dependencies is also waaaay easier this way? Instead of keeping mocks\/stubs\/fakes for the latest <strong>five<\/strong> versions of PostgreSQL (because they&rsquo;re <a href=\"https:\/\/www.postgresql.org\/support\/versioning\/\">supported<\/a> and our product is run on-premises by the people who pay us and use any of the five) to ensure our ORM and\/or DB queries are okay, we can simply parametrize our tests with these versions. Maintaining such test base is way easier and cheaper.<\/p>\n<p>This is the beauty of Testcontainers, these libraries allow us testing against <em>the real thing<\/em>, in all stages of the software delivery process, starting from our own machine. Not worrying about keeping all dependencies installed <em>everywhere<\/em>. And if you&rsquo;re still not sure, how are you going to mock\/stub\/fake the non-zero and tunable network latency?<\/p>\n<h3 id=\"a-bit-more\">A bit more<\/h3>\n<p>Should you be interested in the whole code, it&rsquo;s available below or in <a href=\"https:\/\/github.com\/pioorg\/DeepDiveJava19\/blob\/main\/concurrency\/src\/test\/java\/org\/przybyl\/ddj19\/concurrency\/VirtThreadsPinTCTest.java\">my GitHub repo for Java 19<\/a>.\nPlease keep in mind that this demo assumes that this is the only Testcontainers test in our suite. Should that not be the case, we could perhaps apply some improvements, which I shall describe some other time.<\/p>\n<p>Should you want the test to fail, make sure some Virtual Threads get pinned (which normally you don&rsquo;t want to happen) by making the <code>GreetingObtainer.getGreeting<\/code> method a <code>synchronized<\/code> one. (After this you may want to rebuild the artifact, e.g. by <code>MAVEN_OPTS=&quot;--enable-preview&quot; .\/mvnw package<\/code> ;-) )<\/p>\n<p>In the test I&rsquo;m using <code>try-with-resources<\/code> to make Ryuk less busy. This is a Java idiom which closes the resources opened in the <code>try<\/code> section, regardless the exit point. In general using it to close stuff isn&rsquo;t a bad idea, I&rsquo;d say.<\/p>\n<p>The code:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ we&#39;re going to copy this file from resources to nginx container<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">var<\/span> index <span style=\"color:#f92672\">=<\/span> MountableFile.<span style=\"color:#a6e22e\">forClasspathResource<\/span>(<span style=\"color:#e6db74\">&#34;index.html&#34;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">try<\/span> (\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">var<\/span> nginx <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> NginxContainer<span style=\"color:#f92672\">&lt;&gt;<\/span>(<span style=\"color:#e6db74\">&#34;nginx:1.23.1&#34;<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>        .<span style=\"color:#a6e22e\">withCopyFileToContainer<\/span>(index, <span style=\"color:#e6db74\">&#34;\/usr\/share\/nginx\/html\/index.html&#34;<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>        .<span style=\"color:#a6e22e\">waitingFor<\/span>(<span style=\"color:#66d9ef\">new<\/span> HttpWaitStrategy());\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">var<\/span> toxiProxy <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> ToxiproxyContainer(<span style=\"color:#e6db74\">&#34;ghcr.io\/shopify\/toxiproxy:2.5.0&#34;<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>        .<span style=\"color:#a6e22e\">withNetworkAliases<\/span>(<span style=\"color:#e6db74\">&#34;toxiproxy&#34;<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ starting both containers in parallel<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    Stream.<span style=\"color:#a6e22e\">of<\/span>(nginx, toxiProxy).<span style=\"color:#a6e22e\">parallel<\/span>().<span style=\"color:#a6e22e\">forEach<\/span>(GenericContainer::start);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ creating intoxicated connection to be used between our client and nginx<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">var<\/span> proxy <span style=\"color:#f92672\">=<\/span> toxiProxy.<span style=\"color:#a6e22e\">getProxy<\/span>(nginx, 80);\n<\/span><\/span><span style=\"display:flex;\"><span>    proxy.<span style=\"color:#a6e22e\">toxics<\/span>().<span style=\"color:#a6e22e\">latency<\/span>(<span style=\"color:#e6db74\">&#34;latency&#34;<\/span>, ToxicDirection.<span style=\"color:#a6e22e\">DOWNSTREAM<\/span>, 500).<span style=\"color:#a6e22e\">setJitter<\/span>(50);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#75715e\">\/\/ preparing the artifact to be copied<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">var<\/span> jar <span style=\"color:#f92672\">=<\/span> MountableFile.<span style=\"color:#a6e22e\">forHostPath<\/span>(Paths.<span style=\"color:#a6e22e\">get<\/span>(<span style=\"color:#e6db74\">&#34;target\/concurrency-1.0-SNAPSHOT.jar&#34;<\/span>));\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">try<\/span> (<span style=\"color:#66d9ef\">var<\/span> container <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> GenericContainer<span style=\"color:#f92672\">&lt;&gt;<\/span>(<span style=\"color:#e6db74\">&#34;eclipse-temurin:19-alpine&#34;<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>        .<span style=\"color:#a6e22e\">withCopyFileToContainer<\/span>(jar, <span style=\"color:#e6db74\">&#34;\/tmp\/test.jar&#34;<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span>        .<span style=\"color:#a6e22e\">withExposedPorts<\/span>(8000)\n<\/span><\/span><span style=\"display:flex;\"><span>        .<span style=\"color:#a6e22e\">withCommand<\/span>(<span style=\"color:#e6db74\">&#34;jwebserver&#34;<\/span>)) {\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#75715e\">\/\/ starting container for the client with the client already copied<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>        container.<span style=\"color:#a6e22e\">start<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#75715e\">\/\/ where the client should call<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#66d9ef\">var<\/span> uriFromContainer <span style=\"color:#f92672\">=<\/span> String.<span style=\"color:#a6e22e\">format<\/span>(<span style=\"color:#e6db74\">&#34;http:\/\/%s:%d\/&#34;<\/span>, <span style=\"color:#e6db74\">&#34;toxiproxy&#34;<\/span>, proxy.<span style=\"color:#a6e22e\">getOriginalProxyPort<\/span>());\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>        Assertions.<span style=\"color:#a6e22e\">assertDoesNotThrow<\/span>(() <span style=\"color:#f92672\">-&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>            <span style=\"color:#75715e\">\/\/ running the client which should call the nginx using intoxicated proxy<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>            <span style=\"color:#66d9ef\">var<\/span> result <span style=\"color:#f92672\">=<\/span> container.<span style=\"color:#a6e22e\">execInContainer<\/span>(\n<\/span><\/span><span style=\"display:flex;\"><span>                <span style=\"color:#e6db74\">&#34;java&#34;<\/span>, <span style=\"color:#e6db74\">&#34;--enable-preview&#34;<\/span>, <span style=\"color:#e6db74\">&#34;-Djdk.tracePinnedThreads=full&#34;<\/span>, <span style=\"color:#e6db74\">&#34;-jar&#34;<\/span>, <span style=\"color:#e6db74\">&#34;\/tmp\/test.jar&#34;<\/span>, uriFromContainer);\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>            <span style=\"color:#75715e\">\/\/ eventually it should exit successfully<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>            Assertions.<span style=\"color:#a6e22e\">assertEquals<\/span>(0, result.<span style=\"color:#a6e22e\">getExitCode<\/span>());\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>            <span style=\"color:#75715e\">\/\/ and there should be no virtual threads pinned<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>            MatcherAssert.<span style=\"color:#a6e22e\">assertThat<\/span>(result.<span style=\"color:#a6e22e\">getStdout<\/span>(), not(containsString(<span style=\"color:#e6db74\">&#34;onPinned&#34;<\/span>)));\n<\/span><\/span><span style=\"display:flex;\"><span>        });\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div>"},{"title":"How to (mis)use Virtual Threads","link":"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/loom\/misusing-virtual-threads\/","pubDate":"Wed, 23 Nov 2022 17:00:00 +0100","guid":"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/loom\/misusing-virtual-threads\/","description":"<h2 id=\"how-to-enable-virtual-threads\">How to enable Virtual Threads?<\/h2>\n<p>During my talks about Java 19 (which have the mandatory part dedicated to Virtual Threads), I&rsquo;ve been asked: <em>how do I enable Virtual Threads in the JVM?<\/em> quite a few times.<\/p>\n<p>This question carries an assumption that there&rsquo;s some kind of switch, which has to be activated or hit to &ldquo;magically&rdquo; turn good ol&rsquo; Threads into Virtual Threads. AFAICT there is no such thing right now, and I rather doubt there will be one in the future. There is no system property, environment variable or <code>java<\/code> parameter I know of, that would make Virtual Threads be used <em>instead<\/em> of Platform Threads. (Sure, to be able to use VTs we need to <code>java --enable-preview<\/code>, but that applies to all preview features, it&rsquo;s not VTs specific.)<\/p>\n<p>The Virtual Threads can be activated only by an explicit change in the source code. Basically, the places where Threads are created have to be revisited and changed so that VTs are created instead.<\/p>\n<p>There are at least a few ways to use Virtual Threads instead of Platform Threads.<\/p>\n<p>If we create Threads &ldquo;by hand&rdquo; in our program, we have to change <code>new Thread(...)<\/code> into <code>Thread.ofVirtual()...<\/code>, pretty much as I described in the <a href=\"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/loom\/testing-virtual-threads\/\">previous installment<\/a>.<\/p>\n<p>If we&rsquo;re using an <a href=\"https:\/\/docs.oracle.com\/en\/java\/javase\/19\/docs\/api\/java.base\/java\/util\/concurrent\/ExecutorService.html\"><code>ExecutorService<\/code><\/a>, it might be wise to create one using <a href=\"https:\/\/docs.oracle.com\/en\/java\/javase\/19\/docs\/api\/java.base\/java\/util\/concurrent\/Executors.html#newVirtualThreadPerTaskExecutor()\"><code>Executors.newVirtualThreadPerTaskExecutor()<\/code><\/a><\/p>\n<p>Which in turn relies on <a href=\"https:\/\/docs.oracle.com\/en\/java\/javase\/19\/docs\/api\/java.base\/java\/lang\/Thread.Builder.html#factory()\"><code>Thread.ofVirtual().factory()<\/code><\/a> that can be used if you need a <code>ThreadFactory<\/code>.<\/p>\n<p>I guess the <a href=\"https:\/\/openjdk.org\/jeps\/428\">Structured Concurrency<\/a> is worth taking a look too. (I&rsquo;ll write about it some other time).<\/p>\n<p>Okay, but<\/p>\n<h2 id=\"how-to-misuse-virtual-threads\">How to <em>misuse<\/em> Virtual Threads?<\/h2>\n<p>There are two simple scenarios related to how not use Virtual Threads, and they&rsquo;re listed in <a href=\"https:\/\/openjdk.org\/jeps\/425\">JEP-425<\/a>.<\/p>\n<ol>\n<li>\n<p>You shall not cache\/reuse Virtual Threads.<\/p>\n<p>Really, they are meant to be used only once, so you don&rsquo;t want to cache them. They aren&rsquo;t heavy. Or you shall not use them to throttle \/ handle backpressure. There are better ways to achieve that in the concurrency toolbox.<\/p>\n<\/li>\n<li>\n<p>You don&rsquo;t want to call blocking operations or native code from a <code>synchronized<\/code> section or method, because such a call pins a VirtualThread making such a call to the Platform Thread carrying it.<\/p>\n<figure class=\"image image right\">\n    <img src=\"shall-not-pin-VTs.jpg\" alt=\"You shall not pin Virtual Threads!\" width=\"770\">\n    <\/figure>\n\n<p>Virtual Threads aren&rsquo;t magic. They&rsquo;re implemented as continuations, and they use (i.e. are <em>mounted to<\/em>) Platform Threads when they&rsquo;re active.<\/p>\n<p>Native calls are pretty easy to understand, I believe. We don&rsquo;t know what the native code is doing, so the Virtual Thread making such a call can&rsquo;t unmount the Platform Thread, and needs to be pinned.<\/p>\n<p>And currently the same applies to blocking I\/O calls, although this might be lifted in the future.<\/p>\n<p>So basically, if you&rsquo;re making blocking calls or native calls, you don&rsquo;t want to wrap them in <code>synchronized<\/code>, at least not for long. If you really need to make sure there are no concurrent calls, use locks\/semaphores\/whatever to ensure that.<\/p>\n<\/li>\n<\/ol>\n<h3 id=\"okay-but-how-can-i-know\">Okay, but how can I know<\/h3>\n<p>Well, we shall test our code, right? And do that <em>before<\/em> it gets into production ;-)<\/p>\n<p>By default, Java 19 will emit a new JFR event, <code>jdk.VirtualThreadPinned<\/code>, every time a Virtual Thread gets pinned, with threshold of 20ms. So after we start creating and using VTs in our code, we might want to run the code and check if there are no such events.<\/p>\n<p>Manually? Nah, we&rsquo;re going to automate this, because a) automation is good, b) we can, thanks to <a href=\"https:\/\/github.com\/moditect\/jfrunit\">JfrUnit<\/a>! YAY!!! A big, big THANK YOU to <a href=\"https:\/\/github.com\/gunnarmorling\">Mr. Gunnar Morling<\/a> and other maintainers.<\/p>\n<p>Let&rsquo;s say our code is making HTTP calls, and we&rsquo;re afraid that the VTs might get pinned. We&rsquo;re going to use JUnit 5 and emulate the service our client is calling. It looks like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">38<\/span><span><span style=\"color:#a6e22e\">@BeforeEach<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">39<\/span><span><span style=\"color:#66d9ef\">void<\/span> <span style=\"color:#a6e22e\">setUp<\/span>() <span style=\"color:#66d9ef\">throws<\/span> Exception {\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">40<\/span><span>    server <span style=\"color:#f92672\">=<\/span> HttpServer.<span style=\"color:#a6e22e\">create<\/span>(<span style=\"color:#66d9ef\">new<\/span> InetSocketAddress(8080), 1_000_000);\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">41<\/span><span>    server.<span style=\"color:#a6e22e\">createContext<\/span>(<span style=\"color:#e6db74\">&#34;\/&#34;<\/span>, exchange <span style=\"color:#f92672\">-&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">42<\/span><span>        <span style=\"color:#66d9ef\">int<\/span> sum <span style=\"color:#f92672\">=<\/span> random.<span style=\"color:#a6e22e\">ints<\/span>(15_000_000).<span style=\"color:#a6e22e\">sum<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">43<\/span><span>        <span style=\"color:#66d9ef\">var<\/span> responseBytes <span style=\"color:#f92672\">=<\/span> (sum <span style=\"color:#f92672\">+<\/span> <span style=\"color:#e6db74\">&#34;&#34;<\/span>).<span style=\"color:#a6e22e\">getBytes<\/span>(StandardCharsets.<span style=\"color:#a6e22e\">UTF_8<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">44<\/span><span>        exchange.<span style=\"color:#a6e22e\">getResponseHeaders<\/span>().<span style=\"color:#a6e22e\">add<\/span>(<span style=\"color:#e6db74\">&#34;content-type&#34;<\/span>, <span style=\"color:#e6db74\">&#34;text\/plain&#34;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">45<\/span><span>        exchange.<span style=\"color:#a6e22e\">sendResponseHeaders<\/span>(200, responseBytes.<span style=\"color:#a6e22e\">length<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">46<\/span><span>        exchange.<span style=\"color:#a6e22e\">getResponseBody<\/span>().<span style=\"color:#a6e22e\">write<\/span>(responseBytes);\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">47<\/span><span>        exchange.<span style=\"color:#a6e22e\">close<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">48<\/span><span>    });\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">49<\/span><span>    server.<span style=\"color:#a6e22e\">setExecutor<\/span>(Executors.<span style=\"color:#a6e22e\">newSingleThreadExecutor<\/span>());\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">50<\/span><span>    server.<span style=\"color:#a6e22e\">start<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">51<\/span><span>}\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">52<\/span><span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">53<\/span><span><span style=\"color:#a6e22e\">@AfterEach<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">54<\/span><span><span style=\"color:#66d9ef\">void<\/span> <span style=\"color:#a6e22e\">tearDown<\/span>() {\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">55<\/span><span>    server.<span style=\"color:#a6e22e\">stop<\/span>(1);\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">56<\/span><span>}<\/span><\/span><\/code><\/pre><\/div>\n<p>The server is extremely dumb: it&rsquo;s single-threaded and summarizing 15 million ints (to keep it busy without <code>Thread.sleep()<\/code>), and then serving the sum to the client as plain text. (Depending on your hardware, you may need to tune this number.)\nWhat we want to achieve here is to make HTTP call to this server take some time, and thus block the client.<\/p>\n<p>Then, the actual test case may look like this:\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">58<\/span><span><span style=\"color:#a6e22e\">@Test<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">59<\/span><span><span style=\"color:#a6e22e\">@EnableEvent<\/span>(<span style=\"color:#e6db74\">&#34;jdk.VirtualThreadPinned&#34;<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">60<\/span><span><span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#66d9ef\">void<\/span> <span style=\"color:#a6e22e\">shouldNotPin<\/span>() <span style=\"color:#66d9ef\">throws<\/span> InterruptedException {\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">61<\/span><span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">62<\/span><span>    <span style=\"color:#66d9ef\">var<\/span> client <span style=\"color:#f92672\">=<\/span> HttpClient.<span style=\"color:#a6e22e\">newBuilder<\/span>().<span style=\"color:#a6e22e\">connectTimeout<\/span>(Duration.<span style=\"color:#a6e22e\">ofSeconds<\/span>(5)).<span style=\"color:#a6e22e\">build<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">63<\/span><span>    <span style=\"color:#66d9ef\">var<\/span> request <span style=\"color:#f92672\">=<\/span> HttpRequest.<span style=\"color:#a6e22e\">newBuilder<\/span>(URI.<span style=\"color:#a6e22e\">create<\/span>(<span style=\"color:#e6db74\">&#34;http:\/\/localhost:8080&#34;<\/span>)).<span style=\"color:#a6e22e\">GET<\/span>().<span style=\"color:#a6e22e\">build<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">64<\/span><span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">65<\/span><span>    VirtThreads.<span style=\"color:#a6e22e\">getGreetings<\/span>(client, request, 20);\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">66<\/span><span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">67<\/span><span>    jfrEvents.<span style=\"color:#a6e22e\">awaitEvents<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">68<\/span><span>    Assertions.<span style=\"color:#a6e22e\">assertTrue<\/span>(jfrEvents.<span style=\"color:#a6e22e\">events<\/span>().<span style=\"color:#a6e22e\">findAny<\/span>().<span style=\"color:#a6e22e\">isEmpty<\/span>(), <span style=\"color:#e6db74\">&#34;there should be no pinned events&#34;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">69<\/span><span>}<\/span><\/span><\/code><\/pre><\/div><\/p>\n<p>This test is also quite simple, I hope. First, in line 59 we tell JfrUnit to capture <code>jdk.VirtualThreadPinned<\/code> JFR events. Then we run the System Under Test. Then in line 89 we stop capturing the events, to check in the very next line if there are no events recorded. Because if there were any VTs pinned, we shall see the events in <code>jfrEvents.events()<\/code>.<\/p>\n<p>Luckily, we don&rsquo;t encounter any, if you simply checkout <a href=\"https:\/\/github.com\/pioorg\/DeepDiveJava19\/\">the demo project<\/a> from GitHub. However, if you decide to play a bit and e.g. turn the <a href=\"https:\/\/github.com\/pioorg\/DeepDiveJava19\/blob\/5d856c18ed8d7545d961c75f74ef9b45d6b4e76d\/concurrency\/src\/main\/java\/org\/przybyl\/ddj19\/concurrency\/virtThreads\/GreetingObtainer.java#L25\"><code>getGreeting(...)<\/code><\/a> method into a <code>synchronized<\/code> one, such a test should tell us that we&rsquo;re misusing Virtual Threads by pinning them.<\/p>\n<p>That&rsquo;s all for now. And yes, I understand this approach has certain flaws, so please stay tuned for the <a href=\"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/loom\/testing-pinned-virtual-threads\/\">next post<\/a>.<\/p>\n"},{"title":"Sailing Modern Java","link":"https:\/\/softwaregarden.dev\/en\/talks\/sailing-modern-java\/","pubDate":"Mon, 21 Nov 2022 10:00:00 +0200","guid":"https:\/\/softwaregarden.dev\/en\/talks\/sailing-modern-java\/","description":"<p>When I have time to talk about Java for more than one hour, it&rsquo;s a Deep Dive (I call it &ldquo;What&rsquo;s new and noteworthy?&rdquo;)\nWhen I have less than forty minutes, we can barely touch the surface, hence it&rsquo;s called then &ldquo;Surfing Modern Java&rdquo;.\nAnything in between, like regular-size talk, is more than surfing, but less than deep dive, hence &ldquo;Sailing Modern Java&rdquo;.<\/p>\n<p>For such a talk I usually cover one or two latest releases, sometimes mentioning what&rsquo;s ahead of us, trying to sneak in as many code demos as I can.<\/p>\n<p>An abstract may look like this:<\/p>\n<p>Another (half a) year has passed, another major Java\u2122 version has been released. Java was supposed &rsquo;to be slow&rsquo;. However, Java turns out to evolve so fast, that next releases aren&rsquo;t just version bumps, but might significantly change the rules of the game. That&rsquo;s a good reason to check out what&rsquo;s new in Java. We&rsquo;re going to cover some features of Java 21:<\/p>\n<ul>\n<li>Virtual Threads,<\/li>\n<li>Pattern Matching for switch,<\/li>\n<li>Record Patterns,<\/li>\n<li>Structured Concurrency,<\/li>\n<li>String Templates,<\/li>\n<li>what&rsquo;s gone and what will be gone,<\/li>\n<li>and other stuff.<\/li>\n<\/ul>\n<p>So far I had the pleasure to give this talk e.g. at <a href=\"https:\/\/devoxx.pl\/\">Devoxx Poland<\/a>, <a href=\"https:\/\/geecon.cz\">GeeCON Prague<\/a>,  VirtualJUG, PentaBar and quite a few others.<\/p>\n<div style=\"position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;\">\n      <iframe allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen\" loading=\"eager\" referrerpolicy=\"strict-origin-when-cross-origin\" src=\"https:\/\/www.youtube-nocookie.com\/embed\/Cs0WuE7Psu8?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0\" style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;\" title=\"YouTube video\"><\/iframe>\n    <\/div>\n\n<p><code> <\/code><\/p>\n<div style=\"position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;\">\n      <iframe allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen\" loading=\"eager\" referrerpolicy=\"strict-origin-when-cross-origin\" src=\"https:\/\/www.youtube-nocookie.com\/embed\/aiNn5a1OjoY?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0\" style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;\" title=\"YouTube video\"><\/iframe>\n    <\/div>\n\n"},{"title":"Testing Virtual Threads","link":"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/loom\/testing-virtual-threads\/","pubDate":"Wed, 02 Nov 2022 21:00:00 +0100","guid":"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/loom\/testing-virtual-threads\/","description":"<p>Let&rsquo;s be honest: we&rsquo;ve been waiting for the Virtual Threads quite some time. We&rsquo;ve been waiting eagerly, we&rsquo;ve seen names changing (they&rsquo;re not <em>fibers<\/em> folks), but here there finally are: Virtual Threads.<\/p>\n<p>Some say the Project Loom is the biggest change Java has seen since version 8, lambdas, and streams. Some say it&rsquo;s even bigger than that. Discussion aside, they are a huge change, it seems.<\/p>\n<p>I remember how we were excited (I was still at the university back then), that we could finally use some real Threads in Java on Windows. Yet time flies by, the industry has changed, the hardware has changed, the way we build our systems has changed too. While we found ways to bypass the limitations of &ldquo;one OS thread per one Java thread&rdquo;, it came with some price: convoluted stack traces and difficult debugging are the first ones that come to mind. Virtual Threads are about to keep us in the boooring, yet easy to grasp thread-per-request model, while unblocking the silicon power down below.<\/p>\n<p>I&rsquo;m not sure if using Virtual Threads as &ldquo;just threads&rdquo; is the recommended approach. The structured concurrency might be a better way (just like executors were better than &ldquo;just threads&rdquo;), yet sometimes there&rsquo;s a need to use simply a thread. And in such situations Virtual Threads should be as easy to use as the good ol&rsquo; Platform Threads we know for years. (And which BTW aren&rsquo;t going anywhere!)<\/p>\n<p>I could have nicely rephrased stuff from <a href=\"https:\/\/openjdk.org\/jeps\/425\">JEP-425<\/a> for this post. Instead, I think it&rsquo;s better to recommend reading the source material and then&hellip; test if we get it right. Because tests are not only about verifying the system, but maybe (even predominantly) how we understand how the system works. And since I&rsquo;ve already done that, perhaps you&rsquo;d like to see how Virtual Threads can be constructed and handled. Also, to answer questions I get asked at conferences: are <code>ThreadLocal<\/code>s supported, can I set priorities or make VirtualThreads non-daemon. All because &ldquo;talk is cheap, show me the code!&rdquo;<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">22<\/span><span><span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">VirtThreadsDiffTest<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">23<\/span><span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">24<\/span><span>    Thread thread <span style=\"color:#f92672\">=<\/span> Thread.<span style=\"color:#a6e22e\">ofVirtual<\/span>().<span style=\"color:#a6e22e\">unstarted<\/span>(() <span style=\"color:#f92672\">-&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">25<\/span><span>    });\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">26<\/span><span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">27<\/span><span>    <span style=\"color:#a6e22e\">@Test<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">28<\/span><span>    <span style=\"color:#66d9ef\">void<\/span> <span style=\"color:#a6e22e\">shouldThrowExceptionsForUnsupportedMethods<\/span>() {\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">29<\/span><span>        assertThrows(UnsupportedOperationException.<span style=\"color:#a6e22e\">class<\/span>, () <span style=\"color:#f92672\">-&gt;<\/span> thread.<span style=\"color:#a6e22e\">stop<\/span>());\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">30<\/span><span>        assertThrows(UnsupportedOperationException.<span style=\"color:#a6e22e\">class<\/span>, () <span style=\"color:#f92672\">-&gt;<\/span> thread.<span style=\"color:#a6e22e\">suspend<\/span>());\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">31<\/span><span>        assertThrows(UnsupportedOperationException.<span style=\"color:#a6e22e\">class<\/span>, () <span style=\"color:#f92672\">-&gt;<\/span> thread.<span style=\"color:#a6e22e\">resume<\/span>());\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">32<\/span><span>        assertThrows(IllegalArgumentException.<span style=\"color:#a6e22e\">class<\/span>, () <span style=\"color:#f92672\">-&gt;<\/span> thread.<span style=\"color:#a6e22e\">setDaemon<\/span>(<span style=\"color:#66d9ef\">false<\/span>));\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">33<\/span><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">34<\/span><span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">35<\/span><span>    <span style=\"color:#a6e22e\">@Test<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">36<\/span><span>    <span style=\"color:#66d9ef\">void<\/span> <span style=\"color:#a6e22e\">shouldOnlyBeDaemon<\/span>() {\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">37<\/span><span>        thread.<span style=\"color:#a6e22e\">setDaemon<\/span>(<span style=\"color:#66d9ef\">true<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">38<\/span><span>        assertTrue(thread.<span style=\"color:#a6e22e\">isDaemon<\/span>());\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">39<\/span><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">40<\/span><span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">41<\/span><span>    <span style=\"color:#a6e22e\">@Test<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">42<\/span><span>    <span style=\"color:#66d9ef\">void<\/span> <span style=\"color:#a6e22e\">shouldAlwaysHaveNormalPriority<\/span>() {\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">43<\/span><span>        thread.<span style=\"color:#a6e22e\">setPriority<\/span>(Thread.<span style=\"color:#a6e22e\">MAX_PRIORITY<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">44<\/span><span>        assertEquals(Thread.<span style=\"color:#a6e22e\">NORM_PRIORITY<\/span>, thread.<span style=\"color:#a6e22e\">getPriority<\/span>());\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">45<\/span><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">46<\/span><span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">47<\/span><span>    <span style=\"color:#a6e22e\">@Test<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">48<\/span><span>    <span style=\"color:#66d9ef\">void<\/span> <span style=\"color:#a6e22e\">shouldSuportThreadLocalVariablesByDefault<\/span>() <span style=\"color:#66d9ef\">throws<\/span> InterruptedException {\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">49<\/span><span>        <span style=\"color:#66d9ef\">var<\/span> tl <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> ThreadLocal<span style=\"color:#f92672\">&lt;<\/span>Integer<span style=\"color:#f92672\">&gt;<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">50<\/span><span>        Thread.<span style=\"color:#a6e22e\">startVirtualThread<\/span>(() <span style=\"color:#f92672\">-&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">51<\/span><span>            assertNull(tl.<span style=\"color:#a6e22e\">get<\/span>());\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">52<\/span><span>            tl.<span style=\"color:#a6e22e\">set<\/span>(42);\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">53<\/span><span>            assertEquals(42, tl.<span style=\"color:#a6e22e\">get<\/span>());\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">54<\/span><span>        }).<span style=\"color:#a6e22e\">join<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">55<\/span><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">56<\/span><span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">57<\/span><span>    <span style=\"color:#a6e22e\">@Test<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">58<\/span><span>    <span style=\"color:#66d9ef\">void<\/span> <span style=\"color:#a6e22e\">shouldAllowOptOutFromThreadLocal<\/span>() <span style=\"color:#66d9ef\">throws<\/span> InterruptedException {\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">59<\/span><span>        <span style=\"color:#66d9ef\">var<\/span> tl <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> ThreadLocal<span style=\"color:#f92672\">&lt;<\/span>Integer<span style=\"color:#f92672\">&gt;<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">60<\/span><span>        Thread.<span style=\"color:#a6e22e\">ofVirtual<\/span>().<span style=\"color:#a6e22e\">allowSetThreadLocals<\/span>(<span style=\"color:#66d9ef\">false<\/span>).<span style=\"color:#a6e22e\">start<\/span>(() <span style=\"color:#f92672\">-&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">61<\/span><span>            assertThrows(UnsupportedOperationException.<span style=\"color:#a6e22e\">class<\/span>, () <span style=\"color:#f92672\">-&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">62<\/span><span>                tl.<span style=\"color:#a6e22e\">set<\/span>(17);\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">63<\/span><span>            });\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">64<\/span><span>        }).<span style=\"color:#a6e22e\">join<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">65<\/span><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">66<\/span><span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">67<\/span><span>    <span style=\"color:#a6e22e\">@Test<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">68<\/span><span>    <span style=\"color:#66d9ef\">void<\/span> <span style=\"color:#a6e22e\">shouldSupportInheritableThreadLocal<\/span>() <span style=\"color:#66d9ef\">throws<\/span> InterruptedException {\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">69<\/span><span>        <span style=\"color:#66d9ef\">var<\/span> itl <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> InheritableThreadLocal<span style=\"color:#f92672\">&lt;<\/span>Integer<span style=\"color:#f92672\">&gt;<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">70<\/span><span>        Thread.<span style=\"color:#a6e22e\">startVirtualThread<\/span>(() <span style=\"color:#f92672\">-&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">71<\/span><span>            itl.<span style=\"color:#a6e22e\">set<\/span>(33);\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">72<\/span><span>            Thread.<span style=\"color:#a6e22e\">startVirtualThread<\/span>(() <span style=\"color:#f92672\">-&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">73<\/span><span>                assertEquals(33, itl.<span style=\"color:#a6e22e\">get<\/span>());\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">74<\/span><span>            });\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">75<\/span><span>        }).<span style=\"color:#a6e22e\">join<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">76<\/span><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">77<\/span><span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">78<\/span><span>    <span style=\"color:#a6e22e\">@Test<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">79<\/span><span>    <span style=\"color:#66d9ef\">void<\/span> <span style=\"color:#a6e22e\">shouldSupportOptingOutInheritableThreadLocal<\/span>() <span style=\"color:#66d9ef\">throws<\/span> InterruptedException {\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">80<\/span><span>        <span style=\"color:#66d9ef\">var<\/span> itl <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> InheritableThreadLocal<span style=\"color:#f92672\">&lt;<\/span>Integer<span style=\"color:#f92672\">&gt;<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">81<\/span><span>        Thread.<span style=\"color:#a6e22e\">startVirtualThread<\/span>(() <span style=\"color:#f92672\">-&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">82<\/span><span>            itl.<span style=\"color:#a6e22e\">set<\/span>(33);\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">83<\/span><span>            Thread.<span style=\"color:#a6e22e\">ofVirtual<\/span>().<span style=\"color:#a6e22e\">inheritInheritableThreadLocals<\/span>(<span style=\"color:#66d9ef\">false<\/span>).<span style=\"color:#a6e22e\">start<\/span>(() <span style=\"color:#f92672\">-&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">84<\/span><span>                assertNull(itl.<span style=\"color:#a6e22e\">get<\/span>());\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">85<\/span><span>            });\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">86<\/span><span>        }).<span style=\"color:#a6e22e\">join<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">87<\/span><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">88<\/span><span>}<\/span><\/span><\/code><\/pre><\/div>\n<figure class=\"image image right\">\n<img src=\"needle-threads.jpg\" alt=\"Threads, threads, threads!\" width=\"640\">\n<\/figure>\n\n<p>Do I like the builder approach? Boy, I love it ;-)\nSure, this is the very first preview of the project Loom in Java (as a preview feature). Things might change. When are we going to see it as a standard feature? I can&rsquo;t tell, I can only hope everyone will take their time to give it enough testing and love. It&rsquo;s better to wait longer, than end up with some perhaps not-so-fortunate decisions (I&rsquo;m looking at you, <a href=\"https:\/\/docs.oracle.com\/en\/java\/javase\/19\/docs\/api\/java.base\/java\/util\/Optional.html#get()\"><code>Optional.get<\/code><\/a> ;-)<\/p>\n<p>The code above comes from my <a href=\"https:\/\/github.com\/pioorg\/DeepDiveJava19\/blob\/main\/concurrency\/src\/test\/java\/org\/przybyl\/ddj19\/concurrency\/VirtThreadsDiffTest.java\">DeepDiveJava19<\/a> project, should you be interested in running more examples.<\/p>\n<p>Stay tuned!<\/p>\n<p>PS. Mandatory picture of some random threads has been added. Apparently, not having one while talking about project Loom, is seen &ldquo;unprofessional&rdquo; by some ;-)<\/p>\n"},{"title":"Java 18 & 19. What's new and noteworthy??","link":"https:\/\/softwaregarden.dev\/en\/talks\/java-18-19-new-and-noteworthy\/","pubDate":"Wed, 12 Oct 2022 10:00:00 +0200","guid":"https:\/\/softwaregarden.dev\/en\/talks\/java-18-19-new-and-noteworthy\/","description":"<p>Hey, there are two major Java versions released every year! We don\u2019t have to wait 3 years or so for new features anymore. Isn\u2019t that cool? \ud83d\ude09<\/p>\n<p>Java was supposed &ldquo;to be slow&rdquo;. However, Java turns out to evolve so fast, that next releases aren&rsquo;t just version bumps, but might significantly change the rules of the game. That&rsquo;s a good reason to check out what&rsquo;s new in Java.<\/p>\n<p>To name a few changes:<\/p>\n<ul>\n<li>Pattern Matching for switch,<\/li>\n<li>Record Patterns,<\/li>\n<li>Virtual Threads,<\/li>\n<li>Calling native stuff,<\/li>\n<li>Simple Web server,<\/li>\n<li>what&rsquo;s gone and what will be gone,<\/li>\n<li>and other stuff.<\/li>\n<\/ul>\n<p>If you find them interesting, let\u2019s dive deep together into new interesting stuff.<\/p>\n<p>So far I had the pleasure to give this talk at <a href=\"https:\/\/devoxx.be\/\">Devoxx Belgium<\/a>. Doing that the morning after a very intensive 3h workshop the evening before wasn&rsquo;t something I&rsquo;m planning to do again, but it had its own pros and cons ;-)<\/p>\n<div style=\"position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;\">\n      <iframe allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen\" loading=\"eager\" referrerpolicy=\"strict-origin-when-cross-origin\" src=\"https:\/\/www.youtube-nocookie.com\/embed\/O4MudYN2axA?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0\" style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;\" title=\"YouTube video\"><\/iframe>\n    <\/div>\n\n"},{"title":"Go Go Java Developer","link":"https:\/\/softwaregarden.dev\/en\/talks\/go-go-java-developer\/","pubDate":"Wed, 13 Jul 2022 10:00:00 +0200","guid":"https:\/\/softwaregarden.dev\/en\/talks\/go-go-java-developer\/","description":"<p>&ldquo;You can never understand one language until you understand at least two.&rdquo; \u2013 Geoffrey Willans<\/p>\n<p>For years, I\u2019ve been developing mostly in JVM languages. Sometimes in other C-derived languages, which was both cool and easy.<\/p>\n<p>A few months ago (due to a career shift) I had to learn Go rapidly. While technically Go has keywords looking similar to C, many things are simply different and even unheard of in C-based OOP languages. Learning Go is a great journey and the best are these AH-HA moments, when doing things in Go I suddenly understood Java better.<\/p>\n<p>Sure, during a single talk I won\u2019t teach you Go. Thing is: I don\u2019t event want to, as all I want is to show you some concepts in Go which can help you (just as they helped me) become better Java developer and understand why we need projects Valhalla and Panama. It\u2019s about leaving our comfort zone to get\u2026 more comfort.<\/p>\n<p>I was able to give this talk at VoxxedDays Bucharest, Devoxx UK, Devoxx Poland.<\/p>\n<p>Online:\n<div style=\"position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;\">\n      <iframe allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen\" loading=\"eager\" referrerpolicy=\"strict-origin-when-cross-origin\" src=\"https:\/\/www.youtube-nocookie.com\/embed\/oxMC_183plE?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0\" style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;\" title=\"YouTube video\"><\/iframe>\n    <\/div>\n<\/p>\n<p>Offline:\n<div style=\"position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;\">\n      <iframe allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen\" loading=\"eager\" referrerpolicy=\"strict-origin-when-cross-origin\" src=\"https:\/\/www.youtube-nocookie.com\/embed\/qYAHRud98Ek?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0\" style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;\" title=\"YouTube video\"><\/iframe>\n    <\/div>\n<\/p>\n"},{"title":"(mis)using modern Java","link":"https:\/\/softwaregarden.dev\/en\/talks\/misusing-modern-java\/","pubDate":"Sat, 06 Nov 2021 10:00:00 +0200","guid":"https:\/\/softwaregarden.dev\/en\/talks\/misusing-modern-java\/","description":"<p>Modern Java is really awesome when it comes to \u201cHello, World!\u201d demos. It\u2019s also cool for a sophisticated systems and algorithms, provided their authors write code which obeys a few fairly simple contracts and avoids obvious traps.<\/p>\n<p>There are a few mantras regarding recent features of modern Java, such as:<\/p>\n<ul>\n<li>records can replace JavaBeans everywhere<\/li>\n<li>you never need to write <code>hashCode()<\/code> for records<\/li>\n<li>pattern matching with <code>instanceof<\/code> is the best tool for <code>equals()<\/code><\/li>\n<li>just ignore <code>--illegal-access<\/code> and set it to <code>permit<\/code><\/li>\n<li><code>synchronize (new Long(42))<\/code> is the best for monitoring and so on.<\/li>\n<\/ul>\n<p>This talk has been given at jLove, Doing Java Better and Java Day Lviv.<\/p>\n<p>No recording in English published so far.<\/p>\n"},{"title":"Java 16 & 17. What's new and noteworthy??","link":"https:\/\/softwaregarden.dev\/en\/talks\/java-17-new-and-noteworthy\/","pubDate":"Tue, 12 Oct 2021 10:00:00 +0200","guid":"https:\/\/softwaregarden.dev\/en\/talks\/java-17-new-and-noteworthy\/","description":"<p>Another (half a) year has passed, another major Java\u2122 version has been released.\nJava was supposed &ldquo;to be slow&rdquo;. However, Java turns out to evolve so fast, that next releases aren&rsquo;t just version bumps, but might significantly change the rules of the game. That&rsquo;s a good reason to check out what&rsquo;s new in Java.\nWe&rsquo;re going to cover:<\/p>\n<ul>\n<li>Records, where and how to use them, apart from DTO\/VO<\/li>\n<li>Pattern matching with instanceof A.K.A. Smart casting<\/li>\n<li>Sealed classes, new dimension of types extensibility (for inheritance)<\/li>\n<li>Warnings from Jigsaw (&ndash;illegal-access strikes back!)<\/li>\n<li>And Valhalla (for value-based classes abuse)<\/li>\n<li>Talking to native stuff from Panama<\/li>\n<li>and more.<\/li>\n<\/ul>\n<p>All visualised in actual code, not just slides.<\/p>\n<p>I was able to talk on Java 16 and 17 for more almost 3 hours at <a href=\"https:\/\/www.devoxx.fr\/\">Devoxx France<\/a> and also at <a href=\"http:\/\/2022.devoxx.pl\/speakers\/speaker-details%3Fid=6201.html\">Devoxx Poland<\/a> (but the video hasn&rsquo;t been released yet.)\n<div style=\"position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;\">\n      <iframe allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen\" loading=\"eager\" referrerpolicy=\"strict-origin-when-cross-origin\" src=\"https:\/\/www.youtube-nocookie.com\/embed\/wUinQWbTdFE?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0\" style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;\" title=\"YouTube video\"><\/iframe>\n    <\/div>\n<\/p>\n"},{"title":"What do I think about Lombok?","link":"https:\/\/softwaregarden.dev\/en\/posts\/varia\/what-i-think-about-lombok\/","pubDate":"Thu, 10 Jun 2021 14:00:00 +0200","guid":"https:\/\/softwaregarden.dev\/en\/posts\/varia\/what-i-think-about-lombok\/","description":"<p>What do I think about Lombok?<\/p>\n<p>I think it&rsquo;s a nice island, and I wish to visit it one day.<\/p>\n<p>What do I think about Project Lombok?<\/p>\n<p>Well, I&rsquo;ve been asked this question so many times, I&rsquo;ve decided to write this post. Its main purpose is to be able to paste the link and back up, because the (yet another) discussion might be so intensive, that fists will be shaken and heads will roll&hellip; There are three assumptions here:<\/p>\n<ul>\n<li>These are my opinions. You may or may not like them. It&rsquo;s up to you and I can&rsquo;t help it. If you find familiarising with someone&rsquo;s opinions disturbing, maybe it&rsquo;s time to stop reading. This includes (but it&rsquo;s not limited to) all magnificent souls behind Project Lombok.<\/li>\n<li>In Poland, we say &lsquo;only a cow doesn&rsquo;t change its mind&rsquo;, and since I don&rsquo;t identify myself as a cow, my opinions may change. E.g., because your read them and convinced me I was wrong. Trust me, I like to be enlightened that I was wrong. I find this as an absolute foundation of scientific approach. Therefore, this entry is a subject to change without prior notice.<\/li>\n<li>I&rsquo;ll keep referring to &ldquo;Project Lombok&rdquo; as simply &ldquo;Lombok&rdquo;.<\/li>\n<\/ul>\n<h3 id=\"where-do-i-know-lombok-from\">Where do I know Lombok from?<\/h3>\n<p>I first heard about Lombok during Hamlet D&rsquo;Arcy&rsquo;s talk, which AFAIR was in Cracow like 10 years ago or so, so it must have been GeeCON or 33rd Degree (now known as Devoxx Poland).\nMore or less at the same time (or maybe a bit earlier) I started familiarising myself with Scala. Like, you know, <code>case class<\/code>es, generated accessors, <code>@BeanProperty<\/code>, and the like.<\/p>\n<p>And I was impressed, that&rsquo;s what I remember for sure. That in Java we can also have some trivia generated for us.<\/p>\n<p>It took some time before I saw that in real production code. I saw it here and there, I used that in a few projects over few years, so now I dare to consider myself as an ordinary Java dev who saw how the tool performs in combat.<\/p>\n<h3 id=\"tool-not-a-lib\">Tool? Not a lib?<\/h3>\n<p>Precisely. From my point of view Lombok is not exactly a library.\nI like the informal distinction between libraries and frameworks (which I think I&rsquo;ve heard for the first time from Dr. Venkat Subramaniam) that relationship with a library is easier to break than with a framework, just as it&rsquo;s easier to swap girlfriends than wives. In theory, we should be able to replace one library with another one, provided it&rsquo;s doing more or less the same, especially when they implement the same interfaces (although being equally functional many times is enough). To some extent we can say that about e.g. Apache Commons and Google Guava, or some logging libraries. Frameworks OTOH are significantly different to get swapped or rid off, e.g. when was the last time when you replaced Spring Framework with Quarkus or Micronaut in a project with some history? Exactly, it&rsquo;s also doable (like everything in IT, having enough time and money), but it&rsquo;s not something we frequently do, because the thing leaked literally everywhere.<\/p>\n<p>Many of us like to think that our external dependencies can only be libraries or frameworks. Quite like people years ago wanted mushrooms to be either animals or plants. World, I&rsquo;m afraid, might not be that simple and because of that there&rsquo;s not only <em>fauna<\/em> and <em>flora<\/em> around us, but <em>fungi<\/em> as well. (Guess what, now we have three more <a href=\"https:\/\/en.wikipedia.org\/wiki\/Kingdom_(biology)\">kingdoms<\/a>.)<\/p>\n<p>I think that Lombok, despite having some libraries&rsquo; properties, is not strictly speaking a library. Can you name other two Java libraries which (make sure all are checked):<\/p>\n<ul>\n<li>rely on (pre-)compiler&rsquo;s plugins<\/li>\n<li>aren&rsquo;t easy to work with if you don&rsquo;t have an IDE plugin installed<\/li>\n<li>freakuently stop working with new releases of JDK, IDE, etc.<\/li>\n<li>spread to all layers of your architecture?<\/li>\n<\/ul>\n<p>That&rsquo;s my point. I don&rsquo;t know if the term &ldquo;tool&rdquo; is the best one, but since I don&rsquo;t quite enjoy using &ldquo;gizmo&rdquo; or &ldquo;wichajster&rdquo;, let me use that term. We might come up with another one, if we find a better name. What I want to stress here, is that IMHO it&rsquo;s not true to say &lsquo;Lombok is (yet another) library&rsquo;. Taking its prerequisites into account, and the effort to get rid of it from any mature project (I&rsquo;m thinking about Testcontainers here ;-) ), it&rsquo;s not that librarish at all, despite being an innocent single entry in your POM file.<\/p>\n<h3 id=\"lombok-is-easy-peasy\">Lombok is easy-peasy<\/h3>\n<p>Lombok might seem easy after you watch a demo or live coding session given by one of professional Developer Advocates. Little annotation here, another one there, et voil\u00e0, we saved a lot of key-strokes. Question is: what had we sacrificed to get this easiness?<\/p>\n<ul>\n<li>Have you seen this demo opened by someone else in their IDE (even as source bundle for RTFM) without the IDE plugin?<\/li>\n<li>Have you seen them carefully selecting versions of JDK, IDE, Lombok and Gradle to make sure the Demo Gods are satisfied?<\/li>\n<li>Do you think anyone has tried to upgrade this little demo across these versions (well, if you wish, you can try to upgrade my little demo for <a href=\"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/records\/vs-lombok\/\">records&rsquo; torture<\/a> to the newest Java and Lombok&hellip;))? Just instead of rolling it back before next talk?<\/li>\n<li>Have you ever tried mixed build with other languages?<\/li>\n<\/ul>\n<h3 id=\"lombok-is-darn-hard-and-banned\">Lombok is darn hard and banned<\/h3>\n<p>&lsquo;We can&rsquo;t allow Lombok, because new junior members constantly broke things by using <code>@Data<\/code>!&rsquo; Oh boy, how many times did I hear it? Now, my question is: how many times did your junior members broke things up because they clicked-this-then-that and generated incorrect <code>equals<\/code> or <code>hashCode<\/code> in IDE wizard? Or worse, added some fields but forgot to re-generate these methods? What if you&rsquo;ll end-up with bugs due to <a href=\"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/records\/should-write-equals-and-hashcode\/\">default implementations in records<\/a>? Will you keep blaming these other tools, instead of sheer human incompetence? What about universities\/bootcamps\/trainers, will you blame them for not teaching the absolute Java 101, that is: when, how and WHY write <code>equals<\/code> and <code>hashCode<\/code>?<\/p>\n<h3 id=\"go-kotlinscala\">Go Kotlin\/Scala<\/h3>\n<p>Yeah, been there, saw that. I think we&rsquo;re going back to the previous point, because (whether you like it or not) they&rsquo;re still running on JVM. Besides, think of the codebase from company&rsquo;s or manager&rsquo;s point of view and stretch it to the total life span: employing decent Java developer might not be so easy. Do you think hiring Kotlin\/Scala devs is easier or harder? Or do you really think doing such a drastic change like choosing a new language is justified, &lsquo;because Lombok&rsquo;? Don&rsquo;t get me wrong, whenever I see point in going multi-lang projects I vote for that change, but software product is not only about choosing language or dependencies, there&rsquo;s a bigger perspective in space-time.<\/p>\n<h3 id=\"not-worth-the-trouble\">Not worth the trouble<\/h3>\n<p>Could I answer in any other way than &lsquo;it depends&rsquo;?\nThere are pros and cons for literally everything in IT (except &ldquo;Hello World!&rdquo;). So the answer, I think, is quite simple here: if you know the cost of using Lombok, and it&rsquo;s significantly less than not using it, why not use it? After all, it&rsquo;s just a tool. Question is: do you really know the cost of using Lombok in the very project you&rsquo;re in? Not that &lsquo;I suspect&hellip;&rsquo; or &lsquo;I heard&hellip;&rsquo;, or &lsquo;Everyone knows &hellip;&rsquo; I mean the actual consequences.<\/p>\n<h3 id=\"lombok-is-lombok\">Lombok is Lombok<\/h3>\n<p>It may sound trivial, but I really think Lombok is the one and only of its kind in Java ecosystem.<\/p>\n<p>It&rsquo;s powerful, but with power comes responsibility. There might be a reason why we don&rsquo;t let our children drive monster trucks, or even our regular cars, and instead give them these little RC ones&hellip; It&rsquo;s because a modern automobile is still a complicated piece of machinery even to drive, not to mention maintenance.<\/p>\n<p>Lombok is not a toy, it&rsquo;s a sophisticated tool, and as such should be used by qualified personnel to make sure it doesn&rsquo;t do more harm than good. This is, I think, one of the biggest failures of our community: hiding complexity, so naive and junior souls can think &lsquo;it just works&rsquo; or &lsquo;it&rsquo;s magic, don&rsquo;t worry&rsquo;. Due to all these single-use demos it looks innocent and always safe, but it&rsquo;s not. In hands of untrained person it may turn into destruction tool sometimes.<\/p>\n<p>How do I define trained person, when it comes to Lombok? Well, I see some stages:<\/p>\n<ol>\n<li>someone knows, that Lombok is cool,<\/li>\n<li>someone knows, that Lombok has documentation,<\/li>\n<li>someone read the documentation,<\/li>\n<li>someone understood the documentation,<\/li>\n<li>someone verified they understand the documentation by checking the &ldquo;deLomboked&rdquo; source code,<\/li>\n<li>someone verified they understand the documentation by checking the generated byte-code.<\/li>\n<\/ol>\n<p>Why do I say about verifying using byte-code? Well, maybe because (surprise, surprise) what Lombok does is manipulating byte-code.<\/p>\n<figure class=\"image image right\">\n<img src=\"rock-4671055_640.jpg\" alt=\"Road and cliffs\" width=\"550\">\n<\/figure>\n\n<p>This is how I see Lombok. A very powerful (thus potentially dangerous) tool, which usage should be verified and approved by Stage 6 specialist, carefully comparing benefits to the cost, and constantly mentoring less experienced team members.\nSomeone who knows by heart, that if they write <code>@AnnotationA<\/code> in position X, certain byte code will be generated and thus certain behaviour will kick in. And if the <code>@AnnotationB<\/code> will be used, or the <code>@AnnotationA<\/code> will receive a parameter, or will be moved to position Y, other things will happen. From that perspective Lombok is just a copy-and-paste thing. However, it takes effort to get there.<\/p>\n<p>Beware of advisors, who tell you that you can take a nice, free and safe shortcut to avoid all bumps and efforts.<\/p>\n<p>Picture by <a href=\"https:\/\/pixabay.com\/pl\/users\/dimitrisvetsikas1969-1857980\/?utm_source=link-attribution&amp;utm_medium=referral&amp;utm_campaign=image&amp;utm_content=4671055%22\">Dimitris Vetsikas<\/a>.<\/p>\n"},{"title":"Are you ready for Valhalla?","link":"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/ready-for-valhalla\/","pubDate":"Thu, 27 May 2021 14:00:00 +0200","guid":"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/ready-for-valhalla\/","description":"<p>Many features and changes we see coming live in new Java version (if not most of them) are developed under so-called umbrella projects. We frequently see syntax improvements from project Amber, project Jigsaw is about bringing modules, project Loom (surprise, surprise) is about new threads, project Panama roughly speaking is about using native stuff safely and efficiently, and among the most known ones, project Valhalla starts to become a thing, thanks to <a href=\"https:\/\/openjdk.java.net\/jeps\/390\">JEP-390<\/a> being included in Java 16.<\/p>\n<p>From my point of view (and you don&rsquo;t have to agree with me), JEP-390 is similar in its nature to <a href=\"https:\/\/openjdk.java.net\/jeps\/390\">JEP-396<\/a>, which I described in <a href=\"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/illegal-access-in-java-16\/\">the previous installment<\/a>. What makes is totally different though, is timing.<\/p>\n<p>As we know, JPMS (Java Platform Module System), consisting of many JEPs and JSRs, saw the daylight officially with Java 9, being postponed for a few years. When we saw it, it was also accompanied by the <code>illegal access<\/code> warnings too, only we got a combo: actual change and actual warning at the same time, in the very same release. Of course, we witness now the warning (and violations of OOP) changing in Java 16 and (most probably) Java 17, but there was no official warning emitted, neither by <code>javac<\/code>, nor by JVM, in any release before.<\/p>\n<p>Compared to that, project Valhalla reaches GA differently. We see some warnings first, giving us chance and time to prepare for the core Valhalla&rsquo;s changes going live. Project Valhalla (and this is a gross oversimplification, my friends) is about allowing us creating value-based objects, i.e. objects which in a way are like primitive types we have in Java. To give you an example, when we have an array of, let&rsquo;s say, one million objects packed into an array, do we really need all of them to have their unique header, if all of them have exactly the same header, and we don&rsquo;t use a single object for synchronization? Maybe these objects could be more int-ish in their nature then? So we give up identity of these objects (which we don&rsquo;t use anyway) to favour performance? That&rsquo;s what more or less about it: about giving us opportunity to create objects where we care only about their value, hence <em>value-based<\/em>.<\/p>\n<p>It turns out that there might be quite a few classes that should be used only for the value stored inside their objects and that they should be more like <em>primitive pieces of data<\/em>, despite not being defined as one of the <a href=\"https:\/\/docs.oracle.com\/javase\/tutorial\/java\/nutsandbolts\/datatypes.html\"><em>primitive data types<\/em><\/a>.<\/p>\n<p>There&rsquo;s a nice description of the expected properties of a <a href=\"https:\/\/docs.oracle.com\/en\/java\/javase\/16\/docs\/api\/java.base\/java\/lang\/doc-files\/ValueBased.html\"><em>value-based class<\/em><\/a>, I really suggest reading it, as the definition changed slightly over recent releases.<\/p>\n<h3 id=\"whats-a-value-based-class-actually\">What&rsquo;s a <em>value-based class<\/em> actually?<\/h3>\n<p>[Update: I also covered this in the part one of <a href=\"https:\/\/softwaregarden.dev\/en\/talks\/java-16-new-and-noteworthy\/\">Java 16. What&rsquo;s new and noteworthy<\/a>.]<\/p>\n<p>Currently, these are all classes annotated with <code>jdk.internal.@ValueBased<\/code>. Examples are:<\/p>\n<ul>\n<li><code>java.lang.{Byte, Short, Integer, Long, Float, Double, Boolean, Character}<\/code><\/li>\n<li><code>java.util.{Optional, OptionalDouble, ...}<\/code><\/li>\n<li><code>java.time.{Instant, ZonedDateTime, Duration, ...}<\/code><\/li>\n<li>implementations of results returned by methods like <code>List.of(), List.copyOf(), Set.of(), ..., Map.entry()<\/code><\/li>\n<\/ul>\n<p>If we simplify things again, we could say about such classes, that their objects should be created using factory methods (not constructors), and they give up their identity (being able to be compared using <code>==<\/code> or used in <code>synchronized<\/code> clause), to rely solely on equality (using <code>equals()<\/code>) in Java. Thanks to all of that and being immutable, the objects\/instances can be freely replaced one by another, something similar to what we have with <code>-XX:+UseStringDeduplication<\/code>.<\/p>\n<p>Let&rsquo;s check some real examples to see what these changes are all about and how to detect violations during compilation and during runtime.<\/p>\n<h4 id=\"all-constructors-are-deprecatedforremoval--true-now\">All constructors are <code>@Deprecated(forRemoval = true)<\/code> now<\/h4>\n<p>Not that using a constructor for mentioned classes was easy or a good idea anytime in the past, but now if we try to call one directly in our code, we can not only see a warning in an IDE (like a red like striking through), but also a compiler warning:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-text\" data-lang=\"text\"><span style=\"display:flex;\"><span>warning: [removal] Long(long) in Long has been deprecated and marked for removal\n<\/span><\/span><span style=\"display:flex;\"><span>private final static Long aLong = new Long(42);\n<\/span><\/span><span style=\"display:flex;\"><span>                                  ^\n<\/span><\/span><\/code><\/pre><\/div><p>Solution is quite simple: stop calling the constructors, go for direct calls of factory methods, e.g. <code>Long.valueOf(42L)<\/code>, <code>Duration.ofSeconds(15)<\/code> or autoboxing when appropriate.<\/p>\n<h4 id=\"synchronization-attempts-yield-new-synchronization-warning\">Synchronization attempts yield new <code>synchronization<\/code> warning<\/h4>\n<p>Whenever we try in our code to synchronize on an object of <em>value-based class<\/em>, the compiler will warn us using a new warning type, the <code>synchronization<\/code> warning:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-text\" data-lang=\"text\"><span style=\"display:flex;\"><span>warning: [synchronization] attempt to synchronize on an instance of a value-based class\n<\/span><\/span><span style=\"display:flex;\"><span>    synchronized (aLong) {\n<\/span><\/span><span style=\"display:flex;\"><span>    ^\n<\/span><\/span><\/code><\/pre><\/div><p>This one is more tricky, because if your build tools don&rsquo;t happen to be aware of this new type of warning, you might not see this warning at all. E.g. using Maven compiler plugin in version 3.8.1, even when directly enabling all compiler warnings (or just <code>&lt;compilerArg&gt;-Xlint:synchronization&lt;\/compilerArg&gt;<\/code>), this very warning cannot be seen, because using:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-xml\" data-lang=\"xml\"><span style=\"display:flex;\"><span>  <span style=\"color:#f92672\">&lt;plugin&gt;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#f92672\">&lt;artifactId&gt;<\/span>maven-compiler-plugin<span style=\"color:#f92672\">&lt;\/artifactId&gt;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#f92672\">&lt;version&gt;<\/span>3.8.1<span style=\"color:#f92672\">&lt;\/version&gt;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#f92672\">&lt;configuration&gt;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#f92672\">&lt;compilerArgs&gt;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#75715e\">&lt;!--&lt;compilerArg&gt;-Xlint:synchronization&lt;\/compilerArg&gt;--&gt;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#f92672\">&lt;compilerArg&gt;<\/span>-Xlint:all<span style=\"color:#f92672\">&lt;\/compilerArg&gt;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>      <span style=\"color:#f92672\">&lt;\/compilerArgs&gt;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#f92672\">&lt;\/configuration&gt;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#f92672\">&lt;\/plugin&gt;<\/span>\n<\/span><\/span><\/code><\/pre><\/div><p>results only with the previous warning (about using constructor):<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-text\" data-lang=\"text\"><span style=\"display:flex;\"><span>[WARNING] (...)ValueBasedClasses.java:[28,39] Long(long) in java.lang.Long has been deprecated and marked for removal\n<\/span><\/span><span style=\"display:flex;\"><span>[INFO] ------------------------------------------------------------------------\n<\/span><\/span><span style=\"display:flex;\"><span>[INFO] BUILD SUCCESS\n<\/span><\/span><span style=\"display:flex;\"><span>[INFO] ------------------------------------------------------------------------\n<\/span><\/span><\/code><\/pre><\/div><p>Please, be aware of that. Luckily for us, Intellij IDEA marks this okay (thankfully this warning doesn&rsquo;t require indexing, it seems ;-) ).<\/p>\n<h4 id=\"analysing-3rd-party-artifacts\">Analysing 3rd party artifacts<\/h4>\n<p>It might be you don&rsquo;t compile the sources yourself, but instead you&rsquo;re using some JARs provided by or fetched from 3rd party  \/ external vendor. Fear not, then just use <code>jdeprscan<\/code> and Bob&rsquo;s your uncle!<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-text\" data-lang=\"text\"><span style=\"display:flex;\"><span>$ jdeprscan goodies\/target\/goodies-1.0-SNAPSHOT.jar \n<\/span><\/span><span style=\"display:flex;\"><span>Jar file goodies\/target\/goodies-1.0-SNAPSHOT.jar:\n<\/span><\/span><span style=\"display:flex;\"><span>class ValueBasedClasses uses deprecated method java\/lang\/Long::&lt;init&gt;(J)V (forRemoval=true)\n<\/span><\/span><\/code><\/pre><\/div><p>Unfortunately, nothing seems to detect weird calls like<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span>Long.<span style=\"color:#a6e22e\">class<\/span>.<span style=\"color:#a6e22e\">getDeclaredConstructors<\/span>()<span style=\"color:#f92672\">[<\/span>0<span style=\"color:#f92672\">]<\/span>.<span style=\"color:#a6e22e\">newInstance<\/span>(<span style=\"color:#e6db74\">&#34;42&#34;<\/span>);\n<\/span><\/span><\/code><\/pre><\/div><p>but maybe there should be a sane limit in warnings ;-)<\/p>\n<h4 id=\"runtime-detection-of-synchronized\">Runtime detection of <code>synchronized<\/code><\/h4>\n<p>Checking for <code>synchronized(valueObject)<\/code> can also be performed during runtime, which is especially useful for 3rd party code (as it&rsquo;s not picked up by <code>jdeprscan<\/code>). To enable it, your <code>java<\/code> parameters should contain either:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-text\" data-lang=\"text\"><span style=\"display:flex;\"><span>java -XX:+UnlockDiagnosticVMOptions -XX:DiagnoseSyncOnValueBasedClasses=1\n<\/span><\/span><\/code><\/pre><\/div><p>or<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-text\" data-lang=\"text\"><span style=\"display:flex;\"><span>java -XX:+UnlockDiagnosticVMOptions -XX:DiagnoseSyncOnValueBasedClasses=2\n<\/span><\/span><\/code><\/pre><\/div><p>The difference is in the way the JVM will react when synchronization on a value object is detected. <code>DiagnoseSyncOnValueBasedClasses=1<\/code> results in your program instantly going belly up with message:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-text\" data-lang=\"text\"><span style=\"display:flex;\"><span>#  Internal Error (synchronizer.cpp:416), pid=29406, tid=29407\n<\/span><\/span><span style=\"display:flex;\"><span>#  fatal error: Synchronizing on object 0x000000062f2a7bb8 of klass java.lang.Long at ValueBasedClasses.main(ValueBasedClasses.java:32)\n<\/span><\/span><\/code><\/pre><\/div><p>whereas using <code>DiagnoseSyncOnValueBasedClasses=2<\/code> is not fatal (i.e. the program will keep working) and makes each such attempt log a message like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-text\" data-lang=\"text\"><span style=\"display:flex;\"><span>[0,076s][info][valuebasedclasses] Synchronizing on object 0x000000062f2a7818 of klass java.lang.Long\n<\/span><\/span><span style=\"display:flex;\"><span>[0,076s][info][valuebasedclasses] \tat ValueBasedClasses.main(ValueBasedClasses.java:32)\n<\/span><\/span><span style=\"display:flex;\"><span>[0,076s][info][valuebasedclasses] \t- locked &lt;0x000000062f2a7818&gt; (a java.lang.Long)\n<\/span><\/span><\/code><\/pre><\/div><h3 id=\"what-to-do-if-i-see-any-of-these-warnings\">What to do if I see any of these warnings?<\/h3>\n<figure class=\"image image right\">\n<img src=\"viking.png\" alt=\"Happy Viking\" width=\"640\">\n<\/figure>\n\n<p>First I&rsquo;d check if you have the warnings enabled and reported by your build tool and runtime.<\/p>\n<p>Then it&rsquo;s quite simple: stop using constructor and stop using value objects in <code>synchronized<\/code> block, use another object as a monitor, maybe even <code>Object lock = new Object();<\/code><\/p>\n<p>There&rsquo;s no switch (or at least I&rsquo;m not aware of it) that would &ldquo;silence&rdquo; such warnings in the future, like equivalent of <code>--illegal-access=permit<\/code>. And even if there was such a switch, I wouldn&rsquo;t recommend using it.<\/p>\n<p>Because if your code keeps using <em>value-based classes<\/em> in the way causing such warnings, you won&rsquo;t be able to enter Valhalla for eternal glory!<\/p>\n"},{"title":"Illegal access in Java 16 A.K.A. 'My program crashes!'","link":"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/illegal-access-in-java-16\/","pubDate":"Thu, 06 May 2021 14:00:00 +0200","guid":"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/illegal-access-in-java-16\/","description":"<blockquote>\n<p>Roses are red<\/p>\n<p>reflection may hit<\/p>\n<p>you shall not use<\/p>\n<p><code>--illegal-access=permit<\/code><\/p>\n<\/blockquote>\n<p>As a Java developer (if you tried to at least step out of your Java 8 comfort zone) chances are you saw something like this in your logs or terminal output:<\/p>\n<pre tabindex=\"0\"><code>WARNING: An illegal reflective access operation has occurred\nWARNING: Illegal reflective access by org.przybyl.ddj16.stronglyEncapsulatedInternals.StronglyEncapsulatedInternals to field java.lang.String.value\nWARNING: Please consider reporting this to the maintainers of org.przybyl.ddj16.stronglyEncapsulatedInternals.StronglyEncapsulatedInternals\nWARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations\nWARNING: All illegal access operations will be denied in a future release\n<\/code><\/pre><p>Since Java 9 release, a lot has been said and written about project Jigsaw, which not only modularised JDK itself (no more <code>rt.jar<\/code>!) but also brought to us the notion of the <em>illegal access<\/em>. I explain what that is in my <a href=\"https:\/\/softwaregarden.dev\/en\/talks\/migrating-java11\/\">Java. Migrating to 11 in real app<\/a> talk, let me recap briefly (in case you haven&rsquo;t seen it).<\/p>\n<p>Not every reflection in Java world is fundamentally one of These Bad Ideas\u2122. If you&rsquo;d like to discover in runtime capabilities of an object you&rsquo;ve been given, reflection might be quite handy. What&rsquo;s giving us headache is so called <em>deep reflection<\/em>.<\/p>\n<p>Object-oriented programming was invented for a reason. There are some pros and cons of this paradigm, but one of the key aspects of OOP is <em>encapsulation<\/em>, meaning: methods and properties of an object might have different accessibility scopes. Some methods might be public, some fields might be private, for example. The dreaded <em>deep reflection<\/em> tries to make everything visible to client code, no matter if the author of the object wanted some parts to be internal (e.g. <code>private<\/code>). As such, by many (and not only OOP purists), the <em>deep reflection<\/em> is seen as an abuse of the OOP.<\/p>\n<p>In the Java world the daemon of the <em>deep reflection<\/em> is usually summoned by the <em>setAccessible(true)<\/em> call, like in the following example:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span><span style=\"color:#f92672\">import<\/span> java.lang.reflect.Field;\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#f92672\">import<\/span> java.time.Instant;\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#f92672\">import<\/span> java.util.Arrays;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">StronglyEncapsulatedInternals<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#66d9ef\">static<\/span> <span style=\"color:#66d9ef\">void<\/span> <span style=\"color:#a6e22e\">main<\/span>(String<span style=\"color:#f92672\">[]<\/span> args) <span style=\"color:#66d9ef\">throws<\/span> NoSuchFieldException, IllegalAccessException {\n<\/span><\/span><span style=\"display:flex;\"><span>        deepLookInto(<span style=\"color:#e6db74\">&#34;Hello --illegal-access=deny!&#34;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>        secondsIn(Instant.<span style=\"color:#a6e22e\">now<\/span>());\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#66d9ef\">static<\/span> <span style=\"color:#66d9ef\">void<\/span> <span style=\"color:#a6e22e\">deepLookInto<\/span>(String input) {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#66d9ef\">try<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>            Field valueField <span style=\"color:#f92672\">=<\/span> String.<span style=\"color:#a6e22e\">class<\/span>.<span style=\"color:#a6e22e\">getDeclaredField<\/span>(<span style=\"color:#e6db74\">&#34;value&#34;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>            valueField.<span style=\"color:#a6e22e\">setAccessible<\/span>(<span style=\"color:#66d9ef\">true<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>            <span style=\"color:#66d9ef\">byte<\/span><span style=\"color:#f92672\">[]<\/span> actualValue <span style=\"color:#f92672\">=<\/span> (<span style=\"color:#66d9ef\">byte<\/span><span style=\"color:#f92672\">[]<\/span>)valueField.<span style=\"color:#a6e22e\">get<\/span>(input);\n<\/span><\/span><span style=\"display:flex;\"><span>            System.<span style=\"color:#a6e22e\">out<\/span>.<span style=\"color:#a6e22e\">println<\/span>(<span style=\"color:#e6db74\">&#34;Actual char array in string is: &#34;<\/span> <span style=\"color:#f92672\">+<\/span> Arrays.<span style=\"color:#a6e22e\">toString<\/span>(actualValue));\n<\/span><\/span><span style=\"display:flex;\"><span>        } <span style=\"color:#66d9ef\">catch<\/span> (NoSuchFieldException <span style=\"color:#f92672\">|<\/span> IllegalAccessException e) {\n<\/span><\/span><span style=\"display:flex;\"><span>            e.<span style=\"color:#a6e22e\">printStackTrace<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>        }\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#66d9ef\">static<\/span> <span style=\"color:#66d9ef\">void<\/span> <span style=\"color:#a6e22e\">secondsIn<\/span>(Instant now) <span style=\"color:#66d9ef\">throws<\/span> NoSuchFieldException, IllegalAccessException {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#66d9ef\">var<\/span> secondsField <span style=\"color:#f92672\">=<\/span> now.<span style=\"color:#a6e22e\">getClass<\/span>().<span style=\"color:#a6e22e\">getDeclaredField<\/span>(<span style=\"color:#e6db74\">&#34;seconds&#34;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>        secondsField.<span style=\"color:#a6e22e\">setAccessible<\/span>(<span style=\"color:#66d9ef\">true<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>        System.<span style=\"color:#a6e22e\">out<\/span>.<span style=\"color:#a6e22e\">println<\/span>(secondsField.<span style=\"color:#a6e22e\">get<\/span>(now));\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>It may look innocent at the first glance, right? This is a kind of code we see a lot in the Java world, and technically it was a perfectly valid code until Java 8.<\/p>\n<p>Things started to change after project Jigsaw saw the sunlight, as part of the Java 9 release (in September 2017). Then we started to see the warning quoted above, telling us (in a rephrased way, of course), that actually calling <code>setAccessible(true)<\/code> on fields and methods which aren&rsquo;t accessible to us, is seen as <code>illegal reflective access operation<\/code> and as such might be A Bad Idea\u2122.<\/p>\n<p>Please note it doesn&rsquo;t raise a warning about any &ldquo;reflective access operation&rdquo;, but &ldquo;<strong>illegal<\/strong> reflective access operation&rdquo;. Using reflection on parts which are still accessible to us (like the <em>public<\/em> part of the API) is still considered <strong>legal<\/strong>. In fact, should Java care if a <code>public<\/code> method is called directly or using reflection? What&rsquo;s wrong in calling a public getter or accessor? Exactly&hellip;<\/p>\n<p>There were many discussions and tickets about this warning. Java 9 introduced a new parameter, <code>--illegal-access<\/code> with four possible values:<\/p>\n<ul>\n<li><code>permit<\/code> (default) - which generates the warning only when the first illegal access was detected<\/li>\n<li><code>warn<\/code> - emitting the warning after each illegal access detection<\/li>\n<li><code>debug<\/code> - adding also a stack trace (pretty much like an exception) to <code>warn<\/code><\/li>\n<li><code>deny<\/code> - acting like <code>debug<\/code> for the <em>first<\/em> detection, then killing the program.<\/li>\n<\/ul>\n<p>Because the default was named <code>permit<\/code>, it was enough for some people to say&hellip; it&rsquo;s permitted! Doesn&rsquo;t matter the message was quite explicitly saying  &lsquo;&hellip; <em>illegal<\/em> &hellip;&rsquo;<\/p>\n<p>What about <code>All illegal access operations will be denied in a future release<\/code>? &lsquo;Naaah, not much to worry about. I don&rsquo;t think they will&hellip;&rsquo;<\/p>\n<p>Also, some people used to say that &lsquo;it&rsquo;s the way our library works, and it&rsquo;s just a warning; ignore it and live happily ever after&rsquo;. Worse, some other folks decided to follow this advice, not even worrying about <code>--add-opens<\/code>.<\/p>\n<p>Trouble is, the <em>ever after<\/em> might have ended with release of Java 16 in March 2021. ;-)<\/p>\n<h3 id=\"in-java-16---illegal-accessdeny\">In Java 16 <code>--illegal-access=deny<\/code><\/h3>\n<figure class=\"image image right\">\n<img src=\"you-shall-not-use.jpg\" alt=\"You shall not use\" width=\"400\">\n<\/figure>\n\n<p>This means that if your application summons the demons of deep reflection, either in the code you &amp; your team wrote, or in a 3rd party dependency, your application will simply go belly up. It will stop and work no more with the defaults. Now this pesky warning can&rsquo;t be simply ignored and <em>something<\/em> has to be done.<\/p>\n<p>Question is, what are you going do, my fellow Java developer?<\/p>\n<p>IMHO the worst thing you can do is to stay with Java versions &lt;=15 (will your clients &amp; users accept that?) or use the <code>--illegal-access<\/code> parameter set to <code>permit<\/code>. It&rsquo;s because it doesn&rsquo;t address the issue in any way, it&rsquo;s like putting a lipstick on a pig or tossing <code>@Ignore\/@Disable<\/code> on a falling JUnit test. Also, because this time the warning also says:<\/p>\n<pre tabindex=\"0\"><code>VM warning: Option --illegal-access is deprecated and will be removed in a future release\n<\/code><\/pre><p>Yes, even the possibility of setting <code>--illegal-access=deny<\/code> might be taken away from us one day. I&rsquo;m not in the  OpenJDK\/Oracle Java team, so I can&rsquo;t tell you when this happens (another 3,5 years?) or if it happens at all. Thing is: the <code>--illegal-access<\/code> switch is now <em>deprecated for removal<\/em> and one day it might be removed. Gone.<\/p>\n<p>Chances are this will happen for Java 17 as seen in <a href=\"https:\/\/openjdk.java.net\/jeps\/403\">JEP 403<\/a>. Seventeen. It&rsquo;s not a typo. ;-)<\/p>\n<p>It&rsquo;s yet another warning you may ignore on your way of producing legacy code for your future self (and future generations, in case your career plan is to go for a manager seat).<\/p>\n<p>The best thing you can do, in my humble opinion, is to eliminate the problem:<\/p>\n<ul>\n<li>stop using <code>setAccessible(true)<\/code> in your codebase<\/li>\n<li>upgrade your dependencies, so they&rsquo;re not making that call either<\/li>\n<li>in case the dependency vendor says &lsquo;it has to be this way&rsquo; (meaning: &lsquo;we can&rsquo;t change our architecture to stop violating the OOP, sorry (not sorry)&rsquo;), consider another vendor.<\/li>\n<\/ul>\n<p>In my reading (and you&rsquo;re not obligated to agree by any means) modules in Java are not only about modularising the JDK (although that seems to be the primary goal) and annoying library maintainers. Modules in Java &gt;=9 are also a great opportunity to enforce clean(er) architecture relying on the <code>module-info<\/code> descriptors, without any 3rd party tools.<\/p>\n<p>Talking about the example code above, there are two <code>setAccessible(true)<\/code> calls. I don&rsquo;t know why anyone would need to e.g. persist a <code>String<\/code> using the content of <strong>internal<\/strong> <code>value<\/code>. A string is a string, right? If you need bytes (who doesn&rsquo;t every now and then?) please go for <code>getBytes()<\/code> in one of its variants.<\/p>\n<p>The same applies to <code>Instant<\/code>: IMHO it shouldn&rsquo;t be persisted by walking one private field after another private field. Instead, the code should recognise it&rsquo;s working with an Instant and therefore call <code>getEpochSecond()<\/code> or <code>getNano()<\/code> (depending on the scenario) and then reconstruct the object using e.g. one <code>ofEpochSecond(...)<\/code> factory methods (also because it&rsquo;s <code>@ValueBased<\/code> by Valhalla).<\/p>\n<p>I understand we might not be able to go for the best option immediately, so there&rsquo;s also a middle ground, which isn&rsquo;t that bad:<\/p>\n<ol>\n<li>set <code>--illegal-access=debug<\/code> or (<code>warn<\/code>, if you don&rsquo;t need any stacktrace) and examine the output<\/li>\n<li>based on the output, set <code>--add-opens<\/code> parameter(s), to legalise the access<\/li>\n<li>please remember that <code>--add-opens<\/code> statements can be grouped in flat text files, so you can e.g. group them like one file per one dependency<\/li>\n<\/ol>\n<p>Again, please refer to my <a href=\"https:\/\/softwaregarden.dev\/en\/talks\/migrating-java11\/\">Java. Migrating to 11 in real app<\/a> talk if you&rsquo;d like to know how this can be done. And, as usual, please read the <a href=\"https:\/\/openjdk.java.net\/jeps\/396\">JEP 396<\/a>.<\/p>\n<h3 id=\"fly-you-fools\">Fly, you fools!<\/h3>\n"},{"title":"Java 16. What's new and noteworthy?","link":"https:\/\/softwaregarden.dev\/en\/talks\/java-16-new-and-noteworthy\/","pubDate":"Thu, 06 May 2021 10:00:00 +0200","guid":"https:\/\/softwaregarden.dev\/en\/talks\/java-16-new-and-noteworthy\/","description":"<p>Another (half a) year has passed, another major Java\u2122 version has been released.\nJava was supposed &ldquo;to be slow&rdquo;. However, Java turns out to evolve so fast, that next releases aren&rsquo;t just version bumps, but might significantly change the rules of the game. That&rsquo;s a good reason to check out what&rsquo;s new in Java.\nWe&rsquo;re going to cover:<\/p>\n<ul>\n<li>Records, where and how to use them, apart from DTO\/VO<\/li>\n<li>Pattern matching with instanceof A.K.A. Smart casting<\/li>\n<li>Sealed classes, new dimension of types extensibility (for inheritance)<\/li>\n<li>Warnings from Jigsaw (&ndash;illegal-access strikes back!)<\/li>\n<li>And Valhalla (for value-based classes abuse)<\/li>\n<li>Talking to native stuff from Panama<\/li>\n<li>and more.<\/li>\n<\/ul>\n<p>All visualised in actual code, not just slides.<\/p>\n<p>I was able to talk on Java 16 for more than 3 hours is total thanks to joined initiative of <a href=\"https:\/\/wroclaw.jug.pl\/\">WroclawJUG<\/a> and <a href=\"https:\/\/silesia.jug.pl\/\">SilesiaJUG<\/a>.<\/p>\n<p>Part one (covering almost everything except records and trivia):<\/p>\n<div style=\"position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;\">\n      <iframe allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen\" loading=\"eager\" referrerpolicy=\"strict-origin-when-cross-origin\" src=\"https:\/\/www.youtube-nocookie.com\/embed\/OLcFpWEzf9c?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0\" style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;\" title=\"YouTube video\"><\/iframe>\n    <\/div>\n\n<p>Part two (covering records and some trivia):<\/p>\n<div style=\"position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;\">\n      <iframe allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen\" loading=\"eager\" referrerpolicy=\"strict-origin-when-cross-origin\" src=\"https:\/\/www.youtube-nocookie.com\/embed\/QHT4xosL97w?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0\" style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;\" title=\"YouTube video\"><\/iframe>\n    <\/div>\n\n"},{"title":"Java Records tortured with Lombok yet again (builder edition)","link":"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/records\/vs-lombok-yet-again-with-builder-pattern\/","pubDate":"Thu, 15 Apr 2021 18:00:00 +0200","guid":"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/records\/vs-lombok-yet-again-with-builder-pattern\/","description":"<p>Last year I wrote <a href=\"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/records\/vs-lombok\/\">two<\/a> <a href=\"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/records\/vs-lombok-again\/\">posts<\/a> about torturing Java records with Lombok. Fortunately (or not, depends on your point of view), Lombok&rsquo;s team decided to end these sick plays. So it seems that with Java 16 and Lombok 1.18.20 there&rsquo;s no more tossing <code>@Getter<\/code> or <code>@With<\/code> on records. More details can be found in their <a href=\"https:\/\/github.com\/rzwitserloot\/lombok\/pull\/2578\">GitHub issue #2578<\/a>. Basically, javac generates errors like:<\/p>\n<pre tabindex=\"0\"><code>@ToString is only supported on a class or enum.\n<\/code><\/pre><p>which makes<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">@ToString<\/span>(of<span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;f1&#34;<\/span>)\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#66d9ef\">record<\/span> <span style=\"color:#a6e22e\">RecordWithToStringFromLombok<\/span>(<span style=\"color:#66d9ef\">int<\/span> f1, String f2) {}\n<\/span><\/span><\/code><\/pre><\/div><p>impossible. The same happens, if you annotate the record with e.g. <code>@Getter<\/code>. It seems that records are not classes ;-) Or that Lombok feels uncomfortable generating <code>toString()<\/code> from subset of record&rsquo;s fields.\nIf you still desperately need getters for record&rsquo;s components, not just accessors, you can go for something like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#66d9ef\">record<\/span> <span style=\"color:#a6e22e\">RecordWithGetters<\/span>(<span style=\"color:#a6e22e\">@Getter<\/span> <span style=\"color:#66d9ef\">int<\/span> f1, <span style=\"color:#a6e22e\">@Getter<\/span> String f2) {}\n<\/span><\/span><\/code><\/pre><\/div><p>which won&rsquo;t generate any errors, but it won&rsquo;t generate any getters either. Boom. Add getters manually, apart from accessors, if your library\/framework desperately needs the <code>get<\/code> prefix. Or just stick to JavaBeans.<\/p>\n<p>However, maybe there are still other ways to &ldquo;exploit&rdquo; Lombok with records and bring it to another level? Maybe this time it could be even somewhat useful?<\/p>\n<h3 id=\"do-java-records-have-builder\">Do Java records have builder?<\/h3>\n<figure class=\"image image right\">\n<img src=\"records-lombok.jpg\" alt=\"Records or Lombok\" width=\"400\">\n<\/figure>\n\n<p>Short answer: no. Currently, there&rsquo;s no &lsquo;default&rsquo; or &lsquo;standard&rsquo; builder for records. If you need one, you can create one on your own. Or&hellip; we can misbehave and try to (ab)use Lombok yet another time. ;-)<\/p>\n<p>Let&rsquo;s say we have a dummy record like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">record<\/span> <span style=\"color:#a6e22e\">BuilderRecord<\/span>(<span style=\"color:#66d9ef\">int<\/span> a, String b, Double c) {}\n<\/span><\/span><\/code><\/pre><\/div><p>and we&rsquo;d like to create instances using builder, as it sounds more fluent. Adding <code>@Builder<\/code> doesn&rsquo;t show any errors. However, the only method generated in <code>BuilderRecord.builder()<\/code> is <code>build()<\/code>. Not quite what we expected.<\/p>\n<p>Also, delomboking the <code>@Builder<\/code> generates:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">record<\/span> <span style=\"color:#a6e22e\">BuilderRecord<\/span>(<span style=\"color:#66d9ef\">int<\/span> a, String b, Double c) {\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    BuilderRecord() {\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#66d9ef\">static<\/span> BuilderRecordBuilder <span style=\"color:#a6e22e\">builder<\/span>() {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">new<\/span> BuilderRecordBuilder();\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#66d9ef\">static<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">BuilderRecordBuilder<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>        BuilderRecordBuilder() {\n<\/span><\/span><span style=\"display:flex;\"><span>        }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#66d9ef\">public<\/span> BuilderRecord <span style=\"color:#a6e22e\">build<\/span>() {\n<\/span><\/span><span style=\"display:flex;\"><span>            <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">new<\/span> BuilderRecord();\n<\/span><\/span><span style=\"display:flex;\"><span>        }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#66d9ef\">public<\/span> String <span style=\"color:#a6e22e\">toString<\/span>() {\n<\/span><\/span><span style=\"display:flex;\"><span>            <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#e6db74\">&#34;BuilderRecord.BuilderRecordBuilder()&#34;<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>        }\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>which doesn&rsquo;t compile, because the constructor isn&rsquo;t canonical. Oops.<\/p>\n<p>However, we can keep pushing. After all, <code>@Builder<\/code> is annotated <code>@Target({TYPE, METHOD, CONSTRUCTOR})<\/code>&hellip; ;-)<\/p>\n<p>Let&rsquo;s create an empty compact constructor, only to annotate it with <code>@Builder<\/code>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">@Builder<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>BuilderRecord {}\n<\/span><\/span><\/code><\/pre><\/div><p>Bingo!<\/p>\n<p>This time we can write:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">var<\/span> sample <span style=\"color:#f92672\">=<\/span> BuilderRecord.<span style=\"color:#a6e22e\">builder<\/span>().<span style=\"color:#a6e22e\">a<\/span>(42).<span style=\"color:#a6e22e\">b<\/span>(<span style=\"color:#e6db74\">&#34;answer&#34;<\/span>).<span style=\"color:#a6e22e\">c<\/span>(Double.<span style=\"color:#a6e22e\">POSITIVE_INFINITY<\/span>).<span style=\"color:#a6e22e\">build<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>System.<span style=\"color:#a6e22e\">out<\/span>.<span style=\"color:#a6e22e\">println<\/span>(sample);\n<\/span><\/span><\/code><\/pre><\/div><p>and it produces the expected output:<\/p>\n<pre tabindex=\"0\"><code>BuilderRecord[a=42, b=answer, c=Infinity]\n<\/code><\/pre><p>Just for the sake of completeness, the delomboked version is as follows:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">record<\/span> <span style=\"color:#a6e22e\">BuilderRecord<\/span>(<span style=\"color:#66d9ef\">int<\/span> a, String b, Double c) {\n<\/span><\/span><span style=\"display:flex;\"><span>    BuilderRecord {\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#66d9ef\">static<\/span> BuilderRecordBuilder <span style=\"color:#a6e22e\">builder<\/span>() {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">new<\/span> BuilderRecordBuilder();\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#66d9ef\">static<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">BuilderRecordBuilder<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#66d9ef\">int<\/span> a;\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#66d9ef\">private<\/span> String b;\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#66d9ef\">private<\/span> Double c;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>        BuilderRecordBuilder() {\n<\/span><\/span><span style=\"display:flex;\"><span>        }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#66d9ef\">public<\/span> BuilderRecordBuilder <span style=\"color:#a6e22e\">a<\/span>(<span style=\"color:#66d9ef\">int<\/span> a) {\n<\/span><\/span><span style=\"display:flex;\"><span>            <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">a<\/span> <span style=\"color:#f92672\">=<\/span> a;\n<\/span><\/span><span style=\"display:flex;\"><span>            <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">this<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>        }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#66d9ef\">public<\/span> BuilderRecordBuilder <span style=\"color:#a6e22e\">b<\/span>(String b) {\n<\/span><\/span><span style=\"display:flex;\"><span>            <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">b<\/span> <span style=\"color:#f92672\">=<\/span> b;\n<\/span><\/span><span style=\"display:flex;\"><span>            <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">this<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>        }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#66d9ef\">public<\/span> BuilderRecordBuilder <span style=\"color:#a6e22e\">c<\/span>(Double c) {\n<\/span><\/span><span style=\"display:flex;\"><span>            <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">c<\/span> <span style=\"color:#f92672\">=<\/span> c;\n<\/span><\/span><span style=\"display:flex;\"><span>            <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">this<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>        }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#66d9ef\">public<\/span> BuilderRecord <span style=\"color:#a6e22e\">build<\/span>() {\n<\/span><\/span><span style=\"display:flex;\"><span>            <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">new<\/span> BuilderRecord(a, b, c);\n<\/span><\/span><span style=\"display:flex;\"><span>        }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#66d9ef\">public<\/span> String <span style=\"color:#a6e22e\">toString<\/span>() {\n<\/span><\/span><span style=\"display:flex;\"><span>            <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#e6db74\">&#34;BuilderRecord.BuilderRecordBuilder(a=&#34;<\/span> <span style=\"color:#f92672\">+<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">a<\/span> <span style=\"color:#f92672\">+<\/span> <span style=\"color:#e6db74\">&#34;, b=&#34;<\/span> <span style=\"color:#f92672\">+<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">b<\/span> <span style=\"color:#f92672\">+<\/span> <span style=\"color:#e6db74\">&#34;, c=&#34;<\/span> <span style=\"color:#f92672\">+<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">c<\/span> <span style=\"color:#f92672\">+<\/span> <span style=\"color:#e6db74\">&#34;)&#34;<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>        }\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>This time the delomboked code compiles and works the same way.<\/p>\n<p>It seems then that maybe there&rsquo;s a way to still toss Lombok onto a record. And maybe (just maybe) the result isn&rsquo;t that bad&hellip;? It would be nicer, of course, if we didn&rsquo;t have to use the compact constructor.<\/p>\n<p>If you have more sick ideas about (mis)using records and Lombok, let me know!<\/p>\n"},{"title":"Is hashCode() in Java records cached?","link":"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/records\/is-hashcode-in-records-cached\/","pubDate":"Thu, 15 Apr 2021 00:15:00 +0200","guid":"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/records\/is-hashcode-in-records-cached\/","description":"<p>Many times during my talks covering Java records I was asked if the result of <code>hashCode()<\/code> of a record is cached. Let&rsquo;s see. ;-)<\/p>\n<p>Actually, if you have followed <a href=\"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/records\/should-write-equals-and-hashcode\/\">my previous post<\/a> on record&rsquo;s <code>equals()<\/code> and <code>hashCode()<\/code>, you may already know the answer. But since this question is separate, let&rsquo;s run a separate experiment.<\/p>\n<p>First, let&rsquo;s define a simple debug method:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">static<\/span> <span style=\"color:#66d9ef\">void<\/span> <span style=\"color:#a6e22e\">printHashCodes<\/span>(Record record, List<span style=\"color:#f92672\">&lt;?&gt;<\/span> list) {\n<\/span><\/span><span style=\"display:flex;\"><span>    System.<span style=\"color:#a6e22e\">out<\/span>.<span style=\"color:#a6e22e\">printf<\/span>(<span style=\"color:#e6db74\">&#34;%d, %d, %s%n&#34;<\/span>, record.<span style=\"color:#a6e22e\">hashCode<\/span>(), list.<span style=\"color:#a6e22e\">hashCode<\/span>(), list);\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>Next, let&rsquo;s run the following:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">record<\/span> <span style=\"color:#a6e22e\">IsHashCodeCached<\/span>(List<span style=\"color:#f92672\">&lt;?&gt;<\/span> list) {}\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">var<\/span> list <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> ArrayList<span style=\"color:#f92672\">&lt;<\/span>String<span style=\"color:#f92672\">&gt;<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">var<\/span> record <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> IsHashCodeCached(list);\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">var<\/span> words <span style=\"color:#f92672\">=<\/span> List.<span style=\"color:#a6e22e\">of<\/span>(<span style=\"color:#e6db74\">&#34;ene&#34;<\/span>, <span style=\"color:#e6db74\">&#34;due&#34;<\/span>, <span style=\"color:#e6db74\">&#34;like&#34;<\/span>, <span style=\"color:#e6db74\">&#34;fake&#34;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>printHashCodes(record, list);\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">for<\/span> (String word : words) {\n<\/span><\/span><span style=\"display:flex;\"><span>    list.<span style=\"color:#a6e22e\">add<\/span>(word);\n<\/span><\/span><span style=\"display:flex;\"><span>    printHashCodes(record, list);\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><p>The results I get using OpenJDK Runtime Environment (build 16+36-2231) without any extra switches or parameters are the following:<\/p>\n<pre tabindex=\"0\"><code>1, 1, []\n100603, 100603, [ene]\n3218521, 3218521, [ene, due]\n103095902, 103095902, [ene, due, like]\n-1095859017, -1095859017, [ene, due, like, fake]\n<\/code><\/pre><p>If you don&rsquo;t get the very same numbers, don&rsquo;t worry. The contract of hashCode says that the results of <code>hashCode()<\/code> <em>might<\/em> differ when re-starting a given Java programme again and again.\nWhat matters here is that the hashCode on a record changes whenever we change one of its components during single programme execution. As I wrote in <a href=\"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/records\/should-write-equals-and-hashcode\/\">the previous post<\/a>, records are immutable, but it&rsquo;s <em>shallow immutability<\/em>.<\/p>\n<p>Answering the original question: even if <code>hashCode()<\/code> is cached somehow, this cache seems to be invalidated after every change. ;-)<\/p>\n<p>Besides, the JavaDoc clearly states: <em>The precise algorithm used in the implicitly provided implementation is unspecified and is subject to change within the above limits.<\/em> If you&rsquo;re interested in the limits, <a href=\"https:\/\/docs.oracle.com\/en\/java\/javase\/16\/docs\/api\/java.base\/java\/lang\/Record.html#hashCode()\">RTFM<\/a>!<\/p>\n<p>Apart from that, to be extra clear (some need to have things written directly): having mutable components in records might be one of these <em>Really Bad Ideas\u2122<\/em>. I suggest thinking at least twice before such a record is written. This post is just a demo.<\/p>\n"},{"title":"Do we really never need to implement equals() and hashCode() in Java 16 records?","link":"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/records\/should-write-equals-and-hashcode\/","pubDate":"Wed, 14 Apr 2021 15:00:00 +0200","guid":"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/records\/should-write-equals-and-hashcode\/","description":"<h3 id=\"hype-strikes-again\">Hype strikes again<\/h3>\n<p>I remember some hype, back in late winter 2020, when Java 14 was about to be released and quite a buzz about one if its preview features, namely records. Despite many efforts from the &ldquo;Java team&rdquo; and #usualSuspects, there were really (too) many tweets &amp; Co. in the wild that &ldquo;records are automatically generated beans&rdquo;. Well, I hope we got that cleared, at least to some extent, so more and more people started realise that statements like &ldquo;records are Java Beans, only without setters&rdquo; are basically false. If some people still need to be convinced about that, please follow another post on <a href=\"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/records\/can-and-cannot\/\">records&rsquo; reflection<\/a> in my blog.<\/p>\n<p>This late winter there was another hype. Since I really don&rsquo;t want to point fingers, either believe me it was or search of your own. ;-) Basically, this late winter and early spring we had to face &ldquo;for records you never have to write <code>equals()<\/code> and <code>hashCode()<\/code> methods&rdquo; and that&rsquo;s something that makes me somewhat uncomfortable.<\/p>\n<p>Actually, <a href=\"https:\/\/openjdk.java.net\/jeps\/395\">JEP 395: Records<\/a> doesn&rsquo;t state that, unless I&rsquo;m missing something. (Please let me know if I&rsquo;m wrong in this (or any other) case.) It says something like &ldquo;record classes get <code>equals()<\/code> and <code>hashCode()<\/code> automatically, and they&rsquo;re based on all components, and they can be overwritten (obey their contracts, pretty please)&rdquo;. The actual quotes are: &laquo;a record class acquires many standard members automatically: (&hellip;) equals and hashCode methods which ensure that two record values are equal if they are of the same type and contain equal component values&raquo; and &laquo;Developers are sometimes tempted to cut corners by omitting methods such as equals, leading to surprising behavior or poor debuggability, or by pressing an alternate but not entirely appropriate class into service because it has the &ldquo;right shape&rdquo; and they don&rsquo;t want to declare yet another class.&raquo;<\/p>\n<p>Please don&rsquo;t get me wrong. I really, really love the fact that records are immutable and acquire <code>equals()<\/code> and <code>hashCode()<\/code> automatically, apart from other features. It&rsquo;s just we can&rsquo;t overstretch this blanket to also cover &ldquo;never write <code>equals()<\/code>&hellip;&rdquo; Java records are immutable in a sense, that based on each component from the header a <code>private final<\/code> field is generated. Therefore, we can&rsquo;t reassign a new object to such a field, and it&rsquo;s really nice if this field&rsquo;s fields are also immutable, and so on, because this gives us deeply immutable data structure in hand. Examples: <code>java.lang.String<\/code>, <code>java.time.Instant<\/code>, <code>java.lang.Long<\/code>, immutable collections (although you&rsquo;ll find that at runtime, sorry).<\/p>\n<p>However, sometimes these fields can have mutable members\/elements, like <code>java.util.Date<\/code>, <code>java.util.ArrayList<\/code>, <code>java.util.concurrent.atomic.AtomicInteger<\/code> or arrays. Meaning: we can&rsquo;t set a new <code>ArrayList<\/code> as record&rsquo;s field once the constructor finishes creating record instance\/object, but we can add elements to this <code>ArrayList<\/code>. Apart from JavaDoc (which we all read, understand and implement every day), there is gazillion or two posts and videos how to implement <code>equals()<\/code> and <code>hashCode()<\/code> properly, just duckduck them. Things get much simpler if the objects have no moving parts, and creating incorrect implementation of these two methods is somewhat challenging then. ;-)<\/p>\n<p>Based on two facts:<\/p>\n<ul>\n<li>records are immutable<\/li>\n<li>records get <code>equals()<\/code> and <code>hashCode()<\/code> generated<\/li>\n<\/ul>\n<p>many started this &ldquo;records hype, 2021 edition\u2122&rdquo;. However, as we&rsquo;ve already seen, records are immutable, but in the <em>shallow<\/em> way. Nothing makes your records&rsquo; fields magically immutable too!<\/p>\n<h3 id=\"little-demo-if-you-please\">Little demo, if you please<\/h3>\n<figure class=\"image image right\">\n<img src=\"https:\/\/www.wykop.pl\/cdn\/c3201142\/comment_UCl17CFsT9x6fcb4po4vjx0xBgh7Mh9L.jpg\" alt=\"Rekord\">\n<\/figure>\n\n<p>Many posts &amp; tutorials on Java records have some vinyl for title slide or miniature. (In fact, my <a href=\"https:\/\/softwaregarden.dev\/en\/talks\/java-records-for-intrigued\/\">Java Records for the Intrigued<\/a> 2021 edition also does.)<\/p>\n<p>However, the very first association that comes to my mind when I hear &lsquo;record&rsquo; is&hellip; a sweet bar. ;-) When I was a child, we used to eat them quite a lot, and it&rsquo;s a real pity they&rsquo;re not made anymore. For those of you who didn&rsquo;t have the pleasure of trying them, they were somewhat similar in taste to Snickers.<\/p>\n<p>So, we&rsquo;re going to use these bars in the demo. Let&rsquo;s pretend we own a candy factory, and we can produce one bar at a time. There&rsquo;s no way more than one is produced at given timestamp. Then, due to somewhat specific business rule (like a lot of them, right?) we need to trace\/label the location of each bar. Kind like a parcel. Obviously, once made, the bars have their time of fabrication fixed, we only keep adding locations until they end up in someone&rsquo;s mouth.<\/p>\n<p>Therefore, a na\u00efve implementation might look like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">record<\/span> <span style=\"color:#a6e22e\">Rekord<\/span>(Instant created, List<span style=\"color:#f92672\">&lt;<\/span>String<span style=\"color:#f92672\">&gt;<\/span> locations) {}\n<\/span><\/span><\/code><\/pre><\/div><p>We create two bars:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">var<\/span> bar1 <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> Rekord(Instant.<span style=\"color:#a6e22e\">ofEpochSecond<\/span>(1618309360), <span style=\"color:#66d9ef\">new<\/span> ArrayList<span style=\"color:#f92672\">&lt;&gt;<\/span>(Collections.<span style=\"color:#a6e22e\">singletonList<\/span>(<span style=\"color:#e6db74\">&#34;factory&#34;<\/span>)));\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">var<\/span> bar2 <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> Rekord(Instant.<span style=\"color:#a6e22e\">ofEpochSecond<\/span>(1618309370), <span style=\"color:#66d9ef\">new<\/span> ArrayList<span style=\"color:#f92672\">&lt;&gt;<\/span>(Collections.<span style=\"color:#a6e22e\">singletonList<\/span>(<span style=\"color:#e6db74\">&#34;factory&#34;<\/span>)));\n<\/span><\/span><\/code><\/pre><\/div><p>And we add them to a box:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">var<\/span> box <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> HashSet<span style=\"color:#f92672\">&lt;<\/span>Rekord<span style=\"color:#f92672\">&gt;<\/span>();\n<\/span><\/span><span style=\"display:flex;\"><span>box.<span style=\"color:#a6e22e\">add<\/span>(bar1);\n<\/span><\/span><span style=\"display:flex;\"><span>box.<span style=\"color:#a6e22e\">add<\/span>(bar2);\n<\/span><\/span><\/code><\/pre><\/div><p>Very nice!\nThen they reach different warehouses:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span>bar1.<span style=\"color:#a6e22e\">locations<\/span>().<span style=\"color:#a6e22e\">add<\/span>(<span style=\"color:#e6db74\">&#34;warehouseAlpha&#34;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>bar2.<span style=\"color:#a6e22e\">locations<\/span>().<span style=\"color:#a6e22e\">add<\/span>(<span style=\"color:#e6db74\">&#34;warehouseBeta&#34;<\/span>);\n<\/span><\/span><\/code><\/pre><\/div><p>and someone decides to reuse the box (recycling, mind you!) and put them to a common box again, for easier tracing of batches:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span>box.<span style=\"color:#a6e22e\">add<\/span>(bar1);\n<\/span><\/span><span style=\"display:flex;\"><span>box.<span style=\"color:#a6e22e\">add<\/span>(bar2);\n<\/span><\/span><\/code><\/pre><\/div><p>Question: how many bars do we have in this box? Obviously, two!<\/p>\n<p>Turns out we might have a box with Schr\u00f6dinger bars, because there seem to be&hellip; four?<\/p>\n<pre tabindex=\"0\"><code>jshell&gt; box.size();\n$12 ==&gt; 4\n<\/code><\/pre><p>It can&rsquo;t be! We produced only two! Let&rsquo;s check what&rsquo;s inside this box:<\/p>\n<pre tabindex=\"0\"><code>jshell&gt; box.forEach(System.out::println);\nRekord[created=2021-04-13T10:22:50Z, locations=[factory, warehouseBeta]]\nRekord[created=2021-04-13T10:22:40Z, locations=[factory, warehouseAlpha]]\nRekord[created=2021-04-13T10:22:40Z, locations=[factory, warehouseAlpha]]\nRekord[created=2021-04-13T10:22:50Z, locations=[factory, warehouseBeta]]\n<\/code><\/pre><p>Apparently, in our box we keep each bar twice (despite it exists as a single entity) and the box is a set, which in theory doesn&rsquo;t allow duplicates&hellip;? Or something like that. Complicated, I know ;-)<\/p>\n<h3 id=\"weve-all-been-there-havent-we\">We&rsquo;ve all been there, haven&rsquo;t we?<\/h3>\n<p>It happened before we understood the true meaning of the <code>hashCode<\/code>&rsquo;s <a href=\"https:\/\/docs.oracle.com\/en\/java\/javase\/16\/docs\/api\/java.base\/java\/lang\/Object.html#hashCode()\">JavaDoc<\/a>. Actually, having a <code>hashCode()<\/code> on an object giving different results during single execution and putting such objects to a <code>HashSet<\/code> might be one of these <em>Really Bad Ideas\u2122<\/em>.<\/p>\n<p>I know this example is somewhat dummy, but please don&rsquo;t expect me to put here real &ldquo;business&rdquo; code. NDA and stuff, you know.<\/p>\n<p>The whole thing is about understanding <code>equals()<\/code>, <code>hashCode()<\/code>, identity and equality of objects, implications of mutability and Java collections as well.<\/p>\n<p>The criticism I often hear about project Lombok is that <code>@Data<\/code> generates incorrect <code>equals()<\/code> and <code>hashCode()<\/code> and therefore Lombok itself should be banned. Well, I don&rsquo;t want to tell you, whether you should or shouldn&rsquo;t use Lombok. Just tell me, is it really fair to blame Lombok for this very thing? Who do we blame if the implementation generated by the IDE is also incorrect, because it uses all fields, including mutable ones? The IDE? Or do we rather go for <a href=\"https:\/\/en.wiktionary.org\/wiki\/PICNIC\">PICNIC<\/a> with <code>git blame<\/code>?<\/p>\n<p>Who are we going to blame after we fix some errors in 2023 and later, because &lsquo;oh, this bug was caused by incorrect automatic implementation of this record, sir&rsquo;? ;-)<\/p>\n<p>My dear fellow developers, it is our job to know, how the things we use behave (to decent level also under the hood) before we use them in code. Whether it&rsquo;s a library, a compiler plugin or new language syntax, it is our responsibility to use them properly, not to excuse us with some false prophets we heard back in 2021.<\/p>\n<p>Of course, when I see a code like the one with <code>Rekord<\/code>, there are some code smells, and we should do something about that.\nI see a few options at least.<\/p>\n<ul>\n<li>First I would try to get rid of moving parts, in this case the <code>List&lt;String&gt; locations<\/code> component\/field. Rekords should not be responsible for tracking themselves. (Unless they really have labels placed on them, who knows?)<\/li>\n<li>If we really can&rsquo;t get rid of it, let&rsquo;s try to make it (at least at runtime level) not able to be modified. Maybe by adding a full canonical constructor, which could make sure the list cannot be modified, by using <a href=\"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/riddle-answer\/\"><code>List.copyOf()<\/code><\/a>:<\/li>\n<\/ul>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">record<\/span> <span style=\"color:#a6e22e\">Rekord<\/span>(Instant created, List<span style=\"color:#f92672\">&lt;<\/span>String<span style=\"color:#f92672\">&gt;<\/span> locations) {\n<\/span><\/span><span style=\"display:flex;\"><span>    Rekord(Instant created, List<span style=\"color:#f92672\">&lt;<\/span>String<span style=\"color:#f92672\">&gt;<\/span> locations) {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">created<\/span> <span style=\"color:#f92672\">=<\/span> created;\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">locations<\/span> <span style=\"color:#f92672\">=<\/span> List.<span style=\"color:#a6e22e\">copyOf<\/span>(locations);\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><ul>\n<li>If that&rsquo;s impossible too, maybe we could try to skip this field from being used by <code>equals()<\/code> and <code>hashCode()<\/code> whatsoever:<\/li>\n<\/ul>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">record<\/span> <span style=\"color:#a6e22e\">Rekord<\/span>(Instant created, List<span style=\"color:#f92672\">&lt;<\/span>String<span style=\"color:#f92672\">&gt;<\/span> locations) {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">@Override<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#66d9ef\">boolean<\/span> <span style=\"color:#a6e22e\">equals<\/span>(Object o) {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#66d9ef\">this<\/span> <span style=\"color:#f92672\">==<\/span> o) <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">true<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#66d9ef\">if<\/span> (o <span style=\"color:#f92672\">==<\/span> <span style=\"color:#66d9ef\">null<\/span> <span style=\"color:#f92672\">||<\/span> getClass() <span style=\"color:#f92672\">!=<\/span> o.<span style=\"color:#a6e22e\">getClass<\/span>()) <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">false<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>        Rekord rekord <span style=\"color:#f92672\">=<\/span> (Rekord) o;\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#66d9ef\">return<\/span> created.<span style=\"color:#a6e22e\">equals<\/span>(rekord.<span style=\"color:#a6e22e\">created<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#a6e22e\">@Override<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#66d9ef\">int<\/span> <span style=\"color:#a6e22e\">hashCode<\/span>() {\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#66d9ef\">return<\/span> Objects.<span style=\"color:#a6e22e\">hash<\/span>(created);\n<\/span><\/span><span style=\"display:flex;\"><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span>}\n<\/span><\/span><\/code><\/pre><\/div><ul>\n<li>Maybe we should keep the first value calculated by <code>hashCode()<\/code> during programme execution, provided it&rsquo;s in line with <code>equals()<\/code>?<\/li>\n<li>Or maybe we shall not use <code>record<\/code> for Rekord at all&hellip;?<\/li>\n<\/ul>\n<h3 id=\"sometimes-we-may-need-to-override-equals-and-hashcode-in-records\">Sometimes we may need to override equals() and hashCode() in records<\/h3>\n<p>Don&rsquo;t <del>stackoverflow<\/del> copy&amp;paste this code, please. It&rsquo;s not meant to solve the issue. Its sole purpose was to demonstrate that actually <em>sometimes we may need to override equals() and hashCode() in records<\/em>, which IMHO is quite opposite to <em>in records you don&rsquo;t have to write equals() and hashCode()<\/em>. It really depends. We should know when and <a href=\"https:\/\/docs.oracle.com\/en\/java\/javase\/16\/docs\/api\/java.base\/java\/lang\/Record.html#equals(java.lang.Object)\">why<\/a>, every time we implement them on our own or have generated for us, regardless the tool. At least, until <em>value-based objects<\/em> become a thing. ;-)<\/p>\n<p>Thankfully, because <code>record<\/code>s are <code>final<\/code>, we don&rsquo;t have to worry about <a href=\"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/how-not-to-use-instanceof\/\">using instanceof in <code>equals()<\/code><\/a>.<\/p>\n<p>Apart from that, to be extra clear (some need to have things written directly): having mutable components in records might be one of these <em>Really Bad Ideas\u2122<\/em>. I suggest thinking at least twice before such a record is written. This post is just a demo.<\/p>\n"},{"title":"Some GNOME terminal goodies","link":"https:\/\/softwaregarden.dev\/en\/posts\/linux\/terminal\/emulator-goodies\/","pubDate":"Thu, 04 Feb 2021 10:00:00 +0100","guid":"https:\/\/softwaregarden.dev\/en\/posts\/linux\/terminal\/emulator-goodies\/","description":"<p>After using Linux for quite a few years now, I&rsquo;ve accidentally embarrassed myself. I spend a lot of time using terminal in various forms. I&rsquo;m not sure I know all Vim quirks (not to mention Emacs, but let&rsquo;s not talk about this operating system now), therefore I was pretty confident I know how to use the terminal emulator&hellip; Today I&rsquo;ve found a nice new feature, really low-hanging-fruit, so I&rsquo;ve decided to share it with you, along with some other goodies (maybe not some obvious to Linux neophytes) I&rsquo;m being asked about after my talks.<\/p>\n<p>Without further ado, what I&rsquo;ve discovered today is that if you right click a number in GNOME terminal app (and I don&rsquo;t mean the exact shell running inside), the number will get converted to the HEX representation and also the human friendly file size. Now checking <code>ls -lh<\/code> or overriding <code>alias ll=ls -lah<\/code> is not so much needed.<\/p>\n<p><figure class=\"image image right\">\n<img src=\"GNOME-terminal-emulator.png\" alt=\"GNOME terminal emulator and right click on a number\" width=\"600\">\n<\/figure>\n\nSay, you&rsquo;ve listed files in the current directory with <code>ls -l<\/code>, and the file size is printed in exact number of bytes. Sure, maybe we should have <code>ls -lh<\/code>, to be more human (that is us) friendly. However, if (due to whatever reason) you need to make sure the Windows\u2122 image you downloaded some time ago will fit in size to your medium (because you need to repair the installation for one of your relatives <em>again<\/em>), you can simply right click on <code>4941438976<\/code> and the GNOME terminal will friendly show it you as <code>4.60 Gi<\/code>. As you see, the friendliness of GNU\/Linux manifests itself not only with <code>screen<\/code>, <code>grep<\/code>, <code>awk<\/code>, and so on, but here as well!<\/p>\n<p>(A brief reminder, that <em>k<\/em> stands for <em>kilo<\/em> which is one thousand in Latin. <em>Ki<\/em> stands for 1024, so drive manufacturers seem to hate the little i. Read more about <a href=\"https:\/\/en.wikipedia.org\/wiki\/Byte#Multiple-byte_units\">kibibytes<\/a> and friends.)<\/p>\n<p>Need to know how <code>4941438976<\/code> converts to HEX? No issue, just right click, and you have it as <code>0x1 2688 6000<\/code>. As simple as that.<\/p>\n<p>Okay, so we&rsquo;ve used the mouse. Maybe you use the mouse to switch the tabs? No need for that&hellip; By default, you should be able to switch tabs by hitting <code>Ctrl+PgUp<\/code> and <code>Ctrl+PgDn<\/code>. (That&rsquo;s why I hate most laptop keyboard layouts, because I need to press that pesky <code>Fn<\/code> too.) BTW. that trick might work in other Linux apps too. If not, try <code>Ctrl+Tab<\/code> and <code>Ctrl+Shift+Tab<\/code>.<\/p>\n<p>Okay, but to switch the tabs, one needs to open them first. Again, no need to touch the mouse. <code>Ctrl+Shift+T<\/code>, and the new tab is spawned. Don&rsquo;t like it anymore? When using <code>Bash<\/code>, you should be able to quit by hitting <code>Ctrl+D<\/code>.\nWhat you can do with your mouse, is drag-n-drop your tabs to reorder them, move them between terminal windows or even create new windows.<\/p>\n<p>By default, at least in Ubuntu, you should also be able to copy and paste using keyboard too. &lsquo;But how, it doesn&rsquo;t work, I&rsquo;ve tried <code>Ctrl+C<\/code>!&rsquo;. Well, that&rsquo;s because <code>Ctrl + C<\/code> most probably sends <code>SIGINT<\/code>, so you&rsquo;re telling the current programme to <a href=\"https:\/\/en.wikipedia.org\/wiki\/Control-C#In_command-line_environments\">C-ancel<\/a>. To copy the current selection (created with mouse first), hit <code>Ctrl+Shift+C<\/code>. To paste, hit <code>Ctrl+Shift+V<\/code>.<\/p>\n<p>However, since you&rsquo;re selecting with your mouse anyway, why not paste with the mouse? No, I don&rsquo;t mean right click, selecting &lsquo;Copy&rsquo;, then right click again to choose &lsquo;Paste&rsquo;. In many environments you can simply select some text (usually left button) and then paste it directly, by clicking&hellip; the wheel. By this I don&rsquo;t mean just the terminal emulator, but your IDE, word processor, Excel-like stuff, browser, etc.<\/p>\n<p>Speaking of terminal, if you need to make the font bigger (because you&rsquo;ve found <code>tail -f \/var\/log\/...<\/code> really immersing), no need to point-n-click. You should be able to do that with <code>Ctrl++<\/code>. That is, Control plus plus, which in my layout actually ends up with <code>Ctrl+Shift+=<\/code>. To reverse, just <code>Ctrl+-<\/code>.<\/p>\n<p>That&rsquo;s it for today. I hope the terminal will be a bit friendlier for you now.<\/p>\n"},{"title":"On Security Factors","link":"https:\/\/softwaregarden.dev\/en\/posts\/security\/myths-and-factors\/","pubDate":"Thu, 26 Nov 2020 10:00:00 +0200","guid":"https:\/\/softwaregarden.dev\/en\/posts\/security\/myths-and-factors\/","description":"<p>This post should have a nicer title, but I can&rsquo;t find it. It&rsquo;s about security factors. In a way it might be a missing link between two of my talks: <a href=\"https:\/\/softwaregarden.dev\/en\/talks\/passwords\/\">Passwords. Do you keep them safe?<\/a> and <a href=\"https:\/\/softwaregarden.dev\/en\/talks\/context\/\">CONTEXTVS, STVLTE!<\/a>. And again, it&rsquo;s somewhat &lsquo;What did I just see here?!?&rsquo; driven, sometimes because my work, sometimes not ;-)<\/p>\n<p>Passwords&hellip; Authentication&hellip; They were discussed so many times, you can find really many articles, thesis explaining, discussing, and comparing them. Not to mention dozens of cool and fancy advertisements that you&rsquo;ll be safe, just use <em>our product<\/em>. So maybe this post is about these products&hellip;? And equality&hellip;? I&rsquo;m not going to discuss \u00e9galit\u00e9 in general (along with libert\u00e9 et fraternit\u00e9). I&rsquo;m not a mathematician, statistician or a cryptologist (that&rsquo;s obvious, I&rsquo;m not from Lviv), but I&rsquo;ve been here and there and I saw things.<\/p>\n<figure class=\"image image left\">\n<img src=\"keep_it_secret.jpg\" alt=\"keep it secret\" width=\"300\">\n<\/figure>\n\n<p>In my option the biggest threat to IT security in general is repeating and believing the mantra &lsquo;oh, just do X, and you gonna be safe&rsquo;. Examples? Here you go:<\/p>\n<ul>\n<li>your password needs to have big &amp; small characters, numbers and special characters; if not, it&rsquo;s rubbish<\/li>\n<li>single use passwords are the best passwords, no matter what<\/li>\n<li>using hardware tokens and biometrics should be used instead of passwords<\/li>\n<li>obscurity is security<\/li>\n<li>security is about doing something only once<\/li>\n<li>and so on.<\/li>\n<\/ul>\n<figure class=\"image image right\">\n<img src=\"pue.png\" alt=\"P@ssw0rd\" width=\"400\">\n<\/figure>\n\n<h4 id=\"pssw0rd\">P@ssw0rd<\/h4>\n<p>Let&rsquo;s start with a <code>P@ssw0rd<\/code>. It&rsquo;s an ever-green. Literally. We love green, we love to be green, go to the woods, have green builds, use green energy, have a lot of green papers, and see a green meter next to our password.<\/p>\n<p>Question: is <code>P@ssw0rd<\/code> really a safe, unique password? Is it so difficult to guess? Dear full-stack developer, is your JS password strength meter, showing <code>P@ssw0rd<\/code> green, aware of dictionary attacks? Does it know that the <code>joe@example.com<\/code> has this very <code>P@ssw0rd<\/code> assigned in 17 other pages? Not quite? So why on Earth do you keep using these meters to fool the users, or worse, fool yourself, that this password is safe, because it has:<\/p>\n<ul>\n<li>a big letter =&gt; P<\/li>\n<li>a &lsquo;special&rsquo; character =&gt; @<\/li>\n<li>a number =&gt; 0<\/li>\n<\/ul>\n<p>Once again, I&rsquo;m not sure if anything explains that better than the <a href=\"https:\/\/xkcd.com\/936\/\">&lsquo;correct horse battery staple&rsquo;<\/a> strip.<\/p>\n<p>That&rsquo;s why forcing people to satisfy a regex with their password and get a green bar based on that might not be wise. Worse, if there&rsquo;s a limitation on the password length (like 16 characters max), it&rsquo;s stupid for sure, because it&rsquo;s preventing people from using passwords easy to remember and with high guessing entropy.<\/p>\n<h4 id=\"just-this-one-time-baby\">Just this one time, baby<\/h4>\n<p>Single-use passwords are neat, aren&rsquo;t they? What if I told you, my fellow developer, <em>not always<\/em>?\nIf you have a list of pre-generated single-use passwords (and you really keep it secret), or your singe-use codes are generated by a nice hardware token, and they&rsquo;re used when you have to log in to a system, that might be neat. It seems that you&rsquo;re using a multi-factor authentication, nice. However, this is situational.<\/p>\n<p>If you use the same mechanism not for authenticating yourself (confirming you are you), but let&rsquo;s say, confirming a bank transfer (send XXX$ to YYY, pretty please), is it still <em>that<\/em> safe? Sure, a salesman will tell you &lsquo;of course it is, our hardware token generates a unique key every X seconds, there&rsquo;s a gazillion of combinations, impossible to guess, we&rsquo;re synchronising this with a cesium atomic clock&rsquo; and so on.\nThen let me ask you this question: does this token show you to whom the money is going to be sent and how much?<\/p>\n<p>The printed list\/card of single-use codes can&rsquo;t do that. Your hardware token showing only some codes can&rsquo;t do that either. So if you&rsquo;re really unlucky, it might be you&rsquo;ve just entered your second-factor code in a page which looks like your bank, but it&rsquo;s not, the super-duper-secure-second-factor single-use code just confirmed you&rsquo;ve sent all your money far, far away.<\/p>\n<p>Therefore, a single-use code, used as a second factor, is not equally safe in all situations. Because (surprise, surprise), the <em>context<\/em> is also needed. If it&rsquo;s obvious and always the same (like authentication), good. If you use it in altering context without knowing the context, not equally good.<\/p>\n<h4 id=\"give-me-a-hand-please\">Give me a hand, please<\/h4>\n<p>If I was given a penny, just one penny, every time I hear or see &lsquo;passwords are hard\/old-fashioned\/always insecure and should be replaced by biometrics or hardware&rsquo;, I&rsquo;d be at least a few pounds richer by now.<\/p>\n<p>Adding one factor to another factor doesn&rsquo;t sound bad in general. However, <em>replacing<\/em> one factor with another factor is another story.<\/p>\n<p>Factors can be grouped in categories, e.g:<\/p>\n<ul>\n<li>something you know: a password, your wedding anniversary (you do remember that, right?), your dog&rsquo;s name (c&rsquo;mon, everyone knows it, Susan posted that on Facebook last summer, don&rsquo;t you remember?), your swipe pattern<\/li>\n<li>something you have: a debit card, a piece of hardware, your fingerprints<\/li>\n<\/ul>\n<p>They can be divided in other aspects too, like:<\/p>\n<ul>\n<li>something that can be changed or changes: a password, a sequence of characters generated somewhere<\/li>\n<li>something that cannot (easily) change: your birthdate, your social security number, your fingerprints (usually 10) (some research shows your fingerprints can change e.g. due to stress)<\/li>\n<\/ul>\n<p>Some people just love counting. When they see anything having &lsquo;factor&rsquo; in name, they just put a strong &lsquo;check&rsquo; \u2714\ufe0f next to it, then count the checks \u2714\ufe0f and announce &lsquo;we&rsquo;ve implemented two-factor authentication, because we have two checks \u2714\ufe0f!&rsquo;\nNope. If you use the same factor N times, it&rsquo;s not an N-factor security. It&rsquo;s still one factor, used N times, that&rsquo;s it. So if you ask your customers their password AND their birthdate, it&rsquo;s not 2FA. To have a multi-factor authentication, you need to have multiple types of factors, not the same kind of factor repeated many times.<\/p>\n<p>Sometimes one factor gets replaced by another and such replacement is justified more or less by &lsquo;people are weak at X, so let&rsquo;s replace it with Y&rsquo;. Many times we want such replacement, because one factor is more convenient to use. Having a smartwatch on your wrist or swiping a finger on a reader is much easier than entering a (masked) password after all.<\/p>\n<p>However, there might be one more ways the security factors can be divided:<\/p>\n<ul>\n<li>things that can be &rsquo;taken&rsquo; from you and you don&rsquo;t even notice: your password (if you wrote it on a sticker or if it&rsquo;s simple to guess), your SSN, name of your dog<\/li>\n<li>things that can be &rsquo;taken&rsquo; from you when you&rsquo;re unconscious: your phone, your fingerprints, your phone which can be unlocked by your fingerprint (even when you&rsquo;re dead)<\/li>\n<li>things that cannot be taken from you without you knowing it: your password (if you keep it in your brain only)<\/li>\n<\/ul>\n<p>I wish I could add &rsquo;things that cannot be taken from you in any way&rsquo;, but there&rsquo;s always a baseball bat attack vector or drugs. There&rsquo;s one more obvious point though:<\/p>\n<ul>\n<li>things that cannot be taken from you when you&rsquo;re no more: things only you know (like memorised password).<\/li>\n<\/ul>\n<p>It&rsquo;s not my intention to put you in a situation when you have to experience such hard choices, but maybe it&rsquo;s worth thinking about such dilemmas, because being aware of them doesn&rsquo;t harm. Especially, when it&rsquo;s about trading security (and maybe chances of being kept alive) with convenience, because it might not always be about terminal situations. Being robbed, because your smartwatch opened the Sesame, being arrested and groundlessly accused because your phone &rsquo;testified something&rsquo;, etc. I know there are attempts in some law systems here and there to make revealing your password obligatory, but I guess it might be still legal to forget the password due to some stress.<\/p>\n<p>That&rsquo;s why I dare to say<\/p>\n<h3 id=\"not-all-security-factors-are-equal\">Not all security factors are equal<\/h3>\n<p>Just because people use weak passwords (the green meter again), it doesn&rsquo;t mean automatically, that the what-I-have factor is ultimately better that the what-only-I-know factor. Or because aggressive marketing tells you so.<\/p>\n<p>Maybe Jinx &amp; 007 can explain that better than I do ;-)<\/p>\n\n<div style=\"position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;\">\n  <iframe src=\"https:\/\/www.youtube-nocookie.com\/embed\/y2Me95Hki20?start=209&end=229\" style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;\" allowfullscreen title=\"YouTube Video\"><\/iframe>\n<\/div>\n\n<p>Stay safe, folks.<\/p>\n"},{"title":"JAVIPS Online","link":"https:\/\/softwaregarden.dev\/en\/posts\/events\/javips-2020\/","pubDate":"Thu, 22 Oct 2020 22:00:00 +0200","guid":"https:\/\/softwaregarden.dev\/en\/posts\/events\/javips-2020\/","description":"<h3 id=\"javipstalks\">#JAVIPStalks<\/h3>\n<p>On 22nd Oct I had a great pleasure to take part in the JAVIPS online 2020. Due to the pandemic it was different than all the previous events ogranised by Kasia &amp; Asia, but boy, it was so much joy and inspiration. I was able to <del>interrogate<\/del> moderate discussion during Jarek Pa\u0142ka&rsquo;s awesome talk on jumping into Java performance. The bad news for you is that it was all encrypted in Polish. Sorry. ;-)<\/p>\n<p>PS. Since I wasn&rsquo;t the speaker but the moderator only, this is not listed in my talks.<\/p>\n"},{"title":"Surfing Java\u2122 12-16","link":"https:\/\/softwaregarden.dev\/en\/talks\/surfing-java-12-16\/","pubDate":"Thu, 15 Oct 2020 10:00:00 +0200","guid":"https:\/\/softwaregarden.dev\/en\/talks\/surfing-java-12-16\/","description":"<p>In the dark ages, we had to wait for 3-4 years to see the new Java version with some new features. Now there are two major releases every year! Can we benefit from the new features before the next LTS release?<\/p>\n<p>We don\u2019t have to wait 3 years or so for new features any more. Isn\u2019t that cool? \ud83d\ude09 So\u2026 you\u2019d like to check what has happened since Java 11? Record types? Switch expressions? Pattern matching? No more NPE? String blocks? New functions in APIs? What are the Shenandoah and ZGC about? AppCDS to speed up spin-off?<\/p>\n<p>If you find them interesting, let\u2019s check out together new interesting stuff.<\/p>\n<p>In this talk (because it&rsquo;s limited to 45 minutes) I&rsquo;m able to merely scratch the surface of the changes. Please don&rsquo;t confuse it with a deep dive.<\/p>\n<p>I was able to give this talk at e.g. Java Developer Days, Od Kodera do Developera, CodeMotion Spain.<\/p>\n<div style=\"position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;\">\n      <iframe allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen\" loading=\"eager\" referrerpolicy=\"strict-origin-when-cross-origin\" src=\"https:\/\/www.youtube-nocookie.com\/embed\/baATb3B7NW8?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0\" style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;\" title=\"YouTube video\"><\/iframe>\n    <\/div>\n\n"},{"title":"Java 15. What's new and noteworthy?","link":"https:\/\/softwaregarden.dev\/en\/talks\/java-15-new-and-noteworthy\/","pubDate":"Fri, 09 Oct 2020 10:00:00 +0200","guid":"https:\/\/softwaregarden.dev\/en\/talks\/java-15-new-and-noteworthy\/","description":"<p>Another (half a) year has passed, another major Java\u2122 version has been released.\nJava was supposed &ldquo;to be slow&rdquo;. However, Java turns out to evolve so fast, that next releases aren&rsquo;t just version bumps, but might significantly change the game rules. That&rsquo;s a good reason for another deep dive in Java.\nWe&rsquo;re going to cover:<\/p>\n<ul>\n<li>Production ready GCs: ZGC and Shenandoah, if you don&rsquo;t like ice ages<\/li>\n<li>Text blocks, which make Strings easy to declare also for non-liners<\/li>\n<li>Pattern matching with instanceof A.K.A. Smart casting<\/li>\n<li>Records, where and how to use them, apart from DTO\/VO<\/li>\n<li>Sealed classes, new dimension of types visibility (for inheritance)<\/li>\n<li>Hidden classes, which are so hidden, that they can&rsquo;t even use themselves<\/li>\n<li>Foreign memory access, for some off-the-heap data<\/li>\n<li>Helpful NPE messages, which make chasing nulls easier than ever<\/li>\n<\/ul>\n<p>And of course removed, deprecated and tuned stuff (bye bye Nashorn). All visualised in actual code, not just slides.<\/p>\n<div style=\"position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;\">\n      <iframe allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen\" loading=\"eager\" referrerpolicy=\"strict-origin-when-cross-origin\" src=\"https:\/\/www.youtube-nocookie.com\/embed\/SfcBxnsyaME?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0\" style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;\" title=\"YouTube video\"><\/iframe>\n    <\/div>\n\n<p>So far this presentation has been delivered (as a Deep Dive) in Polish only, for WarszawaJUG.\nUnfortunately, during the streaming there were some&hellip; resolution challenges ;-)<\/p>\n<p>That&rsquo;s why if you&rsquo;d like to see my screen only (no organisers&rsquo; slides and talking heads), it&rsquo;s possible as well: the FullHD <a href=\"https:\/\/youtu.be\/QncF-yLjYTc\">recording<\/a> has been published on YT.<\/p>\n"},{"title":"Java Records tortured with Lombok again","link":"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/records\/vs-lombok-again\/","pubDate":"Thu, 08 Oct 2020 23:00:00 +0200","guid":"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/records\/vs-lombok-again\/","description":"<p><em>Update April 2021: Please note this post is about Java 15, with records as preview feature. Things have changed, the update is available in <a href=\"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/records\/vs-lombok-yet-again-with-builder-pattern\/\">another post<\/a>.<\/em><\/p>\n<h3 id=\"why-so-serious\">Why so serious?<\/h3>\n<p>In one of my <a href=\"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/records\/vs-lombok\/\">previous posts<\/a> I was torturing Java\u2122 Records using Lombok. After receiving some really encouraging comments (&lsquo;what a sick idea you have, respect!&rsquo;), delivering a deep-dive talk <a href=\"https:\/\/softwaregarden.dev\/en\/talks\/java-15-new-and-noteworthy\/\">&ldquo;Java 15. What&rsquo;s new and noteworthy&rdquo;<\/a>, and some discussions on JVM Poland Slack channel<a href=\"#slack\">*<\/a>, I&rsquo;ve decided to keep torturing. Sorry ;-)<\/p>\n<p>During the talk and discussing it after there were some, quite natural I&rsquo;d say, attempts to compare records to beans, Lomboked classes, and Scala&rsquo;s <code>case class<\/code>es. (Along with &lsquo;how do you feel about Java drawing ideas from Scala&rsquo; questions.)<\/p>\n<p>I don&rsquo;t mind Java getting ideas to evolve from anywhere. Being also Scala developer, I really don&rsquo;t see any issues with that, whether there was any inspiration or not.\nIn my opinion (at the moment of writing) Java Records are not quite the same as Scala case classes and have somewhat different philosophies, but both can be used in the very same way: as immutable data carriers.<\/p>\n<p>I prefer my data carriers to be immutable first, and then opened to mutability if that&rsquo;s really necessary and justified. Also, I don&rsquo;t see immutability as any sort of big issue anyway. Have you recently heard anyone complaining about immutable <code>String<\/code>s in Java? Or immutable <code>ZonedDateTime<\/code>? Exactly. On the other hand, how many issues did we face with mutable <code>java.util.Date<\/code>&hellip;?<\/p>\n<p>However, to be honest, sometimes we need to create new instances with a little &ldquo;but&rdquo;. Like &lsquo;I need this timestamp to be two minutes later&rsquo;. Then of course we don&rsquo;t mutate the <em>very same<\/em> object, but create a new one based on the original one. Something like:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;display:grid;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1<\/span><span><span style=\"color:#66d9ef\">var<\/span> i1 <span style=\"color:#f92672\">=<\/span> java.<span style=\"color:#a6e22e\">time<\/span>.<span style=\"color:#a6e22e\">Instant<\/span>.<span style=\"color:#a6e22e\">now<\/span>();\n<\/span><\/span><span style=\"display:flex; background-color:#3c3d38\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">2<\/span><span><span style=\"color:#66d9ef\">var<\/span> i2 <span style=\"color:#f92672\">=<\/span> i1.<span style=\"color:#a6e22e\">plusSeconds<\/span>(120)<\/span><\/span><\/code><\/pre><\/div>\n<p>This is something Java Records are missing, at least now.<\/p>\n<h3 id=\"meanwhile-in-scala\">Meanwhile in Scala<\/h3>\n<p>In Scala the case classes have a very handy <code>copy<\/code> method generated. Basically, it&rsquo;s a method with the same signature as the primary constructor and if an argument\/field is missing in the call, the value for such an argument\/field is copied from the object on which we&rsquo;re calling this method.<\/p>\n<p>Whoa! How can an argument to a method be missing in the call? Do you set <code>null<\/code> there (a fellow Java developer may ask)? Not really. Scala 2 has two nice features when it comes to methods: parameters might have default values and arguments to these parameters can be provided in any order, because they can be called by name, not only by position (like in Java).\nTherefore, having a <code>case class<\/code> like:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-scala\" data-lang=\"scala\"><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1<\/span><span><span style=\"color:#66d9ef\">case<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">CaseClass<\/span><span style=\"color:#f92672\">(<\/span>uno<span style=\"color:#66d9ef\">:<\/span> <span style=\"color:#66d9ef\">String<\/span><span style=\"color:#f92672\">,<\/span> dos<span style=\"color:#66d9ef\">:<\/span> <span style=\"color:#66d9ef\">String<\/span><span style=\"color:#f92672\">,<\/span> tres<span style=\"color:#66d9ef\">:<\/span> <span style=\"color:#66d9ef\">String<\/span><span style=\"color:#f92672\">)<\/span><\/span><\/span><\/code><\/pre><\/div>\n<p>we can create an instance of it:\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-scala\" data-lang=\"scala\"><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">2<\/span><span><span style=\"color:#66d9ef\">val<\/span> cc1 <span style=\"color:#66d9ef\">=<\/span> <span style=\"color:#a6e22e\">CaseClass<\/span><span style=\"color:#f92672\">(<\/span><span style=\"color:#e6db74\">&#34;u&#34;<\/span><span style=\"color:#f92672\">,<\/span> <span style=\"color:#e6db74\">&#34;d&#34;<\/span><span style=\"color:#f92672\">,<\/span> <span style=\"color:#e6db74\">&#34;t&#34;<\/span><span style=\"color:#f92672\">)<\/span><\/span><\/span><\/code><\/pre><\/div><\/p>\n<p>and then create an almost identical copy\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-scala\" data-lang=\"scala\"><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">3<\/span><span><span style=\"color:#66d9ef\">val<\/span> cc2 <span style=\"color:#66d9ef\">=<\/span> cc1<span style=\"color:#f92672\">.<\/span>copy<span style=\"color:#f92672\">(<\/span>dos<span style=\"color:#f92672\">=<\/span><span style=\"color:#e6db74\">&#34;two&#34;<\/span><span style=\"color:#f92672\">)<\/span><\/span><\/span><\/code><\/pre><\/div><\/p>\n<p>Yes, that makes <code>cc2<\/code>&rsquo;s fields <code>uno<\/code> and <code>tres<\/code> the same as in <code>cc1<\/code>, but <code>dos<\/code> keeps <code>&quot;two&quot;<\/code>. That makes creating new instances which share a lot of field values really nice.<\/p>\n<p>Let&rsquo;s say we&rsquo;d like to have something similar&hellip; We can&rsquo;t have anything identical, for Java doesn&rsquo;t have named parameters.<\/p>\n<figure class=\"image image right\">\n<img src=\"easy-choice.jpg\" alt=\"hold my beer\" width=\"300\">\n<\/figure>\n\n<h3 id=\"hold-my-beer\">Hold my beer<\/h3>\n<p>What comes to mind almost instantly is &lsquo;how about Lombok's <code>@With<\/code>&rsquo;? Please follow the <a href=\"https:\/\/projectlombok.org\/features\/With\">documentation of <code>@With<\/code><\/a>, as I don&rsquo;t want to repeat it with full details here.<\/p>\n<p>In short: if we have a Java Bean with field <code>name<\/code> and we prepend this field or annotate the bean class with <code>@With<\/code>, in the generated bytecode there will be a method <code>withName<\/code> which will return a new instance with all the fields being the same, except <code>name<\/code> set to whatever we passed to <code>withName<\/code>.<\/p>\n<p>Yeap, you&rsquo;re right, let&rsquo;s try to use Lombok with Java Record :-D\nThe idea looks tempting, but annotating a record with <code>@With<\/code> looks a bit weird in IDEA\u2122. The following code:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1<\/span><span><span style=\"color:#a6e22e\">@With<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">2<\/span><span><span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#66d9ef\">record<\/span> <span style=\"color:#a6e22e\">RecordWithWith<\/span>(String uno, String dos, String tres) {}<\/span><\/span><\/code><\/pre><\/div>\n<p>results with a notification on the annotation. You can take a look on your own:<\/p>\n<figure class=\"image image\">\n<img src=\"RecordWithWith.png\" alt=\"RecordWithWith\">\n<\/figure>\n\n<p>Records always have the &ldquo;full&rdquo; canonical constructor. Even adding one explicitly doesn&rsquo;t make this note vanish. However, maybe we can happily ignore it, because the generated bytecode seems  okay&hellip;? Decompiled it looks like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 1<\/span><span>  <span style=\"color:#75715e\">\/\/ IntelliJ API Decompiler stub source generated from a class file<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 2<\/span><span>  <span style=\"color:#75715e\">\/\/ Implementation of methods is not available<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 3<\/span><span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 4<\/span><span><span style=\"color:#f92672\">package<\/span> dev.softwaregarden.records.torture.lombok;\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 5<\/span><span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 6<\/span><span><span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#66d9ef\">final<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">RecordWithWith<\/span> <span style=\"color:#66d9ef\">extends<\/span> java.<span style=\"color:#a6e22e\">lang<\/span>.<span style=\"color:#a6e22e\">Record<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 7<\/span><span>    <span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#66d9ef\">final<\/span> java.<span style=\"color:#a6e22e\">lang<\/span>.<span style=\"color:#a6e22e\">String<\/span> uno;\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 8<\/span><span>    <span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#66d9ef\">final<\/span> java.<span style=\"color:#a6e22e\">lang<\/span>.<span style=\"color:#a6e22e\">String<\/span> dos;\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 9<\/span><span>    <span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#66d9ef\">final<\/span> java.<span style=\"color:#a6e22e\">lang<\/span>.<span style=\"color:#a6e22e\">String<\/span> tres;\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">10<\/span><span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">11<\/span><span>    <span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#a6e22e\">RecordWithWith<\/span>(java.<span style=\"color:#a6e22e\">lang<\/span>.<span style=\"color:#a6e22e\">String<\/span> uno, java.<span style=\"color:#a6e22e\">lang<\/span>.<span style=\"color:#a6e22e\">String<\/span> dos, java.<span style=\"color:#a6e22e\">lang<\/span>.<span style=\"color:#a6e22e\">String<\/span> tres) { <span style=\"color:#75715e\">\/* compiled code *\/<\/span> }\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">12<\/span><span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">13<\/span><span>    <span style=\"color:#66d9ef\">public<\/span> dev.<span style=\"color:#a6e22e\">softwaregarden<\/span>.<span style=\"color:#a6e22e\">records<\/span>.<span style=\"color:#a6e22e\">torture<\/span>.<span style=\"color:#a6e22e\">lombok<\/span>.<span style=\"color:#a6e22e\">RecordWithWith<\/span> <span style=\"color:#a6e22e\">withUno<\/span>(java.<span style=\"color:#a6e22e\">lang<\/span>.<span style=\"color:#a6e22e\">String<\/span> uno) { <span style=\"color:#75715e\">\/* compiled code *\/<\/span> }\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">14<\/span><span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">15<\/span><span>    <span style=\"color:#66d9ef\">public<\/span> dev.<span style=\"color:#a6e22e\">softwaregarden<\/span>.<span style=\"color:#a6e22e\">records<\/span>.<span style=\"color:#a6e22e\">torture<\/span>.<span style=\"color:#a6e22e\">lombok<\/span>.<span style=\"color:#a6e22e\">RecordWithWith<\/span> <span style=\"color:#a6e22e\">withDos<\/span>(java.<span style=\"color:#a6e22e\">lang<\/span>.<span style=\"color:#a6e22e\">String<\/span> dos) { <span style=\"color:#75715e\">\/* compiled code *\/<\/span> }\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">16<\/span><span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">17<\/span><span>    <span style=\"color:#66d9ef\">public<\/span> dev.<span style=\"color:#a6e22e\">softwaregarden<\/span>.<span style=\"color:#a6e22e\">records<\/span>.<span style=\"color:#a6e22e\">torture<\/span>.<span style=\"color:#a6e22e\">lombok<\/span>.<span style=\"color:#a6e22e\">RecordWithWith<\/span> <span style=\"color:#a6e22e\">withTres<\/span>(java.<span style=\"color:#a6e22e\">lang<\/span>.<span style=\"color:#a6e22e\">String<\/span> tres) { <span style=\"color:#75715e\">\/* compiled code *\/<\/span> }\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">18<\/span><span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">19<\/span><span>    <span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#66d9ef\">final<\/span> java.<span style=\"color:#a6e22e\">lang<\/span>.<span style=\"color:#a6e22e\">String<\/span> <span style=\"color:#a6e22e\">toString<\/span>() { <span style=\"color:#75715e\">\/* compiled code *\/<\/span> }\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">20<\/span><span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">21<\/span><span>    <span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#66d9ef\">final<\/span> <span style=\"color:#66d9ef\">int<\/span> <span style=\"color:#a6e22e\">hashCode<\/span>() { <span style=\"color:#75715e\">\/* compiled code *\/<\/span> }\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">22<\/span><span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">23<\/span><span>    <span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#66d9ef\">final<\/span> <span style=\"color:#66d9ef\">boolean<\/span> <span style=\"color:#a6e22e\">equals<\/span>(java.<span style=\"color:#a6e22e\">lang<\/span>.<span style=\"color:#a6e22e\">Object<\/span> o) { <span style=\"color:#75715e\">\/* compiled code *\/<\/span> }\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">24<\/span><span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">25<\/span><span>    <span style=\"color:#66d9ef\">public<\/span> java.<span style=\"color:#a6e22e\">lang<\/span>.<span style=\"color:#a6e22e\">String<\/span> <span style=\"color:#a6e22e\">uno<\/span>() { <span style=\"color:#75715e\">\/* compiled code *\/<\/span> }\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">26<\/span><span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">27<\/span><span>    <span style=\"color:#66d9ef\">public<\/span> java.<span style=\"color:#a6e22e\">lang<\/span>.<span style=\"color:#a6e22e\">String<\/span> <span style=\"color:#a6e22e\">dos<\/span>() { <span style=\"color:#75715e\">\/* compiled code *\/<\/span> }\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">28<\/span><span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">29<\/span><span>    <span style=\"color:#66d9ef\">public<\/span> java.<span style=\"color:#a6e22e\">lang<\/span>.<span style=\"color:#a6e22e\">String<\/span> <span style=\"color:#a6e22e\">tres<\/span>() { <span style=\"color:#75715e\">\/* compiled code *\/<\/span> }\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">30<\/span><span>}<\/span><\/span><\/code><\/pre><\/div>\n<p>Let&rsquo;s use these <code>with...<\/code> methods, shall we? Oopsie, red alert in IDEA:<\/p>\n<figure class=\"image image\">\n<img src=\"RedAlert.png\" alt=\"Red Alert\">\n<\/figure>\n\n<p>Hmmm&hellip; can we ignore it? Let&rsquo;s check the bytecode:\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 1<\/span><span><span style=\"color:#75715e\">\/\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 2<\/span><span><span style=\"color:#75715e\">\/\/ Source code recreated from a .class file by IntelliJ IDEA<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 3<\/span><span><span style=\"color:#75715e\">\/\/ (powered by FernFlower decompiler)<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 4<\/span><span><span style=\"color:#75715e\">\/\/<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 5<\/span><span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 6<\/span><span><span style=\"color:#f92672\">package<\/span> dev.softwaregarden.records.torture.lombok;\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 7<\/span><span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 8<\/span><span><span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">LombokAndRecordsCheck<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 9<\/span><span>    <span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#a6e22e\">LombokAndRecordsCheck<\/span>() {\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">10<\/span><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">11<\/span><span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">12<\/span><span>    <span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#66d9ef\">static<\/span> <span style=\"color:#66d9ef\">void<\/span> <span style=\"color:#a6e22e\">main<\/span>(String<span style=\"color:#f92672\">[]<\/span> args) {\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">13<\/span><span>        <span style=\"color:#66d9ef\">new<\/span> LombokedBean(1, <span style=\"color:#e6db74\">&#34;one&#34;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">14<\/span><span>        RecordWithWith rww1 <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> RecordWithWith(<span style=\"color:#e6db74\">&#34;1&#34;<\/span>, <span style=\"color:#e6db74\">&#34;a&#34;<\/span>, <span style=\"color:#e6db74\">&#34;Z&#34;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">15<\/span><span>        RecordWithWith rrw2 <span style=\"color:#f92672\">=<\/span> rww1.<span style=\"color:#a6e22e\">withDos<\/span>(<span style=\"color:#e6db74\">&#34;A&#34;<\/span>).<span style=\"color:#a6e22e\">withTres<\/span>(<span style=\"color:#e6db74\">&#34;z&#34;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">16<\/span><span>        System.<span style=\"color:#a6e22e\">out<\/span>.<span style=\"color:#a6e22e\">println<\/span>(rrw2);\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">17<\/span><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">18<\/span><span>}<\/span><\/span><\/code><\/pre><\/div><\/p>\n<p>It should be working then. Let&rsquo;s give it a spin. What do we see in the output window? This:\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-text\" data-lang=\"text\"><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1<\/span><span>Called constructor with [1], [a], [Z]\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">2<\/span><span>Called constructor with [1], [A], [Z]\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">3<\/span><span>Called constructor with [1], [A], [z]\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">4<\/span><span>RecordWithWith[uno=1, dos=A, tres=z]<\/span><\/span><\/code><\/pre><\/div><\/p>\n<p>Despite being red in IDE&rsquo;s editor, the code compiles and works.\nIt looks like we <em>could<\/em> do that, but I&rsquo;m not sure we <em>should<\/em>.\nI know, the &ldquo;red alert&rdquo; is not coming from IDEA&rsquo;s core code, the Lombok IDE plugin doesn&rsquo;t come from JetBrains and most probably it got fooled by the <code>record<\/code>.\nThe <em>real<\/em> compiler down below handled things as expected and made them run&hellip;\nHowever, please read the output with some extra care. I added the print statement in the constructor to demonstrate such a naive approach with subsequent <code>with...<\/code> calls results with subsequent objects being created. Not so nice for the performance, not so nice for this planet.<\/p>\n<p>&lsquo;Hey, maybe we could experiment with <code>@Builder<\/code>!&rsquo; I&rsquo;m not saying &rsquo;no&rsquo;, but maybe we should simply:\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1<\/span><span>RecordWithWith rww1 <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> RecordWithWith(<span style=\"color:#e6db74\">&#34;1&#34;<\/span>, <span style=\"color:#e6db74\">&#34;a&#34;<\/span>, <span style=\"color:#e6db74\">&#34;Z&#34;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">2<\/span><span>RecordWithWith rrw2 <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> RecordWithWith(rr1.<span style=\"color:#a6e22e\">uno<\/span>(), <span style=\"color:#e6db74\">&#34;A&#34;<\/span>, <span style=\"color:#e6db74\">&#34;z&#34;<\/span>);<\/span><\/span><\/code><\/pre><\/div><\/p>\n<p>Maybe it&rsquo;s not that bad? Maybe it&rsquo;s somewhat verbose, but easier to read? Maybe one day Java Records with have <code>with<\/code> methods generated by the compiler? We shall see in next 25 years. ;-)<\/p>\n<p>If your fingers are itchy, and you&rsquo;d like to torture records on your own, the code is on <a href=\"https:\/\/github.com\/pioorg\/recordsTorture\">Github<\/a>.<\/p>\n<p>\n<a name=\"slack\">*)<\/a>\n\nYou&rsquo;re more than welcome to join <a href=\"http:\/\/jvm-poland.slack.com\">JVM Poland<\/a> Slack channel. There&rsquo;s one caveat: the whole transmission is encrypted. We speak Polish. ;-)<\/p>\n"},{"title":"More on shebang in JavaScript(s)","link":"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/scripts\/more-on-shebang\/","pubDate":"Mon, 28 Sep 2020 08:00:00 +0200","guid":"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/scripts\/more-on-shebang\/","description":"<h3 id=\"a-few-more-words-about-shebang\">A few more words about <code>shebang<\/code><\/h3>\n<p>This is an update to the <a href=\"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/scripts\/java-scripts\/\">previous post<\/a>. I haven&rsquo;t discussed the portability of the &ldquo;script with shebang&rdquo; before, because I assumed that:<\/p>\n<ul>\n<li>this is a general scripting issue, not specific to Java\u2122,<\/li>\n<li>it was discussed in the Wikipedia link provided in the previous entry.<\/li>\n<\/ul>\n<p>However, it wasn&rsquo;t referenced directly, so here it comes, a direct link: <a href=\"https:\/\/en.wikipedia.org\/wiki\/Shebang_(Unix)#Portability\">portability of Unix shebang from Wikipedia<\/a>.<\/p>\n<p>Let&rsquo;s discuss this then. Shebang is an absolute path. That&rsquo;s obvious, because the script should work everywhere. The <em>everywhere<\/em> applies not only to <em>every directory<\/em>, but also <em>every computer<\/em>. Because of that, putting in shebang something like <code>\/home\/piotr\/.sdkman<\/code>&hellip; works only for some demo or evaluation. Else, for any kind of serious usage, it&rsquo;s one of those Really Bad Ideas\u2122.<\/p>\n<p>What shall be used then? It really depends, sadly there&rsquo;s no one-size-fits-all solution, at least I&rsquo;m not aware of it. Therefore, my first suggestion would be to ask someone who knows the context you&rsquo;re in, like a sysadmin, DevOps friends, etc. (If they&rsquo;re okay with such &ldquo;scripting&rdquo; in the first place. ;-) )<\/p>\n<p>Nevertheless, there are some paths you can try to follow here. You can start with <code>#!\/usr\/bin\/java<\/code>. If you&rsquo;re using the SDK MANager, and you switch the versions\/vendors often, you might go for <code>\/home\/YOUR-USERNAME\/.sdkman\/candidates\/java\/current\/bin\/java<\/code>.\nUnfortunately, something like <code>#!\/usr\/bin\/env java --source 11<\/code> doesn&rsquo;t work just like that. When I try to use such a shebang on my machine, an error is shown:\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-bash\" data-lang=\"bash\"><span style=\"display:flex;\"><span>\/usr\/bin\/env: \u2018java --source 11\u2019: No such file or directory<\/span><\/span><\/code><\/pre><\/div>\nIt&rsquo;s caused by <a href=\"https:\/\/en.wikipedia.org\/wiki\/Shebang_(Unix)#Character_interpretation\">character interpolation<\/a>, because <code>env<\/code> can&rsquo;t split <code>java --source 11<\/code> and is looking for a programme with exactly this name. There&rsquo;s not much we can do about that in many systems, like Ubuntu 18.04 LTS with <code>env<\/code> version 8.28.<\/p>\n<p>Things look different in other OSes and in recent GNU\/Linux versions, I&rsquo;ve tested FreeBSD 11 and Ubuntu 20.04 LTS. If you&rsquo;re using one of them, or GNU\/Linux with a modern <code>env<\/code> version (like 8.30 or later), you can use -S, which splits the command and its arguments.<\/p>\n<p>Then the shebang can look like this:\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-bash\" data-lang=\"bash\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">#!\/usr\/bin\/env -S java --source 11<\/span><\/span><\/span><\/code><\/pre><\/div><\/p>\n<p>What&rsquo;s more, the <code>-S<\/code> caused also other parameters to work. Using that we can also set the classpath and other stuff.<\/p>\n<p>In the following snippet we&rsquo;re going to (over)use Apache Commons Lang, to check if none of the passed arguments is <code>password<\/code>:\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 1<\/span><span><span style=\"color:#960050;background-color:#1e0010\">#<\/span><span style=\"color:#f92672\">!\/<\/span>usr<span style=\"color:#f92672\">\/<\/span>bin<span style=\"color:#f92672\">\/<\/span>env <span style=\"color:#f92672\">-<\/span>S java <span style=\"color:#f92672\">--<\/span>source 8\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 2<\/span><span><span style=\"color:#f92672\">import<\/span> org.apache.commons.lang3.ArrayUtils;\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 3<\/span><span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 4<\/span><span><span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">ClasspathExample<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 5<\/span><span>    <span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#66d9ef\">static<\/span> <span style=\"color:#66d9ef\">void<\/span> <span style=\"color:#a6e22e\">main<\/span>(String<span style=\"color:#f92672\">[]<\/span> args){\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 6<\/span><span>        <span style=\"color:#66d9ef\">if<\/span> (ArrayUtils.<span style=\"color:#a6e22e\">contains<\/span>(args, <span style=\"color:#e6db74\">&#34;password&#34;<\/span>)) {\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 7<\/span><span>            System.<span style=\"color:#a6e22e\">out<\/span>.<span style=\"color:#a6e22e\">println<\/span>(<span style=\"color:#e6db74\">&#34;Don&#39;t pass passwords as arguments.&#34;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 8<\/span><span>        } <span style=\"color:#66d9ef\">else<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 9<\/span><span>            System.<span style=\"color:#a6e22e\">out<\/span>.<span style=\"color:#a6e22e\">println<\/span>(<span style=\"color:#e6db74\">&#34;Password not detected in arguments.&#34;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">10<\/span><span>        }\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">11<\/span><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">12<\/span><span>}<\/span><\/span><\/code><\/pre><\/div><\/p>\n<p>Of course, it&rsquo;s not going to work if we don&rsquo;t have Commons Lang JAR in your default classpath (which I think shouldn&rsquo;t be the case, if you&rsquo;d like to know my opinion, because of the JAR hell). It fails more or less this way:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-bash\" data-lang=\"bash\"><span style=\"display:flex;\"><span>$ .\/classpathScript.example \n<\/span><\/span><span style=\"display:flex;\"><span>.\/classpathScript.example:2: error: package org.apache.commons.lang3 does not exist\n<\/span><\/span><span style=\"display:flex;\"><span>import org.apache.commons.lang3.ArrayUtils;\n<\/span><\/span><span style=\"display:flex;\"><span>                               ^\n<\/span><\/span><span style=\"display:flex;\"><span>.\/classpathScript.example:6: error: cannot find symbol\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#66d9ef\">if<\/span> <span style=\"color:#f92672\">(<\/span>ArrayUtils.contains<span style=\"color:#f92672\">(<\/span>args, <span style=\"color:#e6db74\">&#34;password&#34;<\/span><span style=\"color:#f92672\">))<\/span> <span style=\"color:#f92672\">{<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>            ^\n<\/span><\/span><span style=\"display:flex;\"><span>  symbol:   variable ArrayUtils\n<\/span><\/span><span style=\"display:flex;\"><span>  location: class ClasspathExample\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#ae81ff\">2<\/span> errors\n<\/span><\/span><span style=\"display:flex;\"><span>error: compilation failed<\/span><\/span><\/code><\/pre><\/div>\n<p>There are at least three options here (provided we&rsquo;re not going to remove the import):<\/p>\n<ul>\n<li>add the JAR to the default classpath (not recommended IMO),<\/li>\n<li>set the CLASSPATH environment variable during the call (doable, but verbose),<\/li>\n<li>set the classpath in shebang, which we&rsquo;re going to explore here.<\/li>\n<\/ul>\n<p>Let&rsquo;s update the last example then (assuming we keep the JARs the old-fashion way, like <code>\/usr\/local\/share\/...<\/code>):\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 1<\/span><span><span style=\"color:#960050;background-color:#1e0010\">#<\/span><span style=\"color:#f92672\">!\/<\/span>usr<span style=\"color:#f92672\">\/<\/span>bin<span style=\"color:#f92672\">\/<\/span>env <span style=\"color:#f92672\">-<\/span>S java <span style=\"color:#f92672\">--<\/span><span style=\"color:#66d9ef\">class<\/span><span style=\"color:#960050;background-color:#1e0010\">-<\/span><span style=\"color:#a6e22e\">path<\/span> <span style=\"color:#f92672\">\/<\/span>usr<span style=\"color:#f92672\">\/<\/span>local<span style=\"color:#f92672\">\/<\/span>share<span style=\"color:#f92672\">\/<\/span>JARs<span style=\"color:#f92672\">\/<\/span>commons<span style=\"color:#f92672\">-<\/span>lang3<span style=\"color:#f92672\">-<\/span>3.<span style=\"color:#a6e22e\">11<\/span>.<span style=\"color:#a6e22e\">jar<\/span> <span style=\"color:#f92672\">--<\/span>source 8 <span style=\"color:#f92672\">-<\/span>Xmx100m \n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 2<\/span><span><span style=\"color:#f92672\">import<\/span> org.apache.commons.lang3.ArrayUtils;\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 3<\/span><span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 4<\/span><span><span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">ClasspathExample<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 5<\/span><span>    <span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#66d9ef\">static<\/span> <span style=\"color:#66d9ef\">void<\/span> <span style=\"color:#a6e22e\">main<\/span>(String<span style=\"color:#f92672\">[]<\/span> args){\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 6<\/span><span>        <span style=\"color:#66d9ef\">if<\/span> (ArrayUtils.<span style=\"color:#a6e22e\">contains<\/span>(args, <span style=\"color:#e6db74\">&#34;password&#34;<\/span>)) {\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 7<\/span><span>            System.<span style=\"color:#a6e22e\">out<\/span>.<span style=\"color:#a6e22e\">println<\/span>(<span style=\"color:#e6db74\">&#34;Don&#39;t pass passwords as arguments.&#34;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 8<\/span><span>        } <span style=\"color:#66d9ef\">else<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 9<\/span><span>            System.<span style=\"color:#a6e22e\">out<\/span>.<span style=\"color:#a6e22e\">println<\/span>(<span style=\"color:#e6db74\">&#34;Password not detected in arguments.&#34;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">10<\/span><span>        }\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">11<\/span><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">12<\/span><span>}<\/span><\/span><\/code><\/pre><\/div><\/p>\n<p>It runs very nice with OpenJDK 11.0.7 and 11.0.8 (at the moment of writing):<\/p>\n<figure class=\"image image\">\n<img src=\"java11-freebsd.png\" alt=\"Java 11 on FreeBSD 11.3\" width=\"660\">\n<\/figure>\n\n<p>So, do we have it? Do we have a portable* script with shebang, which will work in FreeBSD in Ubuntu, with all Java versions? Well, not so fast&hellip; This works with Java 11. If you&rsquo;d like to run it with, let&rsquo;s say, Java 15 (which is the supported version at the moment of writing), then you have to put e.g. <code>--class-path<\/code> after the <code>--source<\/code>, as demonstrated in the picture below:<\/p>\n<figure class=\"image image\">\n<img src=\"java15-ubuntu.png\" alt=\"Java 15 on Ubuntu 20.04\" width=\"660\">\n<\/figure>\n\n<p>Please note this has nothing to do with the operating system AFAICT. It&rsquo;s about the <code>java<\/code>&rsquo;s behaviour when reading the parameters, as depicted e.g. in ticket <a href=\"https:\/\/bugs.openjdk.java.net\/browse\/JDK-8242911\">JDK-8242911<\/a>. However, I can&rsquo;t tell if it&rsquo;s a bug or a feature. Nevertheless, please be aware (when talking about the &ldquo;portability&rdquo;) that not only the order of the JARs in the classpath matters, but that the position of the <code>--class-path<\/code> argument matters too! ;-) And maybe setting the <code>CLASSPATH<\/code> environment variable isn&rsquo;t that bad after all&hellip;<\/p>\n<p>So for Java 15 the shebang from above has to be set as:\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1<\/span><span><span style=\"color:#960050;background-color:#1e0010\">#<\/span><span style=\"color:#f92672\">!\/<\/span>usr<span style=\"color:#f92672\">\/<\/span>bin<span style=\"color:#f92672\">\/<\/span>env <span style=\"color:#f92672\">-<\/span>S java <span style=\"color:#f92672\">--<\/span>source 8 <span style=\"color:#f92672\">-<\/span>Xmx100m <span style=\"color:#f92672\">--<\/span><span style=\"color:#66d9ef\">class<\/span><span style=\"color:#960050;background-color:#1e0010\">-<\/span><span style=\"color:#a6e22e\">path<\/span> <span style=\"color:#f92672\">\/<\/span>usr<span style=\"color:#f92672\">\/<\/span>local<span style=\"color:#f92672\">\/<\/span>share<span style=\"color:#f92672\">\/<\/span>JARs<span style=\"color:#f92672\">\/<\/span>commons<span style=\"color:#f92672\">-<\/span>lang3<span style=\"color:#f92672\">-<\/span>3.<span style=\"color:#a6e22e\">11<\/span>.<span style=\"color:#a6e22e\">jar<\/span> <\/span><\/span><\/code><\/pre><\/div><\/p>\n<h3 id=\"summary\">Summary<\/h3>\n<p>I won&rsquo;t risk here giving you a silver bullet &rsquo;this will work for sure&rsquo; when it comes to shebang in &ldquo;Java Scripts&rdquo;, because I&rsquo;ve seen way too many ways Java is &ldquo;installed&rdquo; or &ldquo;deployed&rdquo;. As you&rsquo;ve seen, this also varies between versions. Not this time, sorry ;-)\nHowever, if your OS supports this, and it matches the way you have Java installed, you can start with:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-bash\" data-lang=\"bash\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">#!\/usr\/bin\/env -S java --source 11<\/span><\/span><\/span><\/code><\/pre><\/div>\n<p>Also, please remember: just because you can, doesn&rsquo;t mean you should. Maybe just sticking to the good ol&rsquo; <code>java -jar myProgramme.jar<\/code> could save you some headaches.<\/p>\n"},{"title":"JavaScript(s)!","link":"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/scripts\/java-scripts\/","pubDate":"Thu, 24 Sep 2020 13:50:47 +0200","guid":"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/scripts\/java-scripts\/","description":"<h3 id=\"java-version-script\">Java, version Script<\/h3>\n<p>There&rsquo;s an old joke where I live about the IT recruiters and IT folks. I don&rsquo;t find it <em>that<\/em> funny, hence I&rsquo;ll spoil it: it&rsquo;s about one person trying to hire another person and one of them knows &lsquo;<em>Java<\/em>&rsquo;, while the other needs &lsquo;<em>Java, version script<\/em>&rsquo;. Or the other way round ;-) Anyway, this similarity in names of these programming languages in not a coincidence, as you may read in <a href=\"https:\/\/en.wikipedia.org\/wiki\/JavaScript#History\">Wikipedia<\/a>.<\/p>\n<p>Many non-Java developers find it shocking, that it&rsquo;s possible these days to write a script (which will run in CLI) not only in Bash, Perl, Python, PHP, etc, but also in Java\u2122. Frankly speaking, if &lsquo;Java version script&rsquo; can run backends now, why scripts can&rsquo;t be written in Java?<\/p>\n<p>This post is not about <code>jshell<\/code>, which can be used both as a REPL, both to run in a batch mode. I&rsquo;d like to show you how you can run a &lsquo;script&rsquo;, or cron it, without creating <code>.class<\/code> or <code>.jar<\/code> files. Heck, the scripts don&rsquo;t even need to be placed in files with <code>.java<\/code> extension!<\/p>\n<h4 id=\"hello-world-again\">Hello World (again)&hellip;<\/h4>\n<p>Without further ado: you know this code, right?\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1<\/span><span><span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">HelloWorldExample<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">2<\/span><span>    <span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#66d9ef\">static<\/span> <span style=\"color:#66d9ef\">void<\/span> <span style=\"color:#a6e22e\">main<\/span>(String<span style=\"color:#f92672\">[]<\/span> args) {\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">3<\/span><span>        System.<span style=\"color:#a6e22e\">out<\/span>.<span style=\"color:#a6e22e\">println<\/span>(<span style=\"color:#e6db74\">&#34;Hello, World!&#34;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">4<\/span><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">5<\/span><span>}<\/span><\/span><\/code><\/pre><\/div><\/p>\n<p>Let&rsquo;s say that this is a fancy script you need to call. It doesn&rsquo;t have to be blazing fast, it should just do the job. Also, you have Java 11+ installed. Plus you&rsquo;re not mastering Bash\/Zsh\/Perl\/whatever-other-scripting-language-you-might-have&hellip;<\/p>\n<p>What&rsquo;s also important, you don&rsquo;t want to run the well-known cycle of edit-&gt;compile-&gt;run. Pretty much like in Python, you&rsquo;d like to edit a text file (or send a snippet to your friend), save it, then run it. If &ldquo;the technology under the hood&rdquo; needs to compile it\/interpret it\/shave a yak, fine, so be it! You just want the thing to run, because it&rsquo;s getting late, and your manager really doesn&rsquo;t care.<\/p>\n<p>So what can you do? Let&rsquo;s say the file is saved as <code>HelloWorldExample.java<\/code>.\nThen you can run\/execute this file the following way:\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-bash\" data-lang=\"bash\"><span style=\"display:flex;\"><span>$ java HelloWorldExample.java<\/span><\/span><\/code><\/pre><\/div><\/p>\n<p>The standard output is:\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-bash\" data-lang=\"bash\"><span style=\"display:flex;\"><span>Hello, World!<\/span><\/span><\/code><\/pre><\/div><\/p>\n<p>Now, you don&rsquo;t need to trust me. You can check on your own, that there&rsquo;s no <code>HelloWorldExample.class<\/code> file in current directory on your machine. Everything happened &lsquo;under the hood&rsquo; and &lsquo;on the flight&rsquo;. In this case the <code>java<\/code> acts like an &ldquo;interpreter&rdquo;.<\/p>\n<p>Wait, that&rsquo;s not all! I&rsquo;ve promised you a script without explicit &ldquo;interpreter&rdquo; when calling, so here it comes.<\/p>\n<h3 id=\"run-example-run\">Run example, run<\/h3>\n<p><figure class=\"image image right\">\n<img src=\"running-498257_640.jpg\" alt=\"run\" width=\"350\">\n<figcaption>\n<p><a href=\"https:\/\/pixabay.com\/pl\/users\/RyanMcGuire-123690\/?utm_source=link-attribution&amp;amp;utm_medium=referral&amp;amp;utm_campaign=image&amp;amp;utm_content=498257\">Picture by Ryan McGuire from Pixabay<\/a><\/p>\n<\/figcaption>\n<\/figure>\n\nFirst, you should find out the location of your <code>java<\/code> command. You can do that by calling <code>which java<\/code> in the terminal. In my case it&rsquo;s <code>\/home\/piotr\/.sdkman\/candidates\/java\/15-open\/bin\/java<\/code>, your results might be different, depending on how and where you have Java installed.<\/p>\n<p>Next, let&rsquo;s copy the <code>HelloWorldExample.java<\/code> to a file <code>hello.script<\/code>. Then let&rsquo;s prepend one line to this file, so it looks like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1<\/span><span><span style=\"color:#960050;background-color:#1e0010\">#<\/span><span style=\"color:#f92672\">!\/<\/span>home<span style=\"color:#f92672\">\/<\/span>piotr<span style=\"color:#f92672\">\/<\/span>.<span style=\"color:#a6e22e\">sdkman<\/span><span style=\"color:#f92672\">\/<\/span>candidates<span style=\"color:#f92672\">\/<\/span>java<span style=\"color:#f92672\">\/<\/span>15<span style=\"color:#f92672\">-<\/span>open<span style=\"color:#f92672\">\/<\/span>bin<span style=\"color:#f92672\">\/<\/span>java <span style=\"color:#f92672\">--<\/span>source 11\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">2<\/span><span><span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">HelloWorldExample<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">3<\/span><span>    <span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#66d9ef\">static<\/span> <span style=\"color:#66d9ef\">void<\/span> <span style=\"color:#a6e22e\">main<\/span>(String<span style=\"color:#f92672\">[]<\/span> args) {\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">4<\/span><span>        System.<span style=\"color:#a6e22e\">out<\/span>.<span style=\"color:#a6e22e\">println<\/span>(<span style=\"color:#e6db74\">&#34;Hello, World!&#34;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">5<\/span><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">6<\/span><span>}<\/span><\/span><\/code><\/pre><\/div>\n<p>This line (if you don&rsquo;t know it) is called <a href=\"https:\/\/en.wikipedia.org\/wiki\/Shebang_(Unix)\">shebang<\/a>. In this very case it says that &ldquo;what follows, should be interpreted as Java code, version 11&rdquo;.<\/p>\n<p>The last thing to do is to make this file executable, by calling <code>chmod u+x hello.script<\/code> in CLI.<\/p>\n<p>Now it&rsquo;s time to call our &ldquo;Java Script&rdquo;:\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-bash\" data-lang=\"bash\"><span style=\"display:flex;\"><span>$ .\/hello.script \n<\/span><\/span><span style=\"display:flex;\"><span>Hello, World!<\/span><\/span><\/code><\/pre><\/div><\/p>\n<p>As you can see, you can call in your terminal a &ldquo;script written in Java&rdquo;.<\/p>\n<p>It can also do more fancy stuff, pretty much like any script. Wanna read some arguments?\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1<\/span><span><span style=\"color:#960050;background-color:#1e0010\">#<\/span><span style=\"color:#f92672\">!\/<\/span>home<span style=\"color:#f92672\">\/<\/span>piotr<span style=\"color:#f92672\">\/<\/span>.<span style=\"color:#a6e22e\">sdkman<\/span><span style=\"color:#f92672\">\/<\/span>candidates<span style=\"color:#f92672\">\/<\/span>java<span style=\"color:#f92672\">\/<\/span>15<span style=\"color:#f92672\">-<\/span>open<span style=\"color:#f92672\">\/<\/span>bin<span style=\"color:#f92672\">\/<\/span>java <span style=\"color:#f92672\">--<\/span>source 8 \n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">2<\/span><span><span style=\"color:#f92672\">import<\/span> java.util.stream.Stream;\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">3<\/span><span><span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">ArgumentsExample<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">4<\/span><span>    <span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#66d9ef\">static<\/span> <span style=\"color:#66d9ef\">void<\/span> <span style=\"color:#a6e22e\">main<\/span>(String<span style=\"color:#f92672\">[]<\/span> args) {\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">5<\/span><span>        Stream.<span style=\"color:#a6e22e\">of<\/span>(args).<span style=\"color:#a6e22e\">forEach<\/span>(System.<span style=\"color:#a6e22e\">out<\/span>::println);\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">6<\/span><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">7<\/span><span>}<\/span><\/span><\/code><\/pre><\/div>\nHere you go:\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-bash\" data-lang=\"bash\"><span style=\"display:flex;\"><span>$ .\/arguments.script ene due rabe\n<\/span><\/span><span style=\"display:flex;\"><span>ene\n<\/span><\/span><span style=\"display:flex;\"><span>due\n<\/span><\/span><span style=\"display:flex;\"><span>rabe<\/span><\/span><\/code><\/pre><\/div><\/p>\n<p>Need to use the script in a piped chain of commands? Then (demo only!):\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1<\/span><span><span style=\"color:#960050;background-color:#1e0010\">#<\/span><span style=\"color:#f92672\">!\/<\/span>home<span style=\"color:#f92672\">\/<\/span>piotr<span style=\"color:#f92672\">\/<\/span>.<span style=\"color:#a6e22e\">sdkman<\/span><span style=\"color:#f92672\">\/<\/span>candidates<span style=\"color:#f92672\">\/<\/span>java<span style=\"color:#f92672\">\/<\/span>15<span style=\"color:#f92672\">-<\/span>open<span style=\"color:#f92672\">\/<\/span>bin<span style=\"color:#f92672\">\/<\/span>java <span style=\"color:#f92672\">--<\/span>source 11 \n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">2<\/span><span><span style=\"color:#f92672\">import<\/span> java.io.IOException;\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">3<\/span><span><span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">PipedExample<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">4<\/span><span>    <span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#66d9ef\">static<\/span> <span style=\"color:#66d9ef\">void<\/span> <span style=\"color:#a6e22e\">main<\/span>(String<span style=\"color:#f92672\">[]<\/span> args) <span style=\"color:#66d9ef\">throws<\/span> IOException {\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">5<\/span><span>        <span style=\"color:#66d9ef\">new<\/span> String(System.<span style=\"color:#a6e22e\">in<\/span>.<span style=\"color:#a6e22e\">readAllBytes<\/span>()).<span style=\"color:#a6e22e\">lines<\/span>().<span style=\"color:#a6e22e\">map<\/span>(String::toUpperCase).<span style=\"color:#a6e22e\">forEach<\/span>(System.<span style=\"color:#a6e22e\">out<\/span>::println);\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">6<\/span><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">7<\/span><span>}<\/span><\/span><\/code><\/pre><\/div>\nSo you can use it:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-bash\" data-lang=\"bash\"><span style=\"display:flex;\"><span>$ whoami | .\/piped.script \n<\/span><\/span><span style=\"display:flex;\"><span>PIOTR<\/span><\/span><\/code><\/pre><\/div>\n<p>I&rsquo;m not sure using &ldquo;Java scripts&rdquo; like these entitles you to call yourself &ldquo;full-stack developer&rdquo;, but for sure this might help if you&rsquo;re not familiar with awk, or you don&rsquo;t have a cat nearby to type some Perl.<\/p>\n<p>For more details, please refer to <a href=\"https:\/\/openjdk.java.net\/jeps\/330\">JEP 330<\/a>.<\/p>\n<p>This post has been continued in its <a href=\"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/scripts\/more-on-shebang\/\">update<\/a>.<\/p>\n"},{"title":"Little Java riddle - the answer","link":"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/riddle-answer\/","pubDate":"Mon, 14 Sep 2020 13:50:47 +0200","guid":"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/riddle-answer\/","description":"<h3 id=\"ene-due-like\">Ene, due, like&hellip;<\/h3>\n<p>The competition is over, the prizes were given away&hellip; And despite the trainings are still going on, it might be time to show the answer to my <a href=\"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/riddle\/\">little riddle<\/a>, and make a comment on it.<\/p>\n<p>Minimal Java\u2122 version needed to run this code is 10. There are two reasons: the presence of <code>var<\/code> and the call of <a href=\"https:\/\/docs.oracle.com\/en\/java\/javase\/11\/docs\/api\/java.base\/java\/util\/List.html#copyOf(java.util.Collection)\"><code>List.copyOf<\/code><\/a>. All overloaded variants of <a href=\"https:\/\/docs.oracle.com\/en\/java\/javase\/11\/docs\/api\/java.base\/java\/util\/List.html#of(E...)\"><code>List.of<\/code><\/a> are available since Java\u00a09.<\/p>\n<p>To answer the second question you still don&rsquo;t need to run the riddle&rsquo;s code, all that&rsquo;s needed is careful examination of the <code>List.of()<\/code> and <code>List.copyOf()<\/code> descriptions in javadoc. (You still have a chance, the links are in the previous paragraph. ;-)) Our <code>raz<\/code> is an unmodifiable list, because the javadoc of <code>of()<\/code> says <em>returns an unmodifiable list<\/em>. It means a list to which we can&rsquo;t add more elements or from which we can&rsquo;t remove any elements once it&rsquo;s created (because the elements can be changed &ldquo;inside&rdquo; if they&rsquo;re mutable). What&rsquo;s more, the javadoc of <code>copyOf()<\/code> states in its implementation note (yeap, we need to read that far) <em>if the given Collection is an unmodifiable List, calling copyOf will generally not create a copy<\/em>, meaning: passing an unmodifiable list results in returning exactly the same list, no copy is made. Which makes <code>raz == dwa<\/code> result in <code>true<\/code> in this riddle and therefore <code>ene<\/code> is printed. If not the <code>else<\/code>, we&rsquo;d see <code>due<\/code> as well, because  <code>x.equals(x)<\/code> should always be <code>true<\/code>.<\/p>\n<p><figure class=\"image image right\">\n<img src=\"jshell-riddle.png\" alt=\"Riddle run in jshell\" width=\"550\">\n<\/figure>\n\nThe third question was marked with an asterisk due to a few reasons at least:<\/p>\n<ul>\n<li>to answer it, one has to run the riddle or read Java sources,<\/li>\n<li>actually it&rsquo;s an implementation details and as such we should not rely on that,<\/li>\n<li>at least two correct answers are possible today, there might be more in the future (because the point above).<\/li>\n<\/ul>\n<p>When we run this code on Java\u00a011 or never (so far up to 15 inclusively), then <code>raz<\/code> is an instance of <code>java.util.ImmutableCollections.List12<\/code>. <code>List12<\/code> is a nested class of <code>ImmutableCollections<\/code>, and the <code>ImmutableCollections<\/code> class is visible inside <code>java.util<\/code> package, so in our code we can&rsquo;t crate an instance of <code>List12<\/code> using a constructor.<br>\nI&rsquo;d like to start the analysis of <code>List12<\/code> with its name. To my eyes (and ears) the actual name of ths call (although no-one told me that) is &ldquo;list one-two&rdquo;, &ldquo;list twelve&rdquo;. Why? Because (and now it&rsquo;s worth taking a look into its source) the instances of this class are capable of keeping exactly one or two objects. What&rsquo;s more, they don&rsquo;t use an array or dynamic links, just two strict references, so after this list is created, it can store one element or two elements, tertium non datur. Briefly speaking, now Java also has specialised collection classes to keep just a few elements (vide <code>Set12<\/code>). As I suggested in <a href=\"https:\/\/softwaregarden.dev\/en\/talks\/context\/\">CONTEXTVS, STVLTE!<\/a> when referring to Scala example, tiny collections happen so frequently in the universe, that it makes sense to have a distinct implementations for them, also for performance reasons. Examples? Here you go: checking the number of elements inside <code>List12<\/code> is dead simple, if the second reference is <code>null<\/code>, then we have one element, in all other cases we have two elements. Really simple and extremely efficient, no need to check array&rsquo;s lenght or cache the result for subsequent <code>size()<\/code> calls.<\/p>\n<p>Just for sake of completenes, a second answer is possible to the third question. In Java\u00a010 the class <code>List12<\/code> didn&rsquo;t exist, there were two disting classes, <code>List1<\/code> and <code>List2<\/code>. As mentions, this is an implementation detail, subject to change in the future, as it&rsquo;s not a part of the public API.<\/p>\n<h3 id=\"dude-so-what\">Dude, so what?<\/h3>\n<p>This whole story has a second meaning IHMO, which I haven&rsquo;t seen as any official statement anywhere, but it&rsquo;s a conclusion I get when I trace the changes in each Java version since\u00a08. My reading is that Java is slowly pushed towards languages, which also allow programming in declarative and\/or functional style, not just imperative. One of the key aspects of functional style is the lack of side effects. Keeping data in unmodifiable structures helps here a lot, not to mention that it makes things easier: it&rsquo;s easier to read such code, it&rsquo;s easier to program in a more defensive way, etc., etc. The argument of &ldquo;but the performance will suffer, dude!&rdquo; can be addressed by &ldquo;can&rsquo;t you see how fast <code>copyOf()<\/code> works?&rdquo; or &ldquo;we have insanely fast classed for small, yet frequent collections&rdquo;. And please don&rsquo;t forget, that the hardware still performs better and better. &ldquo;New&rdquo; kids in the <code>java.time<\/code> block? Immutable. Records? Immutable. Streams? Single use only.<\/p>\n<h3 id=\"we-have-to-go-deeper\">We have to go deeper<\/h3>\n<p>If we go deeper, we might hit another level. I use the aforementioned riddle e.g. when I start my training about the cool new stuff available since Java\u00a08-9. When the participants hear the question &ldquo;what Java version do you have&rdquo;, what you often hear is a loud &ldquo;ELEVEN!!&rdquo;. Later, after the riddle and during the training or code review it turns out that yes, that&rsquo;s true, 11 can be observed in the landscape, but merely as a JVM version running in the production, not the version we think in and develop for. It turns out that the years of education and certification, tons of outdated tutorials and thousands of ancient StackOvefrlow answers (relevant years ago) caused such serious damage to our minds, that repelling loop-osis, if-osis, outdated design patterns, mutability of everything and everywhere is really a challenging job. What&rsquo;s worse, the fresh graduates of our great universities and &ldquo;real-life&rdquo; bootcamps are just replicas of their teachers and mentors. It&rsquo;s really nice if you can spot in the new code something different from <code>collect(toList())<\/code>&hellip; And <code>collect(toUnmodifiableList())<\/code> is really a rare gem. Therefore, my observations is this: we happily set <code>javac<\/code> to use <code>--target 11<\/code>, but our habits and minds still aren&rsquo;t aiming that target. I see quite a lot of job posts like &ldquo;alive JAVA\u00a08 developer wanted&rdquo;. Please don&rsquo;t get me wrong, Java\u00a08 was the version which convinced me that Java isn&rsquo;t a technology, which is going to drift slowly into the dark seas of oblivion, labelled COBOL and which has to be abandoned by jumping onto Scala or Kotlin ships. Java\u00a08 is a bit like a steam engine years ago: it can still be seen frequently, has a lot of power, etc. Maglev and hyperloop don&rsquo;t make sense everywhere, but maybe the electric engines are something we&rsquo;d like to see to be common on the track? Also, I don&rsquo;t think that the old code is cursed, must be rewritten to modern and shiny versions, and so on. What I mean: what was good in times of Java\u00a07, might not be good anymore. Let&rsquo;s try to adapt the way we see Java these days.<\/p>\n<h2 id=\"-i-morele-b\u0119c\">&hellip; i morele b\u0119c!!!<\/h2>\n"},{"title":"Records in Java - what about Lombok?","link":"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/records\/vs-lombok\/","pubDate":"Thu, 28 May 2020 10:40:07 +0200","guid":"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/records\/vs-lombok\/","description":"<p><em>Update April 2021: Please note this post is about Java 15, with records as preview feature. Things have changed, the update is available in <a href=\"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/records\/vs-lombok-yet-again-with-builder-pattern\/\">another post<\/a>.<\/em><\/p>\n<h3 id=\"records-confrontation\">Records: confrontation<\/h3>\n<p>When explaining Java records online I was asked several times &lsquo;right, what about Lombok?&rsquo;<\/p>\n<p>In particular this question was &lsquo;if the records are <em>immutable<\/em>, how are they different from Lombok&rsquo;s <code>@Value<\/code>?&rsquo;<\/p>\n<p>First thing one needs to remember is that <a href=\"\">&ldquo;records are not Java Beans&rdquo;<\/a> and the <code>@Value<\/code> gives us immutable JavaBeans.<\/p>\n<p>The results of using <code>record<\/code> and <code>@Value<\/code> in code are sometimes very similar (if not the same).<\/p>\n<ul>\n<li><code>equals()<\/code>, <code>hashCode()<\/code>, <code>toString()<\/code> are generated.<\/li>\n<li>All fields are marked as <code>private final<\/code>.<\/li>\n<li>The &lsquo;all fields constructors&rsquo; are generated (if the Bean annotated with <code>@Value<\/code> has a field initialised during the declaration, then of course the field is skipped).<\/li>\n<li><code>record<\/code> and <code>@Value<\/code> result in classes which are <code>final<\/code>, so it&rsquo;s impossible to inherit from them.<\/li>\n<\/ul>\n<p>There are two fundamental differences:<\/p>\n<ul>\n<li>In records the components are declared in the record&rsquo;s header (it&rsquo;s beautifully described by <a href=\"https:\/\/openjdk.java.net\/jeps\/384#Java-Grammar\">the grammar from JEP 384<\/a>), whereas in <code>@Value<\/code>d JavaBeans all fields need to be added and based on them the &ldquo;canonical&rdquo; constructor is being generated.<\/li>\n<li>Records have accessors, <code>@Value<\/code> will give us getters.<\/li>\n<\/ul>\n<p>Of course, there are more differences. If you&rsquo;re really interested in them, the ultimate way to learn them is to compare the bytecode or at least to &ldquo;deLombok&rdquo; the code in your IDE. E.g., if the Lombok&rsquo;s configuration in <code>lombok.config<\/code> also has <code>lombok.anyConstructor.addConstructorProperties=true<\/code>, then the &ldquo;canonical&rdquo; constructor thanks to <code>@Value<\/code> is also annotated <code>@java.beans.ConstructorProperties<\/code>. &lsquo;Yeah, but it&rsquo;s a minor detail&hellip;&rsquo;. True, but this detail makes deserialization using Jackson from JSON to objects more elegant. As &rsquo;elegant&rsquo; I mean without putting <code>@JsonCreator<\/code> above the constructor and <code>@JsonProperty(&quot;name)<\/code> before each constructor&rsquo;s parameter. (We shall not forget that in the records the &rsquo;normal deserialization&rsquo; from the binary format is also handled by the constructor, so the concept of &rsquo;let&rsquo;s deserialize using constructors&rsquo; gets more and more popular. Finally.)<\/p>\n<p>There might be more differences in the future. One of the expected ways of using records is <em>pattern matching<\/em> with data extraction. And such extraction requires deconstructing the objects (like <code>unapply<\/code> in Sala). One day we might find out that <code>record<\/code> can also create such deconstructors for records as well. For time being I can&rsquo;t tell if and how it&rsquo;s going to work, if such deconstructors could be &lsquo;manual&rsquo; as well and if Lombok is going to address that anyhow.<\/p>\n<h3 id=\"and-now-kiss\">And now: kiss!<\/h3>\n<p><figure class=\"image image left\">\n<img src=\"now-kiss.png\" alt=\"Now kiss\" width=\"350\">\n<\/figure>\n\nCareful readers of <a href=\"https:\/\/projectlombok.org\/features\/Value\"><code>@Value<\/code>&rsquo;s documentation<\/a> (because you do RTFM, right?) notices, that in a way the <code>@Value<\/code> is a shortcut for a several other annotations. The list looks like this: <code>final @ToString @EqualsAndHashCode @AllArgsConstructor @FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE) @Getter<\/code><\/p>\n<p>Records have <code>toString()<\/code>, so they don&rsquo;t need <code>@ToString<\/code>, and so on. Actually they have everything execept <code>@Getter<\/code>.<\/p>\n<p>What happens when we add <code>@Getter<\/code> to a record&rsquo;s declaration\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">@Getter<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#66d9ef\">record<\/span> <span style=\"color:#a6e22e\">RecordWithGetters<\/span>(<span style=\"color:#66d9ef\">int<\/span> f1, String f2) {}<\/span><\/span><\/code><\/pre><\/div>\nand compile that using Lombok as well? We&rsquo;re going to have a <code>.class<\/code> file , which (after decompilation) looks more or less like this :\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;display:grid;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 1<\/span><span>  <span style=\"color:#75715e\">\/\/ IntelliJ API Decompiler stub source generated from a class file<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 2<\/span><span>  <span style=\"color:#75715e\">\/\/ Implementation of methods is not available<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 3<\/span><span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 4<\/span><span><span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#66d9ef\">final<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">RecordWithGetters<\/span> <span style=\"color:#66d9ef\">extends<\/span> java.<span style=\"color:#a6e22e\">lang<\/span>.<span style=\"color:#a6e22e\">Record<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 5<\/span><span>    <span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#66d9ef\">final<\/span> <span style=\"color:#66d9ef\">int<\/span> f1;\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 6<\/span><span>    <span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#66d9ef\">final<\/span> java.<span style=\"color:#a6e22e\">lang<\/span>.<span style=\"color:#a6e22e\">String<\/span> f2;\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 7<\/span><span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 8<\/span><span>    <span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#a6e22e\">RecordWithGetters<\/span>(<span style=\"color:#66d9ef\">int<\/span> f1, java.<span style=\"color:#a6e22e\">lang<\/span>.<span style=\"color:#a6e22e\">String<\/span> f2) { <span style=\"color:#75715e\">\/* compiled code *\/<\/span> }\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 9<\/span><span>\n<\/span><\/span><span style=\"display:flex; background-color:#3c3d38\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">10<\/span><span>    <span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#66d9ef\">int<\/span> <span style=\"color:#a6e22e\">getF1<\/span>() { <span style=\"color:#75715e\">\/* compiled code *\/<\/span> }\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">11<\/span><span>\n<\/span><\/span><span style=\"display:flex; background-color:#3c3d38\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">12<\/span><span>    <span style=\"color:#66d9ef\">public<\/span> java.<span style=\"color:#a6e22e\">lang<\/span>.<span style=\"color:#a6e22e\">String<\/span> <span style=\"color:#a6e22e\">getF2<\/span>() { <span style=\"color:#75715e\">\/* compiled code *\/<\/span> }\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">13<\/span><span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">14<\/span><span>    <span style=\"color:#66d9ef\">public<\/span> java.<span style=\"color:#a6e22e\">lang<\/span>.<span style=\"color:#a6e22e\">String<\/span> <span style=\"color:#a6e22e\">toString<\/span>() { <span style=\"color:#75715e\">\/* compiled code *\/<\/span> }\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">15<\/span><span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">16<\/span><span>    <span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#66d9ef\">final<\/span> <span style=\"color:#66d9ef\">int<\/span> <span style=\"color:#a6e22e\">hashCode<\/span>() { <span style=\"color:#75715e\">\/* compiled code *\/<\/span> }\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">17<\/span><span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">18<\/span><span>    <span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#66d9ef\">final<\/span> <span style=\"color:#66d9ef\">boolean<\/span> <span style=\"color:#a6e22e\">equals<\/span>(java.<span style=\"color:#a6e22e\">lang<\/span>.<span style=\"color:#a6e22e\">Object<\/span> o) { <span style=\"color:#75715e\">\/* compiled code *\/<\/span> }\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">19<\/span><span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">20<\/span><span>    <span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#66d9ef\">int<\/span> <span style=\"color:#a6e22e\">f1<\/span>() { <span style=\"color:#75715e\">\/* compiled code *\/<\/span> }\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">21<\/span><span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">22<\/span><span>    <span style=\"color:#66d9ef\">public<\/span> java.<span style=\"color:#a6e22e\">lang<\/span>.<span style=\"color:#a6e22e\">String<\/span> <span style=\"color:#a6e22e\">f2<\/span>() { <span style=\"color:#75715e\">\/* compiled code *\/<\/span> }\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">23<\/span><span>}<\/span><\/span><\/code><\/pre><\/div><\/p>\n<p>Meaning: beside the accessors of components, the records also has getters now. I don&rsquo;t know if I like this. But I know that thanks to that we can add one more option to the list in the <a href=\"\">post on records&rsquo; reflection<\/a> and have the getters generated (instead of adding them manually), because &lsquo;sadly, this pesky library needs getters&rsquo;.<\/p>\n<p>Right, but I mentioned <code>@AllArgsConstructor<\/code> earlier&hellip; When we torture the records even more and add this annotation (and when we have the proper entry in <code>json.config<\/code>):<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">@AllArgsConstructor<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#66d9ef\">record<\/span> <span style=\"color:#a6e22e\">RecordWithAllArgsConstructor<\/span>(<span style=\"color:#66d9ef\">int<\/span> f1, String f2) {}<\/span><\/span><\/code><\/pre><\/div>\n<p>then after the compilation this is how the constructor looks like:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">@java.beans.ConstructorProperties<\/span>({<span style=\"color:#e6db74\">&#34;f1&#34;<\/span>, <span style=\"color:#e6db74\">&#34;f2&#34;<\/span>})\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#a6e22e\">RecordWithAllArgsConstructor<\/span>(<span style=\"color:#66d9ef\">int<\/span> f1, java.<span style=\"color:#a6e22e\">lang<\/span>.<span style=\"color:#a6e22e\">String<\/span> f2) { <span style=\"color:#75715e\">\/* compiled code *\/<\/span> }<\/span><\/span><\/code><\/pre><\/div>\n<p>What does it give us? Some &ldquo;compatibility&rdquo; with the Jackson when turning JSON into records (so deserializing).<\/p>\n<p>Wrapping up: adding two more annotations <code>@Getter @AllArgsConstructor<\/code> to a record&rsquo;s definition and having properly configured Lombok in the project, will let us use the records in quite popular aspect, which is turning REST requests into Java objects\/records and the objects\/records into REST responses.<\/p>\n<h3 id=\"is-it-worth-it\">Is it worth it?<\/h3>\n<p>Honestly? I can&rsquo;t tell.<\/p>\n<p>All right, this would allow (if someone is not afraid of <code>--enable-preview<\/code> and living on the edge) using records in a very popular area right now. And when all the libraries used by us will be aware of the <code>record<\/code>s, we&rsquo;d be able to get rid of these annotations.<\/p>\n<p>However, Lombok doesn&rsquo;t come for free. It&rsquo;s difficult to use it without an IDE plugin, the plugin is not always up-to-date, Lombok (because of being a kind of &ldquo;compiler plugin&rdquo;) doesn&rsquo;t work e.g. in mixed compilation with Scala, etc. It&rsquo;s a huge disadvantage that using my current setup (Intellij IDEA 2020.1.1, Lombok plugin to IDEA: 0.30-2020.1) it&rsquo;s impossible to call the record&rsquo;s constructor if this constructor was generated by Lombok ;-) Compiling and running using Maven and <code>OpenJDK Runtime Environment (build 15-ea+23-1098)<\/code> works.<\/p>\n<figure class=\"image image right\">\n<img src=\"records-torture-in-IDEA.png\" alt=\"Lombok-generated constructor in IDEA&#39;s plugin\" width=\"600\">\n<\/figure>\n\n<p>So, is this technically possible? Yes. Is it worth it? You should answer this question yourself.<\/p>\n<h4 id=\"what-about-value\">What about @Value?<\/h4>\n<p>&lsquo;All right, so if the <code>@Getter @AllArgsConstructor<\/code> are in a way a subset of the <code>@Value<\/code>, maybe we could use <code>@Value<\/code> for records?&rsquo;<\/p>\n<p>This is something I wouldn&rsquo;t do in any circumstances.<\/p>\n<ul>\n<li>Using <code>@Value<\/code> generates warning in the IDE, that the methods <code>equals()<\/code> and <code>hashCode()<\/code> don&rsquo;t take into account classes our class inherits from. At the first glance <code>@Value record ARecord(){}<\/code> doesn&rsquo;t inherit anything, but we shall not forget <code>java.lang.Record<\/code>. Lombok, it seems, does for now.<\/li>\n<li>When using Lombok and records at the same time it&rsquo;d be nice to be careful about the method &lsquo;overlapping&rsquo;. If a method is being generated by Lombok and by <code>record<\/code>, then in the <code>.class<\/code> file we&rsquo;ll find the one generated by Lombok. And I think it&rsquo;d better to have the &lsquo;original record&rsquo; method. It&rsquo;s a matter of taste and forward compatibility.<\/li>\n<\/ul>\n<p>Lombok is a powerful tool, and as such it requires understanding and responsibility for all (mis)usages.<\/p>\n<p>If your fingers are itchy, and you&rsquo;d like to torture records on your own, the code is on <a href=\"https:\/\/github.com\/pioorg\/recordsTorture\">Github<\/a>.<\/p>\n"},{"title":"Records in Java - reflection","link":"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/records\/reflection\/","pubDate":"Fri, 15 May 2020 10:30:00 +0200","guid":"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/records\/reflection\/","description":"<h3 id=\"things-get-interesting\">Things get interesting<\/h3>\n<p>When Java 14 was (about to be) released I saw a few discussions following more or less this schema:<\/p>\n<ul>\n<li>Oh, records in Java, cool, finally we have automatically generated setters and getters!<\/li>\n<li>No, records in Java are POJOs without any setters&hellip;<\/li>\n<li>Oh, I see&hellip; Cool, finally in Java we have generated Beans, without any setters though!<\/li>\n<\/ul>\n<p>Now it&rsquo;s time for me to write two most important things about records in Java.\nThe first:<\/p>\n<h2 id=\"records-are-not-javabeans\">Records are not JavaBeans<\/h2>\n<p>and the second:<\/p>\n<h2 id=\"records-are-not-javabeans-1\">Records are not JavaBeans<\/h2>\n<p>People shaken and stirred will find the explanation this below.<\/p>\n<h3 id=\"new-kids-in-the-class\">New kids in the class<\/h3>\n<p>In the <a href=\"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/records\/can-and-cannot\/\">previous entry on records<\/a> it was shown, that the records look a bit like enumeration types introduced in Java 5. Just like an <code>enum<\/code> inherits directly from <code>java.lang.Enum<\/code> and nothing can inherit from it, a <code>record<\/code> inherits directly from <code>java.lang.Record<\/code> and nothing can inherit from it as well.<\/p>\n<p>One of the differences is that <code>enum<\/code> is a keyword, whereas <code>record<\/code> (just like <code>var<\/code>) is not. (Don&rsquo;t focus on the syntax colouring in the browser, please. The JS plugin doesn&rsquo;t support records now ;-))\n.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/this won&#39;t work<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">var<\/span> enum <span style=\"color:#f92672\">=<\/span> ...\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/this works<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">var<\/span> record <span style=\"color:#f92672\">=<\/span> ...<\/span><\/span><\/code><\/pre><\/div>\n<p>Introduction of records brought us two new methods in the <code>Class<\/code> class.<\/p>\n<p>Just as we can check if an object is an <code>enum<\/code> by using <a href=\"https:\/\/docs.oracle.com\/en\/java\/javase\/14\/docs\/api\/java.base\/java\/lang\/Class.html#isEnum()\"><code>Class.isEnum()<\/code><\/a>, we can now check if an object is a record by calling <a href=\"https:\/\/docs.oracle.com\/en\/java\/javase\/14\/docs\/api\/java.base\/java\/lang\/Class.html#isRecord()\"><code>Class.isRecord()<\/code><\/a>.<\/p>\n<p>And when the result of the <code>isRecord()<\/code> tells us &lsquo;it&rsquo;s a record&rsquo;, then we may wish to check what are the components of the record. We can get them in the form of an array calling <a href=\"https:\/\/docs.oracle.com\/en\/java\/javase\/14\/docs\/api\/java.base\/java\/lang\/Class.html#getRecordComponents()\"><code>public RecordComponent[] Class.getRecordComponents()<\/code><\/a>. This works just as getting the list of fields, methods, etc. Of course, having a <code>RecordComponent<\/code>, we can try to get deeper to evaluate the possibilities. Probably the most intriguing one is <a href=\"https:\/\/docs.oracle.com\/en\/java\/javase\/14\/docs\/api\/java.base\/java\/lang\/reflect\/RecordComponent.html#getAccessor()\"><code>getAccessor()<\/code><\/a>, which allows us to get the value of the component.<\/p>\n<p>Please pay some attention to the name of this method. It&rsquo;s not a <em>getter<\/em>, it&rsquo;s an <em>accessor<\/em>. So called <em>gettery<\/em> by convention have their names starting with <code>get<\/code> (or <code>is<\/code>).<\/p>\n<h3 id=\"description-of-the-bean\">Description of the bean<\/h3>\n<p>Let me follow this path. In this journey our companions will be two classes. A &ldquo;typical&rdquo; bean <code>BeanWithSetters<\/code> and a record <code>ReflectionCheck<\/code>. They look the following way (the entire code available on <a href=\"https:\/\/github.com\/pioorg\/DeepDiveJava14\/blob\/master\/src\/main\/java\/org\/przybyl\/ddj14\/records\/s2_reflection\/Reflection.java\">GitHub<\/a>):<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">record<\/span> <span style=\"color:#a6e22e\">ReflectionCheck<\/span>(<span style=\"color:#66d9ef\">int<\/span> a, String b) {}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">BeanWithSetters<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>\t<span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#66d9ef\">final<\/span> UUID id;\n<\/span><\/span><span style=\"display:flex;\"><span>\t<span style=\"color:#66d9ef\">private<\/span> String stringField;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>\t<span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#a6e22e\">BeanWithSetters<\/span>(UUID id, String stringField) {\n<\/span><\/span><span style=\"display:flex;\"><span>\t\t<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">id<\/span> <span style=\"color:#f92672\">=<\/span> id;\n<\/span><\/span><span style=\"display:flex;\"><span>\t\t<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">stringField<\/span> <span style=\"color:#f92672\">=<\/span> stringField;\n<\/span><\/span><span style=\"display:flex;\"><span>\t}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>\t<span style=\"color:#66d9ef\">public<\/span> UUID <span style=\"color:#a6e22e\">getId<\/span>() {\n<\/span><\/span><span style=\"display:flex;\"><span>\t\t<span style=\"color:#66d9ef\">return<\/span> id;\n<\/span><\/span><span style=\"display:flex;\"><span>\t}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>\t<span style=\"color:#66d9ef\">public<\/span> String <span style=\"color:#a6e22e\">getStringField<\/span>() {\n<\/span><\/span><span style=\"display:flex;\"><span>\t\t<span style=\"color:#66d9ef\">return<\/span> stringField;\n<\/span><\/span><span style=\"display:flex;\"><span>\t}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>\t<span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#66d9ef\">void<\/span> <span style=\"color:#a6e22e\">setStringField<\/span>(String stringField) {\n<\/span><\/span><span style=\"display:flex;\"><span>\t\t<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">stringField<\/span> <span style=\"color:#f92672\">=<\/span> stringField;\n<\/span><\/span><span style=\"display:flex;\"><span>\t}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>}<\/span><\/span><\/code><\/pre><\/div>\n<p>What results can we expect when we make them go through the following machine?<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span>BeanInfo beanInfo <span style=\"color:#f92672\">=<\/span> Introspector.<span style=\"color:#a6e22e\">getBeanInfo<\/span>(object.<span style=\"color:#a6e22e\">getClass<\/span>());\n<\/span><\/span><span style=\"display:flex;\"><span>Stream.<span style=\"color:#a6e22e\">of<\/span>(beanInfo.<span style=\"color:#a6e22e\">getPropertyDescriptors<\/span>()).<span style=\"color:#a6e22e\">forEach<\/span>(System.<span style=\"color:#a6e22e\">out<\/span>::println);<\/span><\/span><\/code><\/pre><\/div>\n<p>For <em>JavaBean<\/em> we get what we expect. The bean has two properties (except the class), one of which has only a <em>getter<\/em> (read method), the other one has a <em>setter<\/em> (write method) and a <em>getter<\/em>:<\/p>\n<pre><code>java.beans.PropertyDescriptor[name=class; values={expert=false; visualUpdate=false; hidden=false; enumerationValues=[Ljava.lang.Object;@5ce65a89; required=false}; propertyType=class java.lang.Class; readMethod=public final native java.lang.Class java.lang.Object.getClass()]\njava.beans.PropertyDescriptor[name=id; values={expert=false; visualUpdate=false; hidden=false; enumerationValues=[Ljava.lang.Object;@51521cc1; required=false}; propertyType=class java.util.UUID; readMethod=public java.util.UUID BeanWithSetters.getId()]\njava.beans.PropertyDescriptor[name=stringField; values={expert=false; visualUpdate=false; hidden=false; enumerationValues=[Ljava.lang.Object;@1b4fb997; required=false}; propertyType=class java.lang.String; readMethod=public java.lang.String BeanWithSetters.getStringField(); writeMethod=public void BeanWithSetters.setStringField(java.lang.String)]\n<\/code><\/pre>\n<p>What happens when we perform a similar analysis of a record?<\/p>\n<pre><code>java.beans.PropertyDescriptor[name=class; values={expert=false; visualUpdate=false; hidden=false; enumerationValues=[Ljava.lang.Object;@5ce65a89; required=false}; propertyType=class java.lang.Class; readMethod=public final native java.lang.Class java.lang.Object.getClass()]\n<\/code><\/pre>\n<p>The only thing working like in a <em>JavaBean<\/em> is getting the class of the record. The components from the record&rsquo;s declaration don&rsquo;t generate any getters. A <em>record<\/em> is not a <em>JavaBean<\/em>, Q.E.D.<\/p>\n<h3 id=\"implications\">Implications<\/h3>\n<p>The fact that the records are not <em>JavaBeans<\/em> has some implications. Java 14 didn&rsquo;t emerge in the void. There are more than 25 years of development, creating the ecosystem, tons libraries and frameworks, many developers use it every day. Summarising: it&rsquo;s a mass with some momentum, which inherited an assumption that (almost) everything is a <em>JavaBean<\/em> if there&rsquo;s some data inside.<\/p>\n<p>Suddenly the records show up, being perfect for keeping data, and they don&rsquo;t have any _getter_s. You know, a <em>VO<\/em>, a <em>DTO<\/em>, but no _getter_s. Cool, isn&rsquo;t it?<\/p>\n<p>That&rsquo;s why some libraries may <em>for time being<\/em> not support them in the ideal way. (That&rsquo;s why I think the concept of <em>preview features<\/em> is great for everyone to recover from the shock and make needed changes.)<\/p>\n<p>Let&rsquo;s examine Jackson in version 2.10.3 (whole code on <a href=\"https:\/\/github.com\/pioorg\/DeepDiveJava14\/blob\/master\/src\/main\/java\/org\/przybyl\/ddj14\/records\/s3_serialization\/JSONifocation.java\">GitHub<\/a>). Having a record (for example this one):<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">record<\/span> <span style=\"color:#a6e22e\">SerializationRecordCheck<\/span>(String justOneField) {}<\/span><\/span><\/code><\/pre><\/div>\n<p>if we wish to turn this record into JSON using Jackson:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">new<\/span> ObjectMapper().<span style=\"color:#a6e22e\">writeValueAsString<\/span>(<span style=\"color:#66d9ef\">new<\/span> SerializationBeanCheck(<span style=\"color:#e6db74\">&#34;Bean&#34;<\/span>))<\/span><\/span><\/code><\/pre><\/div>\n<p>we have to face such a beautiful exception:<\/p>\n<pre><code>Exception in thread &quot;main&quot; com.fasterxml.jackson.databind.exc.InvalidDefinitionException: \nNo serializer found for class SerializationRecordCheck and \nno properties discovered to create BeanSerializer \n(to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS)\n<\/code><\/pre>\n<p>These four lines can explain that &lsquo;records are not Java Beans&rsquo; perhaps even better than <code>BeanInfo<\/code>. Jackson expects that it&rsquo;ll be given for serialization a JavaBean, that is: an object having some methods starting with <code>get<\/code>\/<code>is<\/code> (except <code>getClass()<\/code>). However, there are no such methods in the record!<\/p>\n<p>I guess the most probable scenario in the future is that Jackson (and other libraries as well) will check the result of the <code>isRecord()<\/code> and will (de)serialize records differently than JavaBeans. Just as they handle enums already.<\/p>\n<p>Okay, but what shall be done if we badly want to use records now and they appear at the edges of our hexagon?<\/p>\n<p>Most probably we don&rsquo;t want to set the <code>SerializationFeature.FAIL_ON_EMPTY_BEANS<\/code> flag, because we&rsquo;re trying to serialize the record, so we do care about the data.<\/p>\n<ul>\n<li>We can add the getters by hand, so they are calling accessors inside. I don&rsquo;t recommend that.<\/li>\n<li>We can create our own serializer. It makes sense if we don&rsquo;t want to keep our domain code pure, free from any annotations.<\/li>\n<li>We can also annotate all record&rsquo;s components with<code>@JsonProperty<\/code>.<\/li>\n<\/ul>\n<p>This is how the last solution looks in the code:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">record<\/span> <span style=\"color:#a6e22e\">SerializationRecordCheck<\/span>(<span style=\"color:#a6e22e\">@JsonProperty<\/span> String justOneField) {}<\/span><\/span><\/code><\/pre><\/div>\n<p>Annotations we use for the components &ldquo;are copied&rdquo; for the accessors and fields in the records. So we can image the record looking the following way after being compiled:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">@JsonProperty<\/span> \n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#66d9ef\">final<\/span> String justOneField;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#a6e22e\">@JsonProperty<\/span> \n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">public<\/span> String <span style=\"color:#a6e22e\">justOneField<\/span>() {\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#66d9ef\">return<\/span> justOneField;\n<\/span><\/span><span style=\"display:flex;\"><span>}<\/span><\/span><\/code><\/pre><\/div>\n<p>&ldquo;Oh, you saw it, you saw it! They didn&rsquo;t implement thre records as they should, because this librarys doesn&rsquo;t work!!1one&rdquo;.\nTwo questions:<\/p>\n<ul>\n<li>Were enums or the generic types working in all the libraries right away after being introduced?<\/li>\n<li>Is the tail supposed to wag the dog?<\/li>\n<\/ul>\n<p>A similar issue was faced in Scala when some <code>case class<\/code>es were used by some Java libraries expecting getter. In Scala, to make the getter appear in the class as well, the components have to be annotated with <code>@BeanProperty<\/code>. For me, it&rsquo;s hard to say if that was better or worse approach. It was better, because it makes things work &ldquo;right away&rdquo; with the ecosystem. It was worse, because the rotting leg wasn&rsquo;t chopped off. Let&rsquo;s be honest: Scala doesn&rsquo;t have such coverage and such reach as Java does, so Scala had to fit into Java. Does Java itself need to fit into Java?<\/p>\n<p>I think the subject of &rsquo;lack of getters&rsquo; was summarised in the best way by the records JEPs&rsquo; author, Mr. B. Goetz himself: <a href=\"http:\/\/mail.openjdk.java.net\/pipermail\/amber-dev\/2020-May\/006009.html\">link<\/a> to his e-mail.<\/p>\n<h3 id=\"what-do-you-think\">What do you think?<\/h3>\n<p>I think I kind of like this &ldquo;no getters approach&rdquo;, but I develop not only in Java, so I got used to this concept long ago. Actually I could only sigh &lsquo;well, finally&hellip;&rsquo; Besides very accurate judgement of the Java architects I see additional benefit: the accessors simplify our lives even more. Naming is one of the two most difficults contepts in IT. Theoretically the _getter_s, as the name implies, were supposed to start with <em>get<\/em> prefix. However, for a <code>boolean<\/code> there could also be <code>is<\/code>. That made the less thought-out solution crash already (because of the &ldquo;regex diarrhea&rdquo;). What if that was a <code>Boolean<\/code>? Then shall we stick to <code>get<\/code> or was it more like <code>is<\/code>. What about field <code>Boolean wasDelivered<\/code>: <code>getWas...<\/code>, <code>isWas...<\/code>, just <code>was...<\/code> alone? With the accessors the rule is trivial.<\/p>\n<h3 id=\"more-on-serialization\">More on serialization<\/h3>\n<p>Some say we could have some new features in Java sooner if not &lsquo;oh crap, this *** serialization&rsquo;. Records can be serialized just like other objects, all we need is to implement the <code>Serializable<\/code> interface. The binary format is a bit different, but the JVM handles that, we don&rsquo;t have to. For the intrigued souls <a href=\"https:\/\/github.com\/pioorg\/DeepDiveJava14\/blob\/master\/src\/main\/java\/org\/przybyl\/ddj14\/records\/s3_serialization\/Serialization.java\">some code to run<\/a>.<\/p>\n<p>However, there is a huge change when it comes to DEserialization. Records are deserialized using the canonical constructor, we one could risk stating that Java is returning to the OOP track.<\/p>\n"},{"title":"Records in Java - what they can and cannot","link":"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/records\/can-and-cannot\/","pubDate":"Mon, 11 May 2020 10:30:00 +0200","guid":"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/records\/can-and-cannot\/","description":"<p>In the <a href=\"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/records\/intro\/\">previous post<\/a> I wrote how to make a record and what is actually the purpose of the records. In this entry I focus on the limitations and abilities of the records.<\/p>\n<p><em><em>This post has been updated for (coming) Java 15 and <a href=\"https:\/\/openjdk.java.net\/jeps\/384\">JEP 384<\/a>.<\/em><\/em><\/p>\n<p><em><em>If you&rsquo;re more into watching than reading, I shamelessly recommend watching my talk <a href=\"https:\/\/softwaregarden.dev\/en\/talks\/java-records-for-intrigued\/\">Java Records for the Intrigued<\/a>.<\/em><\/em><\/p>\n<h4 id=\"tldr\">TL;DR:<\/h4>\n<p>In records, you can&rsquo;t do anything that can leak the control of the state outside. (Except, not very wise IMHO, keeping mutable objects as record components.) Apart from that everything could be done with records. Could doesn&rsquo;t mean should. ;-)<\/p>\n<h3 id=\"what-records-cannot\">What records cannot?<\/h3>\n<p>As written in <a href=\"https:\/\/openjdk.java.net\/jeps\/359\">JEP 359<\/a>, records are a &ldquo;restricted form of a class, just like <code>enum<\/code>&rdquo;. Of course, the enums and records don&rsquo;t have exactly the same limitations, but some are similar in their nature.<\/p>\n<p>Records can&rsquo;t inherit from the other classes, the other lasses can&rsquo;t inherit from the records. That&rsquo;s why the code below can&rsquo;t work, every line causes compilation error:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">record<\/span> <span style=\"color:#a6e22e\">CannotExtend<\/span>(<span style=\"color:#66d9ef\">int<\/span> a) <span style=\"color:#66d9ef\">extends<\/span> java.<span style=\"color:#a6e22e\">util<\/span>.<span style=\"color:#a6e22e\">Date<\/span> {}\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">ExtendingRecordDoesNotWork<\/span> <span style=\"color:#66d9ef\">extends<\/span> CannotExtend {}<\/span><\/span><\/code><\/pre><\/div>\n<p>Despite all records being objects inheriting from <code>java.lang.Record<\/code>, in record&rsquo;s definition the <code>extends<\/code> can&rsquo;t be used at all.\nAnd of course after being created the record classes are <em>implicite<\/em> <code>final<\/code>, that&rsquo;s why a record cannot be <code>abstract<\/code> and\/or declare\u00a0<code>abstract<\/code> members. All fields are <code>final<\/code> as well.<\/p>\n<p>Beside that records can&rsquo;t declare fields which aren&rsquo;t coming from the declaration \/ canonical constructor:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">record<\/span> <span style=\"color:#a6e22e\">NoExtraFields<\/span>(<span style=\"color:#66d9ef\">int<\/span> field1) {\n<\/span><\/span><span style=\"display:flex;\"><span>\t<span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#66d9ef\">final<\/span> <span style=\"color:#66d9ef\">int<\/span> field2;\n<\/span><\/span><span style=\"display:flex;\"><span>}<\/span><\/span><\/code><\/pre><\/div>\n<p>Creating field <code>field2<\/code> this way won&rsquo;t work.<\/p>\n<p>Records can&rsquo;t change the value of the fields, that&rsquo;s why we can&rsquo;t have something like a &lsquo;setter&rsquo;<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">record<\/span> <span style=\"color:#a6e22e\">NoSetters<\/span>(<span style=\"color:#66d9ef\">int<\/span> field) {\n<\/span><\/span><span style=\"display:flex;\"><span>\t<span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#66d9ef\">void<\/span> <span style=\"color:#a6e22e\">field<\/span>(<span style=\"color:#66d9ef\">int<\/span> newValue) {\n<\/span><\/span><span style=\"display:flex;\"><span>\t\t<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">field<\/span> <span style=\"color:#f92672\">=<\/span> newValue;\n<\/span><\/span><span style=\"display:flex;\"><span>\t}\n<\/span><\/span><span style=\"display:flex;\"><span>}<\/span><\/span><\/code><\/pre><\/div>\n<p>Of course, some names of components are actually restricted. E.g. we can&rsquo;t name a component <code>hashCode<\/code>, because then we&rsquo;d have a <code>hashCode()<\/code> method and the accessor method clash.<\/p>\n<p>In records, we also can&rsquo;t have <code>native<\/code> methods. That makes sense, because such a method could change the state of the record, and the records are meant as immutable data containers (at lest to me). Kind of capsules for data. In this aspect they resemble <code>enum<\/code> or <code>String<\/code>. Once you have an instance in your hand, then (at least theoretically) you can&rsquo;t mingle inside and replace the contents. You can create a new instance which is an exact copy or something similar (like concatenated strings).<\/p>\n<p>By the way, if someone would like to use records for something that&rsquo;s not strictly about data transfer or aggregation, then I think I should advise not to use records for that purpose.<\/p>\n<h3 id=\"what-records-can\">What records can?<\/h3>\n<p>Records can implement interfaces:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">record<\/span> <span style=\"color:#a6e22e\">CanImplementInterfaces<\/span>(<span style=\"color:#66d9ef\">int<\/span> a, <span style=\"color:#66d9ef\">int<\/span> b) <span style=\"color:#66d9ef\">implements<\/span> Comparable<span style=\"color:#f92672\">&lt;<\/span>CanImplementInterfaces<span style=\"color:#f92672\">&gt;<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span>\t<span style=\"color:#a6e22e\">@Override<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>\t<span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#66d9ef\">int<\/span> <span style=\"color:#a6e22e\">compareTo<\/span>(CanImplementInterfaces that) {\n<\/span><\/span><span style=\"display:flex;\"><span>\t\t<span style=\"color:#66d9ef\">return<\/span> Objects.<span style=\"color:#a6e22e\">compare<\/span>(<span style=\"color:#66d9ef\">this<\/span>, that,\n<\/span><\/span><span style=\"display:flex;\"><span>\t\t\tComparator.<span style=\"color:#a6e22e\">comparing<\/span>(CanImplementInterfaces::a)\n<\/span><\/span><span style=\"display:flex;\"><span>\t\t\t    .<span style=\"color:#a6e22e\">thenComparing<\/span>(CanImplementInterfaces::b));\n<\/span><\/span><span style=\"display:flex;\"><span>\t}\n<\/span><\/span><span style=\"display:flex;\"><span>}<\/span><\/span><\/code><\/pre><\/div>\n<p>The above example shows one more option instantly: records can have other methods than accessors, <code>toString()<\/code>, <code>equals()<\/code> and <code>hashCode()<\/code>. They&rsquo;re not limited to implementations of methods declared in interfaces:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">record<\/span> <span style=\"color:#a6e22e\">CustomMethods<\/span>(<span style=\"color:#66d9ef\">int<\/span> a, <span style=\"color:#66d9ef\">int<\/span> b) {\n<\/span><\/span><span style=\"display:flex;\"><span>\t<span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#66d9ef\">void<\/span> <span style=\"color:#a6e22e\">printHello<\/span>(String to) {\n<\/span><\/span><span style=\"display:flex;\"><span>\t\tSystem.<span style=\"color:#a6e22e\">out<\/span>.<span style=\"color:#a6e22e\">println<\/span>(<span style=\"color:#e6db74\">&#34;Hello &#34;<\/span> <span style=\"color:#f92672\">+<\/span> to);\n<\/span><\/span><span style=\"display:flex;\"><span>\t}\n<\/span><\/span><span style=\"display:flex;\"><span>}<\/span><\/span><\/code><\/pre><\/div>\n<p>However, we need to ask ourselves the question if the records are really meant to have methods not related to date they keep inside? I think they shouldn&rsquo;t, but technically they can.<\/p>\n<p>Records can have static fields and methods too:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">record<\/span> <span style=\"color:#a6e22e\">StaticMembers<\/span>(<span style=\"color:#66d9ef\">int<\/span> a) {\n<\/span><\/span><span style=\"display:flex;\"><span>\t<span style=\"color:#66d9ef\">private<\/span> <span style=\"color:#66d9ef\">static<\/span> String FOO <span style=\"color:#f92672\">=<\/span> <span style=\"color:#e6db74\">&#34;bar&#34;<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>\t<span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#66d9ef\">static<\/span> String <span style=\"color:#a6e22e\">bar<\/span>() {\n<\/span><\/span><span style=\"display:flex;\"><span>\t\t<span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#e6db74\">&#34;foo&#34;<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>\t}\n<\/span><\/span><span style=\"display:flex;\"><span>}<\/span><\/span><\/code><\/pre><\/div>\n<p>They can have just one component:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">record<\/span> <span style=\"color:#a6e22e\">OneField<\/span>(<span style=\"color:#66d9ef\">int<\/span> a) {}<\/span><\/span><\/code><\/pre><\/div>\n<p>What&rsquo;s more, they can have no components at all:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">record<\/span> <span style=\"color:#a6e22e\">NoField<\/span>() {}<\/span><\/span><\/code><\/pre><\/div>\n<p>Again: technically that&rsquo;s possible. Does it make a practical sense though? Maybe an <code>enum<\/code> should be used instead?<\/p>\n<h3 id=\"overwriting-generated-methods\">Overwriting generated methods<\/h3>\n<p>A very nice property of the records is that they have some methods present right away. If they need to be overwritten them though, it&rsquo;s possible. However, I&rsquo;d suggest to be reasonable when doing that and of course these implementations need to obey the contracts. In particular the <code>equals()<\/code> i <code>hashCode()<\/code> should be compatible with each other. They can be overwritten the following way, for example:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">record<\/span> <span style=\"color:#a6e22e\">CustomEqualsAndHashCode<\/span>(String string, <span style=\"color:#66d9ef\">int<\/span> a) {\n<\/span><\/span><span style=\"display:flex;\"><span>\t<span style=\"color:#75715e\">\/\/Please keep in mind that equals and hashCode need to obey their contracts!<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>\t<span style=\"color:#a6e22e\">@Override<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>\t<span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#66d9ef\">boolean<\/span> <span style=\"color:#a6e22e\">equals<\/span>(Object o) {\n<\/span><\/span><span style=\"display:flex;\"><span>\t\t<span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#66d9ef\">this<\/span> <span style=\"color:#f92672\">==<\/span> o) <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">true<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>\t\t<span style=\"color:#66d9ef\">if<\/span> (o <span style=\"color:#f92672\">==<\/span> <span style=\"color:#66d9ef\">null<\/span> <span style=\"color:#f92672\">||<\/span> getClass() <span style=\"color:#f92672\">!=<\/span> o.<span style=\"color:#a6e22e\">getClass<\/span>()) <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">false<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span>\t\tCustomEqualsAndHashCode that <span style=\"color:#f92672\">=<\/span> (CustomEqualsAndHashCode) o;\n<\/span><\/span><span style=\"display:flex;\"><span>\t\t<span style=\"color:#66d9ef\">return<\/span> a <span style=\"color:#f92672\">==<\/span> that.<span style=\"color:#a6e22e\">a<\/span> <span style=\"color:#f92672\">&amp;&amp;<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>\t\t\tObjects.<span style=\"color:#a6e22e\">equals<\/span>(string, that.<span style=\"color:#a6e22e\">string<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>\t}\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span>\t<span style=\"color:#a6e22e\">@Override<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>\t<span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#66d9ef\">int<\/span> <span style=\"color:#a6e22e\">hashCode<\/span>() {\n<\/span><\/span><span style=\"display:flex;\"><span>\t\t<span style=\"color:#66d9ef\">return<\/span> Objects.<span style=\"color:#a6e22e\">hash<\/span>(string, a);\n<\/span><\/span><span style=\"display:flex;\"><span>\t}\n<\/span><\/span><span style=\"display:flex;\"><span>}<\/span><\/span><\/code><\/pre><\/div>\n<p>It&rsquo;s also possible to overwrite components&rsquo; accessors. I&rsquo;m not sure why would one want to do that (except creating defense copies of mutable components), but it&rsquo;s possible. Here you go:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">record<\/span> <span style=\"color:#a6e22e\">CustomAccessor<\/span>(<span style=\"color:#66d9ef\">int<\/span> secret) {\n<\/span><\/span><span style=\"display:flex;\"><span>\t<span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#66d9ef\">int<\/span> <span style=\"color:#a6e22e\">secret<\/span>() {\n<\/span><\/span><span style=\"display:flex;\"><span>\t\tSystem.<span style=\"color:#a6e22e\">out<\/span>.<span style=\"color:#a6e22e\">println<\/span>(<span style=\"color:#e6db74\">&#34;Here&#39;s my public secret. Please don&#39;t tell anybody...&#34;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span>\t\t<span style=\"color:#66d9ef\">return<\/span> secret;\n<\/span><\/span><span style=\"display:flex;\"><span>\t}\n<\/span><\/span><span style=\"display:flex;\"><span>}<\/span><\/span><\/code><\/pre><\/div>\n<p>When overwriting the accessors we shall not forget that the return type must match exactly. E.g. an accessor to component of type <code>String<\/code> has to return <code>String<\/code> type, not <code>Object<\/code>, <code>Serializable<\/code> or <code>CharacterSequence<\/code>.<\/p>\n<h3 id=\"le-dessert-constructors\">Le dessert: constructors<\/h3>\n<p>When it comes to constructors in the records, they come in three flavours. There&rsquo;s always present (because it&rsquo;s created by the compiler based on record&rsquo;s definition) so called &lsquo;canonical constructor&rsquo;. If the record <code>R<\/code> declares components <code>A a<\/code>, <code>B b<\/code>, <code>C c<\/code>, then the canonical constructor has parameter in exactly the same order, and it&rsquo;s executed whenever you call <code>new R(a, b, c);<\/code><\/p>\n<p>Just like all generated methods, the canonical constrictor can be overwritten too. It might be handy when we need to check in the constructor if the data for the record makes some sense, because we might not want to create a record instance for such data combination at all. E.g. having four fields it might be required that the first is always different from the second, and the third from the fourth:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">record<\/span> <span style=\"color:#a6e22e\">CustomCanonicalConstructor<\/span>(<span style=\"color:#66d9ef\">int<\/span> a, <span style=\"color:#66d9ef\">int<\/span> b, <span style=\"color:#66d9ef\">int<\/span> c, <span style=\"color:#66d9ef\">int<\/span> d) {\n<\/span><\/span><span style=\"display:flex;\"><span>\t<span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#a6e22e\">CustomCanonicalConstructor<\/span>(<span style=\"color:#66d9ef\">int<\/span> a, <span style=\"color:#66d9ef\">int<\/span> b, <span style=\"color:#66d9ef\">int<\/span> c, <span style=\"color:#66d9ef\">int<\/span> d) {\n<\/span><\/span><span style=\"display:flex;\"><span>\t\t<span style=\"color:#66d9ef\">assert<\/span> (a <span style=\"color:#f92672\">!=<\/span> b);\n<\/span><\/span><span style=\"display:flex;\"><span>\t\t<span style=\"color:#66d9ef\">assert<\/span> (c <span style=\"color:#f92672\">!=<\/span> d);\n<\/span><\/span><span style=\"display:flex;\"><span>\t\t<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">a<\/span> <span style=\"color:#f92672\">=<\/span> a;\n<\/span><\/span><span style=\"display:flex;\"><span>\t\t<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">b<\/span> <span style=\"color:#f92672\">=<\/span> b;\n<\/span><\/span><span style=\"display:flex;\"><span>\t\t<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">c<\/span> <span style=\"color:#f92672\">=<\/span> c;\n<\/span><\/span><span style=\"display:flex;\"><span>\t\t<span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">d<\/span> <span style=\"color:#f92672\">=<\/span> d;\n<\/span><\/span><span style=\"display:flex;\"><span>\t}\n<\/span><\/span><span style=\"display:flex;\"><span>}<\/span><\/span><\/code><\/pre><\/div>\n<p>(I&rsquo;m really wondering how the &rsquo;let&rsquo;s increase the performance by primitive obsession&rsquo; would like to do that when constructing an int[]&hellip; ;-) )<\/p>\n<p>One of the very nice properties of the records is that they allow getting rid of many lines of the ceremonial code, despite it&rsquo;s not an official goal from the JEP. Sadly, overwriting the canonical constructor doesn&rsquo;t look nice. Just to introduce to assertions we had to repeat four parameters and four assignments. Nah, it doesn&rsquo;t look good&hellip;<br>\nLuckily, to avoid that repetition, if all we need to add to the constructor is just a bit of a logic, we can use for that purpose so called &lsquo;compact constructor&rsquo;. The difference is we don&rsquo;t have to repeat &lsquo;obvious things&rsquo;, meaning: parameters and assignments:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">record<\/span> <span style=\"color:#a6e22e\">CustomCompactConstructor<\/span>(<span style=\"color:#66d9ef\">int<\/span> a, <span style=\"color:#66d9ef\">int<\/span> b, <span style=\"color:#66d9ef\">int<\/span> c, <span style=\"color:#66d9ef\">int<\/span> d) {\n<\/span><\/span><span style=\"display:flex;\"><span>\t<span style=\"color:#66d9ef\">public<\/span> CustomCompactConstructor {\n<\/span><\/span><span style=\"display:flex;\"><span>\t\t<span style=\"color:#66d9ef\">assert<\/span> (a <span style=\"color:#f92672\">!=<\/span> b);\n<\/span><\/span><span style=\"display:flex;\"><span>\t\t<span style=\"color:#66d9ef\">assert<\/span> (c <span style=\"color:#f92672\">!=<\/span> d);\n<\/span><\/span><span style=\"display:flex;\"><span>\t}\n<\/span><\/span><span style=\"display:flex;\"><span>}<\/span><\/span><\/code><\/pre><\/div>\n<p>Besides, there&rsquo;s one mode kind of constructions available in the records. I guess it might be useful in rather non-standard situations, when we&rsquo;d like to have the list of parameters in the constructor to be different from record&rsquo;s header. We can initialise a record using another object and extract some data from that object. E.g. we might want to have a record (due to some weird reason) which keeps the length and the <code>hashCode<\/code> of a string. Then to avoid calling <code>length()<\/code> and <code>hashCode()<\/code> methods &lsquo;manually&rsquo; and sending the results as arguments to the constructor, we can hide this extraction in a custom constructor.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">record<\/span> <span style=\"color:#a6e22e\">CustomNonCanonicalConstructor<\/span>(<span style=\"color:#66d9ef\">int<\/span> length, <span style=\"color:#66d9ef\">int<\/span> hash) {\n<\/span><\/span><span style=\"display:flex;\"><span>\t<span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#a6e22e\">CustomNonCanonicalConstructor<\/span>(String string) {\n<\/span><\/span><span style=\"display:flex;\"><span>\t\t<span style=\"color:#66d9ef\">this<\/span>(string.<span style=\"color:#a6e22e\">length<\/span>(), string.<span style=\"color:#a6e22e\">hashCode<\/span>());\n<\/span><\/span><span style=\"display:flex;\"><span>\t}\n<\/span><\/span><span style=\"display:flex;\"><span>}<\/span><\/span><\/code><\/pre><\/div>\n<p>We shall not forget that the canonical constructor exists always and that some rules apply when calling a constructor from a constructor. In particular, <code>this(...)<\/code> must be the first instruction.<\/p>\n"},{"title":"Records in Java - why and what for","link":"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/records\/intro\/","pubDate":"Sat, 09 May 2020 10:40:07 +0200","guid":"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/records\/intro\/","description":"<h3 id=\"java-has-the-record\">Java has the record<\/h3>\n<p>Java 14 introduced records as a <em>preview feature<\/em>. There was (is?) a decent amount of confusion, declarations and even heavy insults against &rsquo;enemy&rsquo; libraries and IDE plugins. Let me take part in this, please.<\/p>\n<p>First of all one could say: finally. After <code>case classes<\/code> in Scala and <code>data classes<\/code> in Kotlin, &rsquo;they finally do that in Java&rsquo;. That&rsquo;s true, but we need to add a few pieces to get the full picture.<\/p>\n<ul>\n<li>Java tries to be backward compatible as much as possible (if that&rsquo;s good or if that&rsquo;s bad, that&rsquo;s another thing).<\/li>\n<li>In May 2020 Java celebrated 25 anniversary and was in the full bloom, it&rsquo;s not a new language without any ecosystem, so the changes need to fit in and make sense, linke in any other mature system or technology.<\/li>\n<li>The hordes of developers need to get prepared for the changes, so drop-by-drop causing to be a better approach than an ice-bucket-challenge.<\/li>\n<\/ul>\n<p>If you&rsquo;d like to start with something formal, I recommend reading and understanding <a href=\"https:\/\/openjdk.java.net\/jeps\/359\">JEP 359<\/a>.<\/p>\n<h3 id=\"my-perception-of-the-records\">My perception of the records<\/h3>\n<p>I think I&rsquo;d start explaining &lsquo;what records are&rsquo; with &lsquo;forget everything you know about Java and let&rsquo;s start from scratch&rsquo;. Then I would focus on one sentence from the JEP, which I really like: <em>Records can be considered a nominal form of tuples<\/em>. Or, as I think Mr. Brian Goetz stated somewhere, <em>named tuples<\/em>. All right, but what are these <em>tuples<\/em>? Well, let&rsquo;s take a look in the friendly yard of SQL. When you type:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-sql\" data-lang=\"sql\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">SELECT<\/span> (gross_weight, gross_volume) <span style=\"color:#66d9ef\">FROM<\/span> packages;<\/span><\/span><\/code><\/pre><\/div>\n<p>as the result you&rsquo;ll get a set of <em>tuples<\/em>, each of them having two elements. (Yes, your DB access programme most probably shows them in a table, that&rsquo;s why they seem to look like rows.)\nIn Java the method returning mass and volume of a single package can be written like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span>GrossWeightAndVolume <span style=\"color:#a6e22e\">getGrossWeightAndVolume<\/span>(PackageID id) {...}<\/span><\/span><\/code><\/pre><\/div>\n<p>However, in order to make this work, we need to create another class <code>GrossWeightAndVolume<\/code>, most probably as a <em>JavaBean<\/em>, together with constructor, getters, and adding <code>equals()<\/code>, <code>hashCode()<\/code>, maybe even <code>toString()<\/code> might be needed too, to have nice output in logs. Instead, we could employ Project Lombok and use <code>@Value<\/code> annotation. (Using Lombok has its prons and cons but that&rsquo;s a story for another post.)<\/p>\n<p>In this very moment the &lsquo;performance maniacs&rsquo; come in and because of &lsquo;increasing the performance&rsquo; instead of another type (the size of the JARs, classloader, &hellip; they say) they insist on using primitive types and in this madness they write the signature of the method as de facto dictated by the SQL query, using an array to represent the tuples:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">double<\/span><span style=\"color:#f92672\">[]<\/span> <span style=\"color:#a6e22e\">getGrossWeightAndVolume<\/span>(<span style=\"color:#66d9ef\">long<\/span> id) {...}<\/span><\/span><\/code><\/pre><\/div>\n<p>Trouble is, having such a SQL query, we can have another one (let&rsquo;s not focus on the &lsquo;business value&rsquo; for the sake of example):<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-sql\" data-lang=\"sql\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">SELECT<\/span> (total_mileage, trunk_volume) <span style=\"color:#66d9ef\">FROM<\/span> cars;<\/span><\/span><\/code><\/pre><\/div>\n<p>You can again create a JavaBean (and maintain it!) or happily use <code>double[]<\/code>.<\/p>\n<p>Things get &lsquo;fun&rsquo; when we realise that the tuples coming both in the SQL, both in <code>double[]<\/code> need to be taken care of really well, because they can never get mixed. If they get mixed, we can suddenly encounter absurds like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-sql\" data-lang=\"sql\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">SELECT<\/span> (gross_weight, gross_volume) <span style=\"color:#66d9ef\">FROM<\/span> packages\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">UNION<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">SELECT<\/span> (total_mileage, trunk_volume) <span style=\"color:#66d9ef\">FROM<\/span> cars;<\/span><\/span><\/code><\/pre><\/div>\n<p>Two <code>double[]<\/code> can be mixed exactly the same way. Can it be even &lsquo;funnier&rsquo;? Of course! We&rsquo;re not skipping types and compiler to be bored&hellip; What happens when we need to return an integer and a floating number? Then we have to change the array to <code>Number[]<\/code>, the <em>autoboxing<\/em> kicks in&hellip; Maybe we need to add a String too&hellip; so what do we then? <code>Serializable[]<\/code>? &lsquo;But you don&rsquo;t have to, you can use the <code>Pair<\/code> or the <code>Triple<\/code> class with generics!&rsquo;. Right, but how can we tell then that one <code>Pair&lt;Double, Double&gt;<\/code> can&rsquo;t be mixed with another <code>Pair&lt;Double, Double&gt;<\/code> which logically and semantically keeps something different? When you see <code>Set&lt;Pair&lt;Double, Double&gt;&gt;<\/code>, what do you expect to find inside? Package sizes? Complex numbers?<\/p>\n<p>Every time when you get rid of type control in Java checked by the compiler, and you start treating the same types differently depending on the context, then to the name <em>Java<\/em> you actually add <em>Script<\/em>.<\/p>\n<p>IMHO for these reasons, in order not to mix plums with Camaros, Java has <em>named<\/em> tuples, which are called <em>records<\/em>.<\/p>\n<h3 id=\"how-to-create-a-record\">How to create a record?<\/h3>\n<p>Very easy. JEP says the records are a &lsquo;restricted form of a class, just like <code>enum<\/code>&rsquo;. If you&rsquo;d like to define a record e.g. for <a href=\"https:\/\/en.wikipedia.org\/wiki\/Complex_number\">complex numbers<\/a>, it can be written like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">record<\/span> <span style=\"color:#a6e22e\">Complex<\/span>(<span style=\"color:#66d9ef\">double<\/span> real, <span style=\"color:#66d9ef\">double<\/span> imaginary) {}<\/span><\/span><\/code><\/pre><\/div>\n<p>If you need to keep the mass, and the size of packages, another record can be defined:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span><span style=\"color:#66d9ef\">record<\/span> <span style=\"color:#a6e22e\">PackageSize<\/span>(<span style=\"color:#66d9ef\">double<\/span> grossWeight, <span style=\"color:#66d9ef\">double<\/span> grossVolume) {}<\/span><\/span><\/code><\/pre><\/div>\n<p>What&rsquo;s the outcome? The compiler will instantly create for us:<\/p>\n<ul>\n<li>canonical constructor, so we can create new instances of records: <code>Complex aComplex = new Complex(3.0, 1.7);<\/code><\/li>\n<li>accessors for each component, so we can e.g. get the real part: <code>double x = aComplex.real();<\/code><\/li>\n<li><code>equals()<\/code> and <code>hashCode()<\/code> methods using all record&rsquo;s components,<\/li>\n<li><code>toString()<\/code> method which will return the name of the record&rsquo;s class plus the names and values of all the components, e.g. <code>Complex[real=3.0, imaginary=1.7]<\/code><\/li>\n<\/ul>\n<p>And that&rsquo;s actually it when it comes to generated items. However, it hurts me a bit that we, the developers, forget about even more important aspect of the records: a record gives us the name and the type! So having:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span>Set<span style=\"color:#f92672\">&lt;<\/span>Complex<span style=\"color:#f92672\">&gt;<\/span> aSet <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> Set<span style=\"color:#f92672\">&lt;&gt;<\/span>();<\/span><\/span><\/code><\/pre><\/div>\n<p>we cannot add to this set a different kind of record (even if it has exactly the same components):<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span><span style=\"color:#75715e\">\/\/ no way, na da<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>aSet.<span style=\"color:#a6e22e\">add<\/span>(<span style=\"color:#66d9ef\">new<\/span> PackageSize(15.<span style=\"color:#a6e22e\">0<\/span>, 10.<span style=\"color:#a6e22e\">0<\/span>));<\/span><\/span><\/code><\/pre><\/div>\n<p>It helps to remember that the compiles is not an old grumpy architect, but a friendly pal, who is always pair programming with you.<\/p>\n<h3 id=\"read-only\">Read only<\/h3>\n<p>If you have missed that by any chance it&rsquo;s worth highlighting, that the records don&rsquo;t have anything like &lsquo;setters&rsquo;. For each component only the access\/read method is generated, there is no method to change them.\nOf course, under the hood the value of each component is stored as a &lsquo;private final&rsquo; field, so it&rsquo;s obvious the references can&rsquo;t be changed or overwritten. What can be done, is to have as a component something that&rsquo;s mutable, like &lsquo;ArrayList&rsquo; or &lsquo;AtomicInteger&rsquo;. However, it doesn&rsquo;t seem to be always reasonable.<\/p>\n<p>In the <a href=\"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/records\/can-and-cannot\/\">next post<\/a>  I describe what can be and what cannot be done with the records.<\/p>\n"},{"title":"How not to use (pattern matching with) instanceof","link":"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/how-not-to-use-instanceof\/","pubDate":"Thu, 07 May 2020 10:08:10 +0200","guid":"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/how-not-to-use-instanceof\/","description":"<h3 id=\"could-doesnt-mean-should-and-sometimes-you-shouldnt\">Could doesn&rsquo;t mean should (and sometimes you shouldn&rsquo;t)<\/h3>\n<p><em>(This post got updated. Please scroll down.)<\/em><\/p>\n<p>In the chase for non-trivial examples to illustrate possible usage of JEP 305 (described by me <a href=\"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/pattern-matching-beginning\/\">here<\/a>), some people might have gone too far, I guess. In particular into the more challenging area of the <code>equals()<\/code> method, present in all Java objects. Let&rsquo;s do something, which makes some of my fellow developers truly shocked: let&rsquo;s RTFM of the <a href=\"https:\/\/docs.oracle.com\/en\/java\/javase\/14\/docs\/api\/java.base\/java\/lang\/Object.html#equals(java.lang.Object)\"><code>Object.equals()<\/code><\/a> method. We can read there which conditions <strong>must<\/strong> be satisfied by a correct implementation of the <code>equals()<\/code> method. One of them is <em>symmetric<\/em>: having any two objects <code>x<\/code> and <code>y<\/code>, <code>calling x.equals(y)<\/code> and <code>y.equals(x)<\/code> must have the same result. Both have to be <code>true<\/code> or both have to be <code>false<\/code>. If one of them is <code>true<\/code> and the other is <code>false<\/code>, then the <code>equals()<\/code> method hasn&rsquo;t been implemented correctly. Deal with that.<\/p>\n<p>One of the myths of the programming world is that &ldquo;inheritance is BAD&rdquo;. (Having enough time I talk about this in <a href=\"https:\/\/softwaregarden.dev\/en\/talks\/context\/\">CONTEXTVS, STVLTE!<\/a>)<\/p>\n<p>Inheritance and type hierarchies aren&rsquo;t bad per se. I really can&rsquo;t tell how someone can never ever use the inheritance and call it &lsquo;object oriented programming&rsquo;. What is bad is the clueless usage of the inheritance when it shouldn&rsquo;t be used, because e.g. it violates the <a href=\"https:\/\/en.wikipedia.org\/w\/index.php?title=Liskov_substitution_principle\">Liskov Substitution Principle<\/a>. Add mindless usage of the JEP 305 to that, and we have a recipe for a disaster.<\/p>\n<h3 id=\"all-right-what-do-you-mean\">All right, what do you mean?<\/h3>\n<p>Let&rsquo;s take a look at this code (an excerpt of <a href=\"https:\/\/github.com\/pioorg\/DeepDiveJava14\/blob\/master\/src\/main\/java\/org\/przybyl\/ddj14\/patternMatching\/EqualsAndInstanceOf.java\">this one<\/a>):<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 1<\/span><span><span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">Point<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 2<\/span><span>\t<span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#66d9ef\">final<\/span> <span style=\"color:#66d9ef\">int<\/span> x;\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 3<\/span><span>\t<span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#66d9ef\">final<\/span> <span style=\"color:#66d9ef\">int<\/span> y;\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 4<\/span><span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 5<\/span><span>\t<span style=\"color:#a6e22e\">@Override<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 6<\/span><span>\t<span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#66d9ef\">boolean<\/span> <span style=\"color:#a6e22e\">equals<\/span>(Object o) {\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 7<\/span><span>\t\t<span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#66d9ef\">this<\/span> <span style=\"color:#f92672\">==<\/span> o) <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">true<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 8<\/span><span>\t\t<span style=\"color:#66d9ef\">if<\/span> (o <span style=\"color:#66d9ef\">instanceof<\/span> Point that) {\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 9<\/span><span>\t\t\t<span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">x<\/span> <span style=\"color:#f92672\">==<\/span> that.<span style=\"color:#a6e22e\">x<\/span> <span style=\"color:#f92672\">&amp;&amp;<\/span> <span style=\"color:#66d9ef\">this<\/span>.<span style=\"color:#a6e22e\">y<\/span> <span style=\"color:#f92672\">==<\/span> that.<span style=\"color:#a6e22e\">y<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">10<\/span><span>\t\t}\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">11<\/span><span>\t\t<span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">false<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">12<\/span><span>\t}\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">13<\/span><span>\t<span style=\"color:#75715e\">\/\/ ...<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">14<\/span><span>}<\/span><\/span><\/code><\/pre><\/div>\n<p>It looks innocent at the first glance, right? Can we push that? Few weeks pass, and an innocent Junior comes in, who &lsquo;only needs to implement Point, but in 3D, you see&rsquo;:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 1<\/span><span><span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">Point3D<\/span> <span style=\"color:#66d9ef\">extends<\/span> Point {\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 2<\/span><span>\t<span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#66d9ef\">final<\/span> <span style=\"color:#66d9ef\">int<\/span> z;\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 3<\/span><span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 4<\/span><span>\t<span style=\"color:#a6e22e\">@Override<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 5<\/span><span>\t<span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#66d9ef\">boolean<\/span> <span style=\"color:#a6e22e\">equals<\/span>(Object o) {\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 6<\/span><span>\t\t<span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#66d9ef\">this<\/span> <span style=\"color:#f92672\">==<\/span> o) <span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">true<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 7<\/span><span>\t\t<span style=\"color:#66d9ef\">if<\/span> (o <span style=\"color:#66d9ef\">instanceof<\/span> Point3D that) {\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 8<\/span><span>\t\t\t<span style=\"color:#66d9ef\">if<\/span> (<span style=\"color:#f92672\">!<\/span><span style=\"color:#66d9ef\">super<\/span>.<span style=\"color:#a6e22e\">equals<\/span>(o))\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 9<\/span><span>\t\t\t\t<span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">false<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">10<\/span><span>\t\t\t<span style=\"color:#66d9ef\">return<\/span> z <span style=\"color:#f92672\">==<\/span> that.<span style=\"color:#a6e22e\">z<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">11<\/span><span>\t\t}\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">12<\/span><span>\t\t<span style=\"color:#66d9ef\">return<\/span> <span style=\"color:#66d9ef\">false<\/span>;\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">13<\/span><span>\t}\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">14<\/span><span>    <span style=\"color:#75715e\">\/\/...<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">15<\/span><span>}<\/span><\/span><\/code><\/pre><\/div>\n<p>It may look innocent at the first glance too&hellip; However, running a simple check of correctness of the <code>equals()<\/code> method:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1<\/span><span><span style=\"color:#66d9ef\">var<\/span> point <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> Point (1,1);\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">2<\/span><span><span style=\"color:#66d9ef\">var<\/span> point3D <span style=\"color:#f92672\">=<\/span> <span style=\"color:#66d9ef\">new<\/span> Point3D(1,1,1);\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">3<\/span><span>System.<span style=\"color:#a6e22e\">out<\/span>.<span style=\"color:#a6e22e\">println<\/span>(point.<span style=\"color:#a6e22e\">equals<\/span>(point3D));\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">4<\/span><span>System.<span style=\"color:#a6e22e\">out<\/span>.<span style=\"color:#a6e22e\">println<\/span>(point3D.<span style=\"color:#a6e22e\">equals<\/span>(point));<\/span><\/span><\/code><\/pre><\/div>\n<p>yields:<\/p>\n<pre><code>true\nfalse\n<\/code><\/pre>\n<p>The conclusion is simple: the implementation of the <code>equals()<\/code> methods is not symmetric. Oh my, but why, oh my? Well, JEP 305 is IMHO quite like any other technology: it should be used correctly, not misused, like in this very case. The mistake is in line 8. &lsquo;But hey, it&rsquo;s just using <em>pattern matching with instanceof<\/em>, it was made for this purpose, don&rsquo;t you know?&rsquo; Well, I don&rsquo;t think so. Point3D is not &ldquo;ah, you see, just an ordinary point, only one more axis&rdquo; and it&rsquo;s incorrect to compare in equals everything that is a point. Yeap, the <code>instanceof<\/code> yields <code>true<\/code> not only for objects of <em>exactly the same type<\/em>, but also for <em>every type, which inherits<\/em>. Yeap, I know, it&rsquo;s truism. But boy, I&rsquo;ve seen too much code to know that this truism isn&rsquo;t as widely known as it should be&hellip;<\/p>\n<h3 id=\"loosen-your-tie-please\">Loosen your tie, please<\/h3>\n<p>In real life (not tutorial one) we need to be pragmatic. Sometimes implementing <code>equals()<\/code> using <code>instanceof<\/code> and JEP 305 isn&rsquo;t bad, if we all in the team are aware of the consequences, we will never inherit from this type, and we need to check identity this way, because some frameworks spawn inheriting proxy classes, e.g. from our entities.<\/p>\n<p>So let me ask you this, please: when you see somewhere in a code (production or blog) <code>instanceof<\/code> inside the <code>equals()<\/code> method, be aware. And don&rsquo;t copy &amp; paste random code from the Internet. Context, stupid!<\/p>\n<h3 id=\"the-update\">The update<\/h3>\n<p>To make things clear and avoid some misunderstanding, I&rsquo;ve decided to follow advice from Nicolai Parlog to update this entry in April 2022.<\/p>\n<p>Using <code>instanceof<\/code> in <code>equals()<\/code> is not problematic itself. Also using inheritance in Java isn&rsquo;t problematic itself. Just as using a hammer is not. But the misuse <em>is<\/em>.<\/p>\n<p>Trouble comes when these are misused, especially together: <code>equals()<\/code> relying on <code>instanceof<\/code> plus child classes.<\/p>\n<p>The remedy to this is quite simple: ideally make the class <code>final<\/code>. <code>Point3D<\/code> isn&rsquo;t &ldquo;a <code>Point<\/code> with just one more extra dimension\/property&rdquo;. <code>sealed<\/code> class would also do, provided all classes have correct <code>equals<\/code>, I guess.\nIf you can&rsquo;t make the class final, then: <code>public final boolean equals(Object o)<\/code> is the way to go. By tossing <code>final<\/code> on <code>equals()<\/code> we at least make sure that there will be no asymmetrical behaviour of <code>equals<\/code>.<\/p>\n<ul>\n<li>&lsquo;Hold on, but then my <code>Point3D(1, 1, 1)<\/code> will be equal to <code>Point(1, 1)<\/code>, that&rsquo;s not what I want, because this point3D isn&rsquo;t equal to the point!!11one&rsquo;<\/li>\n<li>&lsquo;Exactly, didn&rsquo;t I tell you <em><code>Point3D<\/code> isn&rsquo;t &ldquo;a <code>Point<\/code> with just one more extra dimension\/property&rdquo;<\/em>? ;-)<\/li>\n<\/ul>\n<p>TL;DR: <code>final<\/code>ising makes <code>instanceof<\/code> in <code>equals<\/code> safe.\nTL;DR2: don&rsquo;t copy-paste random snippets from the internet without understanding the context, please.<\/p>\n"},{"title":"Pattern Matching - the beginning","link":"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/pattern-matching-beginning\/","pubDate":"Wed, 06 May 2020 20:08:10 +0200","guid":"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/pattern-matching-beginning\/","description":"<p>Java 14 has a lot of new features. One of them (as <em>preview feature<\/em>) is <em>pattern matching with <code>instanceof<\/code><\/em>. Some people programming in languages supporting the functional paradigm to some extent, e.g. Scala, Kotlin (not to mention Haskell) jumped high, full of joy &lsquo;Yay, we gonna have <code>match<\/code> or <code>when<\/code>, extracting data, guards, deconstructors in companion objects and more!&rsquo;\nWe&rsquo;re greedy. Since Java 9 and with major releases every 6 months Java is more of a &lsquo;baby steps&rsquo; approach (or slowly boiling frogs, if you will). And the first baby step having &lsquo;pattern matching&rsquo; in name is <a href=\"https:\/\/openjdk.java.net\/jeps\/305\">JEP 305: Pattern Matching for instanceof (Preview)<\/a>. (If the <em>switch expressions<\/em> aren&rsquo;t an earlier attempt to put some fire under this pot is another story, but at least the JEPs for <em>switch expressions<\/em> don&rsquo;t mention that in their names.)<\/p>\n<h3 id=\"matching-by-the-type\">Matching by the type<\/h3>\n<p>In my opinion this JEP is a nice beginning to pattern matching, and it also allows eliminating ceremony and &lsquo;obvious&rsquo; code. Let&rsquo;s throw an eye\u2122 in the code below in which we&rsquo;re checking if an <code>object<\/code> is an <code>Integer<\/code> and if so, we double it:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;display:grid;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1<\/span><span><span style=\"color:#66d9ef\">if<\/span> (object <span style=\"color:#66d9ef\">instanceof<\/span> Integer) {\n<\/span><\/span><span style=\"display:flex; background-color:#3c3d38\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">2<\/span><span>    Integer integer <span style=\"color:#f92672\">=<\/span> (Integer) object;\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">3<\/span><span>    <span style=\"color:#66d9ef\">int<\/span> doubled <span style=\"color:#f92672\">=<\/span> integer <span style=\"color:#f92672\">*<\/span> 2;\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">4<\/span><span>    <span style=\"color:#75715e\">\/\/here we&#39;re doing something with doubled...<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">5<\/span><span>}<\/span><\/span><\/code><\/pre><\/div>\n<p>Line 2 from the listing above is somewhat controversial to many and (let&rsquo;s speak frankly) is a reason to say that &lsquo;Java is full of ceremony&rsquo;. Well, this might be somewhat true, because if in the first line we&rsquo;ve already checked that &lsquo;it must be an <code>Integer<\/code>&rsquo;, then is the casting in the second line really needed? Can&rsquo;t <code>object<\/code> be used as an <code>Integer<\/code>in line 2 right away? &lsquo;C&rsquo;mon, I know already it&rsquo;s an <code>Integer<\/code>, you&rsquo;ve let me into this <code>if<\/code>, what else do you want??!!1one&rsquo;<\/p>\n<p>Since Java 14 the JEP 305 mentioned earlier can help us. Using it we can rewrite the above code like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;display:grid;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1<\/span><span><span style=\"color:#66d9ef\">if<\/span> (object <span style=\"color:#66d9ef\">instanceof<\/span> Integer integer) {\n<\/span><\/span><span style=\"display:flex; background-color:#3c3d38\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">2<\/span><span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">3<\/span><span>    <span style=\"color:#66d9ef\">int<\/span> doubled <span style=\"color:#f92672\">=<\/span> integer <span style=\"color:#f92672\">*<\/span> 2;\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">4<\/span><span>    <span style=\"color:#75715e\">\/\/here we&#39;re doing something with doubled...<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">5<\/span><span>}<\/span><\/span><\/code><\/pre><\/div>\n<p>What happened to line 2? Well, casting isn&rsquo;t needed anymore. Now, instead of casting, all we need after typing <code>instanceof &lt;AClass&gt;<\/code> is to type a variable name for the variable if its type matches <code>AClass<\/code>. In this case if the <code>object<\/code> successfully matches <code>AClass<\/code>, inside the <code>if<\/code> block it will be visible as <code>Integer integer<\/code>. We may think like &lsquo;casted alias&rsquo;. And we don&rsquo;t need the casting anymore.<\/p>\n<h3 id=\"lets-get-greedy\">Let&rsquo;s get greedy<\/h3>\n<p>This isn&rsquo;t over, my friends. Because we can use the matched object not only in the &lsquo;<code>if<\/code>&rsquo;s body&rsquo;, but also in the <code>if<\/code>&rsquo;s condition. Let&rsquo;s assume we have a &lsquo;business need&rsquo; to double the numbers, but only negative ones. The old-fashioned way of doing that would be:<\/p>\n<p><div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;display:grid;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1<\/span><span><span style=\"color:#66d9ef\">if<\/span> (object <span style=\"color:#66d9ef\">instanceof<\/span> Integer) {\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">2<\/span><span>    Integer integer <span style=\"color:#f92672\">=<\/span> (Integer) object;\n<\/span><\/span><span style=\"display:flex; background-color:#3c3d38\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">3<\/span><span>    <span style=\"color:#66d9ef\">if<\/span> (integer <span style=\"color:#f92672\">&lt;<\/span> 0) {\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">4<\/span><span>        <span style=\"color:#66d9ef\">int<\/span> doubled <span style=\"color:#f92672\">=<\/span> integer <span style=\"color:#f92672\">*<\/span> 2;\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">5<\/span><span>        <span style=\"color:#75715e\">\/\/here we&#39;re doing something with doubled...<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">6<\/span><span>    }\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">7<\/span><span>}<\/span><\/span><\/code><\/pre><\/div>\nIn such a case, beside the casting in line 2, we also need to nest another check. IT&rsquo;s getting nasty, isn&rsquo;t it? We can try to make this code cleaner, we may try to extract the doubling method, and so on. Or we can use JEP 305 even more and write it like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1<\/span><span><span style=\"color:#66d9ef\">if<\/span> (object <span style=\"color:#66d9ef\">instanceof<\/span> Integer integer <span style=\"color:#f92672\">&amp;&amp;<\/span> integer <span style=\"color:#f92672\">&lt;<\/span> 0) {\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">2<\/span><span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">3<\/span><span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">4<\/span><span>    <span style=\"color:#66d9ef\">int<\/span> doubled <span style=\"color:#f92672\">=<\/span> integer <span style=\"color:#f92672\">*<\/span> 2;\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">5<\/span><span>    <span style=\"color:#75715e\">\/\/here we&#39;re doing something with doubled...<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">6<\/span><span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">7<\/span><span>}<\/span><\/span><\/code><\/pre><\/div>\n<p>This time two\/three lines are gone (depends how we format and count the lines), but what&rsquo;s more important we don&rsquo;t have this nested block any more! (I intentionally left the blank lines for better readability and to make the lack of these lines more obvious. In the real code we don&rsquo;t do that.)<\/p>\n<p>In other words: we want to double our object if it matches the pattern &ldquo;an integer and a negative one&rdquo;. That&rsquo;s why this JEP IMHO is named &lsquo;pattern matching with instanceof&rsquo;.<\/p>\n<p>In the coming versions of Java we&rsquo;re awaiting even more sophisticated forms of pattern matching, with deconstruction and other goodies. Until then I suggest playing with what we already have, using <a href=\"https:\/\/github.com\/pioorg\/DeepDiveJava14\/blob\/master\/src\/main\/java\/org\/przybyl\/ddj14\/patternMatching\/InstanceOfPatternMatching.java\">this example<\/a>, for example.<\/p>\n<p>In the <a href=\"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/how-not-to-use-instanceof\/\">next post<\/a> I wrote how we should IMHO not use <em>pattern matching with instanceof<\/em>.<\/p>\n"},{"title":"Little Java riddle","link":"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/riddle\/","pubDate":"Mon, 04 May 2020 13:50:47 +0200","guid":"https:\/\/softwaregarden.dev\/en\/posts\/new-java\/riddle\/","description":"<p>Below you can find a piece of code written in Java. I&rsquo;d like to ask you one thing: please don&rsquo;t run this code before you try to answer.<\/p>\n<p>Copying this code into jshell takes just a few seconds, but then the knowledge may last for a few seconds as well&hellip;<\/p>\n<p>I suggest a little <a href=\"https:\/\/en.wikipedia.org\/wiki\/Thought_experiment\">thought experiment<\/a>, reading Javadoc, running this mentally in your mind&hellip;<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-java\" data-lang=\"java\"><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">19<\/span><span><span style=\"color:#f92672\">import<\/span> java.util.*;\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">20<\/span><span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">21<\/span><span><span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#66d9ef\">class<\/span> <span style=\"color:#a6e22e\">Riddle<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">22<\/span><span>\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">23<\/span><span>\t<span style=\"color:#66d9ef\">public<\/span> <span style=\"color:#66d9ef\">static<\/span> <span style=\"color:#66d9ef\">void<\/span> <span style=\"color:#a6e22e\">main<\/span>(String<span style=\"color:#f92672\">[]<\/span> args) {\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">24<\/span><span>\t\t<span style=\"color:#66d9ef\">var<\/span> raz <span style=\"color:#f92672\">=<\/span> List.<span style=\"color:#a6e22e\">of<\/span>(<span style=\"color:#e6db74\">&#34;checking!&#34;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">25<\/span><span>\t\t<span style=\"color:#66d9ef\">var<\/span> dwa <span style=\"color:#f92672\">=<\/span> List.<span style=\"color:#a6e22e\">copyOf<\/span>(raz);\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">26<\/span><span>\t\t<span style=\"color:#66d9ef\">if<\/span> (raz <span style=\"color:#f92672\">==<\/span> dwa) {\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">27<\/span><span>\t\t\tSystem.<span style=\"color:#a6e22e\">out<\/span>.<span style=\"color:#a6e22e\">println<\/span>(<span style=\"color:#e6db74\">&#34;ene&#34;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">28<\/span><span>\t\t} <span style=\"color:#66d9ef\">else<\/span> <span style=\"color:#66d9ef\">if<\/span> (raz.<span style=\"color:#a6e22e\">equals<\/span>(dwa)) {\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">29<\/span><span>\t\t\tSystem.<span style=\"color:#a6e22e\">out<\/span>.<span style=\"color:#a6e22e\">println<\/span>(<span style=\"color:#e6db74\">&#34;due&#34;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">30<\/span><span>\t\t} <span style=\"color:#66d9ef\">else<\/span> {\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">31<\/span><span>\t\t\tSystem.<span style=\"color:#a6e22e\">out<\/span>.<span style=\"color:#a6e22e\">println<\/span>(<span style=\"color:#e6db74\">&#34;like&#34;<\/span>);\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">32<\/span><span>\t\t}\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">33<\/span><span>\t\tSystem.<span style=\"color:#a6e22e\">out<\/span>.<span style=\"color:#a6e22e\">println<\/span>(raz.<span style=\"color:#a6e22e\">getClass<\/span>().<span style=\"color:#a6e22e\">getCanonicalName<\/span>());\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">34<\/span><span>\t}\n<\/span><\/span><span style=\"display:flex;\"><span style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">35<\/span><span>}<\/span><\/span><\/code><\/pre><\/div>\n<p>Okay, now try to answer these two questions:<\/p>\n<ol>\n<li>What&rsquo;s the <strong>minimal<\/strong> Java version needed to run this code?<\/li>\n<li>What will be the first line printed by this code? <code>ene<\/code>, <code>due<\/code> or maybe <code>like<\/code>?<\/li>\n<li>* What&rsquo;s the class of the <code>raz<\/code> object?<\/li>\n<\/ol>\n<p>Expect the answer (and my comment on it) soon.<\/p>\n<p>The code can be also found on <a href=\"https:\/\/github.com\/pioorg\/efNewJavTiny\/blob\/master\/src\/main\/java\/org\/przybyl\/efNewJavTiny\/Riddle.java\">Github<\/a>.<\/p>\n<p>PS. <em>&lsquo;Ene, due, like, fake&hellip;&rsquo;<\/em> is a counting-out rhyme in Polish, quite popular I guess. You may think <em>&lsquo;Eeny, meeny, miny, moe&hellip;&rsquo;<\/em> <a href=\"https:\/\/pl.wikipedia.org\/wiki\/Wyliczanka_(literatura)\">Wikipedia<\/a>.<\/p>"},{"title":"Privacy","link":"https:\/\/softwaregarden.dev\/en\/privacy\/","pubDate":"Fri, 01 May 2020 11:04:08 +0200","guid":"https:\/\/softwaregarden.dev\/en\/privacy\/","description":"<p>This website uses GoatCounter, a privacy-friendly analytics service. No tracking cookies are used and no personal profiles are created. Anonymous, aggregated statistics are collected solely to understand website usage and improve content.<\/p>\n"},{"title":"Java Records for the Intrigued","link":"https:\/\/softwaregarden.dev\/en\/talks\/java-records-for-intrigued\/","pubDate":"Fri, 10 Apr 2020 15:47:00 +0200","guid":"https:\/\/softwaregarden.dev\/en\/talks\/java-records-for-intrigued\/","description":"<p>Java 14 brought Records as one of the preview features. For many it was reasonable to say &ldquo;no more JavaBeans code generation&rdquo; or &ldquo;Lombok is dead&rdquo;. Is that really the case? What one can do with records and what can&rsquo;t? What about reflection and serialization?<\/p>\n<p><div style=\"position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;\">\n      <iframe allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen\" loading=\"eager\" referrerpolicy=\"strict-origin-when-cross-origin\" src=\"https:\/\/www.youtube-nocookie.com\/embed\/m-1XpTAH7pk?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0\" style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;\" title=\"YouTube video\"><\/iframe>\n    <\/div>\n\n\\<\/p>\n<div style=\"position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;\">\n      <iframe allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen\" loading=\"eager\" referrerpolicy=\"strict-origin-when-cross-origin\" src=\"https:\/\/www.youtube-nocookie.com\/embed\/vVofZuV_oFg?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0\" style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;\" title=\"YouTube video\"><\/iframe>\n    <\/div>\n\n<p>This talk has been presented at e.g. AllTheTalks.online, CodeCamp Romania, JPoint.<\/p>\n"},{"title":"Java 14. What's new and noteworthy?","link":"https:\/\/softwaregarden.dev\/en\/talks\/java-14-new-and-noteworthy\/","pubDate":"Fri, 10 Apr 2020 15:45:00 +0200","guid":"https:\/\/softwaregarden.dev\/en\/talks\/java-14-new-and-noteworthy\/","description":"<p>Hey, there are two major Java versions released every year! We don&rsquo;t have to wait 3 years or so for new features any more. Isn&rsquo;t that cool? ;-)<\/p>\n<p>So&hellip; would you like to check out what has happened in Java 14?<br>\nSwitch expressions available to public?<br>\nNo more NPEs?<br>\nRecord types?<br>\nPattern matching?<br>\nText blocks?<br>\nIf you find them interesting, let&rsquo;s dive deep together into new interesting stuff.<\/p>\n<div style=\"position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;\">\n      <iframe allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen\" loading=\"eager\" referrerpolicy=\"strict-origin-when-cross-origin\" src=\"https:\/\/www.youtube-nocookie.com\/embed\/5w2cOJ-56Uk?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0\" style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;\" title=\"YouTube video\"><\/iframe>\n    <\/div>\n\n<p>This talk has been presented at Wroc\u0142aw JUG and Warszawa JUG.<\/p>\n<p>It is a different format that a &ldquo;regular&rdquo; conference talk, because it is a &ldquo;Deep dive&rdquo;, lasting 2h - 3h.<\/p>\n"},{"title":"Java 12 & 13. What's new and noteworthy?","link":"https:\/\/softwaregarden.dev\/en\/talks\/java-12-13-new-and-noteworthy\/","pubDate":"Fri, 10 Apr 2020 15:43:00 +0200","guid":"https:\/\/softwaregarden.dev\/en\/talks\/java-12-13-new-and-noteworthy\/","description":"<p>Hey, there are two major Java versions released every year! We don&rsquo;t have to wait 3 years or so for new features any more. Isn&rsquo;t that cool? ;-)<\/p>\n<p>So&hellip; you&rsquo;d like to check what has happened since Java 11?<br>\nSwitch expressions?<br>\nText blocks?<br>\nNew functions in String, Streams and other APIs?<br>\nWhat are the Shenandoah and ZGC about?<br>\nAppCDS to speed up spin-off?<br>\nIf you find them interesting, let&rsquo;s dive deep together into new interesting stuff.<\/p>\n<div style=\"position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;\">\n      <iframe allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen\" loading=\"eager\" referrerpolicy=\"strict-origin-when-cross-origin\" src=\"https:\/\/www.youtube-nocookie.com\/embed\/UhtgxxDa-BQ?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0\" style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;\" title=\"YouTube video\"><\/iframe>\n    <\/div>\n\n<p>This talk has been presented at Devoxx Belgium, Devoxx Ukraine, and Wroc\u0142aw JUG.<\/p>\n<p>It is a different format that a &ldquo;regular&rdquo; conference talk, because it is a &ldquo;Deep dive&rdquo;, lasting 2h - 3h.<\/p>\n"},{"title":"Java. Migrating to 11 in real app","link":"https:\/\/softwaregarden.dev\/en\/talks\/migrating-java11\/","pubDate":"Fri, 10 Apr 2020 15:39:00 +0200","guid":"https:\/\/softwaregarden.dev\/en\/talks\/migrating-java11\/","description":"<p>It&rsquo;s (post) Java 11 time now. (Just in case your boss didn&rsquo;t notice ;-))<br>\nIn this talk, I&rsquo;d like to tell you how I managed to migrate two real Java server apps to Java 11 and show some demos.<br>\nWhy was it done?<br>\nHow to convince the business?<br>\nWhat and how was done?<br>\nWhat wasn&rsquo;t required?<br>\nDoes anyone read licenses, manuals, and talks&rsquo; descriptions?<br>\nWhere did I fail in the first approach?<br>\nWas it worth it?<br>\nSome hints for you.<\/p>\n<div style=\"position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;\">\n      <iframe allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen\" loading=\"eager\" referrerpolicy=\"strict-origin-when-cross-origin\" src=\"https:\/\/www.youtube-nocookie.com\/embed\/hAbvZs6bJP8?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0\" style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;\" title=\"YouTube video\"><\/iframe>\n    <\/div>\n\n<p>This talk (in various formats) has been presented at  Devoxx Poland, Devoxx Ukraine, Devoxx Belgium, CodeMotion Milan, Java Developer Days, CoffeeJUG Lviv, 4Developers, Wroc\u0142aw JUG and others.<\/p>\n<p>This talk was:<\/p>\n<ul>\n<li>voted as one of Devoxx Poland 2019 Top 10 talks<\/li>\n<li>awarded 3rd best talk of Devoxx Ukraine 2019<\/li>\n<li>ranked as 2nd best Java talk of 4Developers 2019<\/li>\n<\/ul>\n"},{"title":"Four Diseases","link":"https:\/\/softwaregarden.dev\/en\/talks\/four-diseases\/","pubDate":"Fri, 10 Apr 2020 15:37:00 +0200","guid":"https:\/\/softwaregarden.dev\/en\/talks\/four-diseases\/","description":"<p>How a developer can tell if the system is sick just by taking a look at the input and the output? If you\u2019d like to know that (plus you like standup comedy), come and see! The treatment is safe ;-)<\/p>\n<p>One approach to get familiar with a system is a long and intense reading the manual (and to run an eye over the source code sometimes). Another approach is to take a deep dive into the data model (often in the DB) and to surf the user interface. Both are natural ends of the system, the legendary Input and Output. By examining these ends one can check if there\u2019s good digestion or if guts are rotten. Careful examination can confirm &ldquo;common DDDosis&rdquo;, &ldquo;malignant stringosis&rdquo;, &ldquo;regex diarrhoea&rdquo; or &ldquo;not-made-here syndrome&rdquo;. Unfortunately, sometimes developers get infected in their prenatal life (meaning: at their university). Let me invite you to treatment. A laxative one. (That is: a sequel of &ldquo;Passwords. Do you keep them safe?&rdquo;)<\/p>\n<div style=\"position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;\">\n      <iframe allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen\" loading=\"eager\" referrerpolicy=\"strict-origin-when-cross-origin\" src=\"https:\/\/www.youtube-nocookie.com\/embed\/E9EKWrRcyYk?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0\" style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;\" title=\"YouTube video\"><\/iframe>\n    <\/div>\n\n<p>This talk (in various formats) has been presented at SpreadIT, CoreDump (a.k.a. SegFault), GDG DevFest Toulouse, JavaDay Lviv, Greenfield Conf, 4Developers, Wroc\u0142aw JUG, BoilingFrogs and others.<\/p>\n<p>This talk has been selected the best Architecture talk of 4Developers 2019 and SpreadIT 2018.<\/p>\n"},{"title":"CONTEXTVS, STVLTE! (Context, stupid!)","link":"https:\/\/softwaregarden.dev\/en\/talks\/context\/","pubDate":"Fri, 10 Apr 2020 15:35:31 +0200","guid":"https:\/\/softwaregarden.dev\/en\/talks\/context\/","description":"<p>&ldquo;The best sorting algorithm is quick sort.&rdquo;<br>\n&ldquo;Indexes make DB faster.&rdquo;<br>\n&ldquo;Data should be sorted using ORDER BY.&rdquo;<br>\n&ldquo;Composition - good; inheritance - not good.&rdquo;<br>\n&ldquo;Windows is an operating system.&rdquo;<br>\n&ldquo;You must have transactions in your DB.&rdquo;<br>\n&ldquo;Java is slow.&rdquo;<br>\n&ldquo;Don&rsquo;t eat yellow snow.&rdquo;<br>\n&ldquo;You shall not self-sign your certificates.&rdquo;<br>\n&ldquo;Interrupt in Java is broken.&rdquo;<\/p>\n<p>The IT world is full of mantras\/revealed truth, passed (often in oral tradition) among developer tribes. Mindlessly repeated from generation to generation, they cause a reckless usage. At best this results in more harm than good, in the worst case: a total disaster worth whole train of money.\nThe context is indispensable part of each mantra. Right context can help to distinguish proper usage from incoming disaster.<\/p>\n<p>Do you believe in a mantra by any chance?<br>\nHow to find out the context?<br>\nCan one eat a yellow snow?<br>\nCome and see.<\/p>\n<div style=\"position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;\">\n      <iframe allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen\" loading=\"eager\" referrerpolicy=\"strict-origin-when-cross-origin\" src=\"https:\/\/www.youtube-nocookie.com\/embed\/nVaajs55ZR8?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0\" style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;\" title=\"YouTube video\"><\/iframe>\n    <\/div>\n\n<p>This talk (in various formats) has been presented at Devoxx Poland, Devoxx Ukraine, GDG DevFest Toulouse, 4Developers, Wroc\u0142aw JUG, JAVIPS, and others.<\/p>\n"},{"title":"Graylog: one tool to log 'em all","link":"https:\/\/softwaregarden.dev\/en\/talks\/graylog\/","pubDate":"Fri, 10 Apr 2020 15:33:31 +0200","guid":"https:\/\/softwaregarden.dev\/en\/talks\/graylog\/","description":"<p>There are 10 kinds of people: the ones who already log stuff and the ones who will. ;-)\nBut what can be fascinating about logging? It&rsquo;s just adding some statements of given level to a file in \/var\/log, so what&rsquo;s this presentation for in the fist place?\nWell, ordinary adding lines to \/var\/log and tracing them with tail -f or searching with grep is so&hellip; 1980 and inefficient.\nMeet Graylog: a centralised and distributed log management system. A tool, which will let you gather, process, analyse logs from many sources: syslog, your application, Apache\/Nginx, database, firewall, etc. It can alert, search all ways through, analyse the logs no matter what language\/technology sent them. And it makes that good. And is Open Source.\nThis presentation is about some gotchas based on real-life experience, quick Graylog setup, wiring your apps\/systems\/servers, analysing logs after. Even if the machine which sent them is already gone.<\/p>\n<div style=\"position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;\">\n      <iframe allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen\" loading=\"eager\" referrerpolicy=\"strict-origin-when-cross-origin\" src=\"https:\/\/www.youtube-nocookie.com\/embed\/-o3D-wH4hDI?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0\" style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;\" title=\"YouTube video\"><\/iframe>\n    <\/div>\n\n<p>This talk (in various formats) has been presented at Geecon Poland, Java Developer Days, 4Developers, Wroc\u0142aw JUG and others.<\/p>\n"},{"title":"Passwords, do you keep them safe?","link":"https:\/\/softwaregarden.dev\/en\/talks\/passwords\/","pubDate":"Fri, 10 Apr 2020 15:23:56 +0200","guid":"https:\/\/softwaregarden.dev\/en\/talks\/passwords\/","description":"<p>Some say that keeping passwords in a [web] application is a boring and trivial task: some hashing, maybe some salt, et voil\u00e0! However, storing passwords and other sensitive data might not be as simple as it seems. You&rsquo;ll see a bunch of examples of what to do and what not to do based on a freelance&rsquo;s experience. Watch and see if you&rsquo;re not sitting on a bomb.<\/p>\n<div style=\"position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;\">\n      <iframe allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen\" loading=\"eager\" referrerpolicy=\"strict-origin-when-cross-origin\" src=\"https:\/\/www.youtube-nocookie.com\/embed\/SE2COIwGMIE?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0\" style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;\" title=\"YouTube video\"><\/iframe>\n    <\/div>\n\n<p>This talk (in various formats) has been presented at Chamberconf, 4Developers, Devoxx Poland, Wroc\u0142aw JUG, Coffee JUG Lviv, jLabs Academy and others.<\/p>\n"},{"title":"About me","link":"https:\/\/softwaregarden.dev\/en\/about-me\/","pubDate":"Fri, 10 Apr 2020 11:33:26 +0200","guid":"https:\/\/softwaregarden.dev\/en\/about-me\/","description":"<figure class=\"image image right\">\n<img src=\"me2.jpg\" alt=\"This is how Piotr looks like\" width=\"300\">\n<\/figure>\n\n<p>My name is Piotr, and I&rsquo;m Remote Software Gardener (except for Friday afternoons, when I&rsquo;m also the Admiral of the Northern Seas).<\/p>\n<h2 id=\"bio\">Bio<\/h2>\n<p>Notorious engineer at work and after hours, tracing meanders of the art of software engineering. Remote Software Gardener, mostly working in web-oriented Java gardens. Java Champion. Testcontainers Champion. Programming usually in Java (since 1.3), Scala and Go, but in other languages too. Fan of agility, seen mostly as choosing the right tools and approaches after asking the right questions. Developer, trainer and conference speaker. In his talks, Piotr covers not only hardcore Java but also software architecture, computer security, and soft-skills.<\/p>\n<h3 id=\"would-you-like-to-text-me\">Would you like to text me?<\/h3>\n<p>The easiest way might be to use the Mastodon: <a href=\"https:\/\/mstdn.social\/@piotrprz\">@piotrprz@mstdn.social<\/a>, Twitter: <a href=\"https:\/\/twitter.com\/piotrprz\">@piotrprz<\/a>, Bluesky: <a href=\"https:\/\/bsky.app\/profile\/piotrprz.bsky.social\">@piotrprz<\/a> or Telegram @piotrprz.<\/p>\n<p>If you&rsquo;d like to e-mail me, that should also work. In the &ldquo;recipient&rdquo; field type my first name, then of course @, then follow with this page name.<\/p>\n<h3 id=\"what-was-your-name-again\">What was your name again?<\/h3>\n<p>My name is quite a common name in Polish, there&rsquo;s nothing special about it. Apparently, it <em>has<\/em> some vowels in my mother tongue, because in Polish <code>Y<\/code> is a vowel. (However, I still like my German nickname, Piotr-ohne-Vokale ^^)<\/p>\n<p>To make it a bit easier, I&rsquo;ve recorded how my name sounds in Polish.<\/p>\n<figure >\n<audio controls preload=\"metadata\">\n<source src=\"https:\/\/softwaregarden.dev\/en\/about-me\/piotr.mp3\" type=\"audio\/mpeg\">\n\n<\/audio>\n<\/figure>\n\n<p>Still, you shall not worry how to pronounce my name. Not everyone can possess all super-powers, and you don&rsquo;t have to speak Polish. It&rsquo;s perfectly okay if you approach me with Piotr, Peter, Piter, Pyotr, Pierre, Pedro, Petro, Pietro, Petrus, \u041f\u0435\u0442\u0440\u043e, \u03a0\u03ad\u03c4\u03c1\u03bf\u03c2, and so on.<\/p>\n<p>What I believe matters, is if you approach people with good intentions, not if you&rsquo;re able to say their name super accurately ;-)<\/p>\n"}]}}