<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Victor Warno</title>
    <description>The latest articles on Forem by Victor Warno (@schmowser).</description>
    <link>https://forem.com/schmowser</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F86975%2F2f2399b5-09cc-4a1a-ba84-0492ea162d84.png</url>
      <title>Forem: Victor Warno</title>
      <link>https://forem.com/schmowser</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/schmowser"/>
    <language>en</language>
    <item>
      <title>How I revamped my homepage using scroll animations with GSAP</title>
      <dc:creator>Victor Warno</dc:creator>
      <pubDate>Mon, 15 Mar 2021 22:17:47 +0000</pubDate>
      <link>https://forem.com/schmowser/how-i-revamped-my-homepage-using-scroll-animations-with-gsap-4i2e</link>
      <guid>https://forem.com/schmowser/how-i-revamped-my-homepage-using-scroll-animations-with-gsap-4i2e</guid>
      <description>&lt;p&gt;Have you ever looked at a website or any content on the web and think: "I would love to be able to do something like that!" I usually have that feeling when I see anything animated like the newest Disney motion picture or interactive formats like &lt;a href="https://pudding.cool/2017/05/song-repetition/" rel="noopener noreferrer"&gt;visual essays from Pudding&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;When I stumbled upon the &lt;a href="https://greensock.com/gsap/" rel="noopener noreferrer"&gt;GSAP&lt;/a&gt; library, I took the chance to rebuild my &lt;a href="https://www.schmowser.de/" rel="noopener noreferrer"&gt;homepage&lt;/a&gt; from scratch in order to whip some smooth UX on it like the examples above. The goal is to have all information on one page to be provided bit by bit through scrolling.&lt;/p&gt;




&lt;h1&gt;
  
  
  Setup
&lt;/h1&gt;

&lt;p&gt;GSAP can animate everything JavaScript can touch. They say it interacts well with the common Frontend frameworks. So, I setup a &lt;a href="https://v3.vuejs.org/guide/installation.html#vite" rel="noopener noreferrer"&gt;Vue 3 project with Vite&lt;/a&gt; and got started. GSAP can be installed via npm: &lt;code&gt;npm install gsap&lt;/code&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  Simple example: Loading bar
&lt;/h1&gt;

&lt;p&gt;I want to showcase GSAP's ScrollTrigger features by implementing a loading bar that enters the screen when scrolling down. The output should look similar to this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fs4.gifyu.com%2Fimages%2Fbacktotoploadingbar.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fs4.gifyu.com%2Fimages%2Fbacktotoploadingbar.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;First, we need an element to move. So, we define an CSS element &lt;code&gt;loading-bar&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.loading-bar&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100vw&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;white&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;darkslategrey&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;larger&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Moving the bar 100 pixels to the right for example is fairly simple. Import the gsap dependency and use the &lt;code&gt;.to&lt;/code&gt; function to determine where the element should end up on the screen. GSAP takes care of the corresponding property manipulation for you!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;gsap&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gsap&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;gsap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.loading-bar&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;scrollTrigger&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.loading-bar&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first argument tells GSAP which element should be manipulated. The property &lt;code&gt;scrollTrigger&lt;/code&gt; makes clear when the animation should start. In this case, you want it to move to the right when &lt;code&gt;.loading-bar&lt;/code&gt; enters the screen. &lt;/p&gt;




&lt;h1&gt;
  
  
  Timelines for versatility
&lt;/h1&gt;

&lt;p&gt;We learned the first steps to create our animation. But when to run that code? A solution would be once the instance of the component has been mounted. So, we put it in the corresponding &lt;a href="https://vuejs.org/v2/api/#mounted" rel="noopener noreferrer"&gt;lifecycle hook&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;mounted&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;gsap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;timeline&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nx"&gt;tl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.loading-bar&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;xPercent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that we used a &lt;a href="https://greensock.com/docs/v3/GSAP/Timeline" rel="noopener noreferrer"&gt;Timeline&lt;/a&gt; here because it makes organizing animation steps easier when handling more CSS elements. Imagine writing multiple &lt;code&gt;gsap.to()&lt;/code&gt;s which would make your code hard to read.&lt;/p&gt;

&lt;p&gt;Also, we switched from &lt;code&gt;gsap.to()&lt;/code&gt; to Timeline's &lt;code&gt;.from&lt;/code&gt; function. It is just the other way around this time. Now, our bar will come &lt;em&gt;from&lt;/em&gt; off-screen (left) and slide into the original position.&lt;/p&gt;




&lt;h1&gt;
  
  
  ScrollTrigger
&lt;/h1&gt;

&lt;p&gt;We are missing the trigger for our animation which we will deliver through the ScrollTrigger Plugin. You need to import and register it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ScrollTrigger&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gsap/ScrollTrigger&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;mounted&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="nx"&gt;gsap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;registerPlugin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ScrollTrigger&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;gsap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;timeline&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nx"&gt;tl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.loading-bar&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;xPercent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="nx"&gt;ScrollTrigger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;animation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;tl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;trigger&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.background-panel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;start&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;top top&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;end&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;+=1000&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;pin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;scrub&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You see that the trigger element is a &lt;code&gt;.background-panel&lt;/code&gt; element that I defined to function as a canvas for the animated loading bar. Let's go through the other properties.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;start&lt;/code&gt;: You pass two keywords here. Here, for example, the animation starts when the top of the viewport reaches the top of the background panel. This ensures that the background panel is in full view before the animation starts.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;end&lt;/code&gt;: This determines when the animation ends. This increment means that you need to scroll 1000 pixels to see the full animation evolving. This gives the user the feeling that s/he in scrolling "in place".&lt;/p&gt;

&lt;p&gt;&lt;code&gt;pin&lt;/code&gt;: If set to true, the trigger element (here: the background) is pinned throughout the animation.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;scrub&lt;/code&gt;: If set to true, you can scroll up and the animation is reversed!&lt;/p&gt;

&lt;p&gt;The different effects will become clearer once you see the result on my &lt;a href="https://www.schmowser.de/" rel="noopener noreferrer"&gt;homepage&lt;/a&gt;. Caution: It is not mobile-optimized yet!&lt;/p&gt;




&lt;h1&gt;
  
  
  Verdict
&lt;/h1&gt;

&lt;p&gt;I was astonished by the speed and versatility of animating with GSAP. I even added a Parallax effect to my website among other things.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fs4.gifyu.com%2Fimages%2Fschmowserdeanimation.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fs4.gifyu.com%2Fimages%2Fschmowserdeanimation.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Feel free to tell me what you think of the animations on my &lt;a href="https://www.schmowser.de/" rel="noopener noreferrer"&gt;website&lt;/a&gt;. And go check out GSAP yourself! There is plenty of &lt;a href="https://greensock.com/docs/v3/Plugins/ScrollTrigger" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; and &lt;a href="https://greensock.com/showcase/" rel="noopener noreferrer"&gt;showcases&lt;/a&gt; on their website. It is definitely one of the smoothest frameworks I picked up this year!&lt;/p&gt;




&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@gensahub_style?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Gensa Hub&lt;/a&gt; on &lt;a href="/s/photos/animation?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>vue</category>
      <category>webdev</category>
      <category>showdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Gaining digital independence by breaking away from the Four Horsemen</title>
      <dc:creator>Victor Warno</dc:creator>
      <pubDate>Sun, 03 Jan 2021 16:31:37 +0000</pubDate>
      <link>https://forem.com/schmowser/gaining-digital-independence-by-breaking-away-from-the-four-horsemen-1g11</link>
      <guid>https://forem.com/schmowser/gaining-digital-independence-by-breaking-away-from-the-four-horsemen-1g11</guid>
      <description>&lt;p&gt;The beginning of a new year is always a good chance to tidy your digital self. That is what I started doing a few months ago by breaking away from Tech Giants like Google, Facebook, Amazon and Apple (also known as the Four Horsemen). I am convinced that the current state of the internet is not what the early creators of the web had in mind. So, I tried a few alternatives. It started with privacy in mind but it quickly turned into a panorama of equally good software that lives out there. &lt;/p&gt;

&lt;h1&gt;
  
  
  Browser
&lt;/h1&gt;

&lt;p&gt;This is maybe the easiest but most effective change you can do to make your web experience safer. Instead of Google Chrome, you could use &lt;a href="https://www.mozilla.org/en-US/firefox/new/"&gt;Mozilla Firefox&lt;/a&gt; and &lt;a href="https://www.privacytools.io/browsers/#about_config"&gt;harden it&lt;/a&gt;. The configuration changes prevents &lt;a href="https://www.mozilla.org/en-US/firefox/features/block-fingerprinting/"&gt;Fingerprinting&lt;/a&gt; or Crypto-Mining.&lt;/p&gt;

&lt;p&gt;I also added PrivacyBadger and uBlock as Firefox Addons to keep Tracking to a minimum. &lt;/p&gt;

&lt;h1&gt;
  
  
  Search Engine
&lt;/h1&gt;

&lt;p&gt;The most successful service of the web! I admit that Google did a good job with optimizing their search engine. And for work related questions I still use Google. But I try not to use it for private matters to avoid recommendations and ads.&lt;/p&gt;

&lt;p&gt;There are search engines that are build around privacy like &lt;a href="https://www.qwant.com/"&gt;Quant&lt;/a&gt; and &lt;a href="https://duckduckgo.com/"&gt;DuckDuckGo&lt;/a&gt;. A special place in my heart is reserved for &lt;a href="https://www.ecosia.org/"&gt;Ecosia&lt;/a&gt; based in Berlin which declared the mission to plant a tree with every search. DuckDuckGo also develops a browser but keep in mind that it is a US company where different rules for data protection apply.&lt;/p&gt;

&lt;h1&gt;
  
  
  Email
&lt;/h1&gt;

&lt;p&gt;Changing email addresses seems like changing your physical address. And some websites make it hard to migrate to a new one. Google does a good job at integrating its services with your Gmail account, so it is probably even harder.&lt;/p&gt;

&lt;p&gt;The alternatives I mention here usually cost a small amount per month. The more known email provider that offer encrypted mails are Protonmail and Tutanota. I went with a Berlin-based provider called &lt;a href="https://posteo.de/en"&gt;Posteo&lt;/a&gt;. The service costs 1€ per month but is worth so much more. You even get to choose three aliases. Posteo also offers regex in email filters, if you like implementing that yourself.&lt;/p&gt;

&lt;p&gt;If you do not want to do an overhaul of your emails right away, try out any of the service above for a month and see if it suits your needs.&lt;/p&gt;

&lt;h1&gt;
  
  
  Cloud
&lt;/h1&gt;

&lt;p&gt;Talking about Google services, you probably do not want to miss out on the Cloud services like Google Docs and Google Photos. At least for the latter, you should consider switching your Cloud provider as &lt;a href="https://www.theverge.com/2020/11/11/21560810/google-photos-unlimited-cap-free-uploads-15gb-ending"&gt;Google introduces a storage limit this summer (2020)&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;One possibility is always self-hosting which you can easily do with &lt;a href="https://nextcloud.com/"&gt;Nextcloud&lt;/a&gt;. I plan to setup a Raspberry Pi and host Nextcloud myself. But if that is too much effort, you can always choose a provider to do it for you.&lt;/p&gt;

&lt;p&gt;If you set up a Pi for Cloud services and have a spare laptop, feel free to check out my &lt;a href="https://dev.to/schmowser/recycle-your-old-laptop-to-upgrade-your-raspberry-pi-setup-54c5"&gt;guide on using it as a monitor&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Office tools
&lt;/h1&gt;

&lt;p&gt;Having opted out of Google's Cloud services, we also lose the ability to use the convenient Google Docs or Sheets apps. But we can transition to &lt;a href="https://cryptpad.fr/"&gt;CryptPad&lt;/a&gt; for example. CryptPad even offers a code editor! &lt;/p&gt;

&lt;p&gt;As I do not use Office tools that often, I only needed a solid note taking app that synchronizes over all my devices. Then, I stumbled upon &lt;a href="https://standardnotes.org/"&gt;Standard Notes&lt;/a&gt; which provides exactly that with the correct sense privacy.&lt;/p&gt;

&lt;h1&gt;
  
  
  Mobile OS
&lt;/h1&gt;

&lt;p&gt;If you have a smartphone, chances are good that it is either an iPhone or and Android Phone. That means either Apple or Google has the sovereignty over your data. I played around with Ubuntu Touch but the missing user base shows in the lack of apps. &lt;/p&gt;

&lt;p&gt;While refurbishing old devices, I flashed &lt;a href="https://lineage.microg.org/"&gt;LineageOS with microG&lt;/a&gt; onto an old phone (OnePlus) and it worked right away. &lt;a href="https://lineageos.org/"&gt;LineageOS&lt;/a&gt; is based on Android 10 and is built for longevity and security. Putting &lt;a href="https://microg.org/"&gt;microG&lt;/a&gt; on top ensures that all apps from the Google Play Store work (as microG reimplements the strict underlying Google Play services). &lt;/p&gt;

&lt;p&gt;While it is recommended to get apps from the open-source oriented F-Droid store, you can actually get missing apps from the Play Store alternative &lt;a href="https://f-droid.org/en/packages/com.aurora.store/"&gt;Aurora Store&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Map
&lt;/h1&gt;

&lt;p&gt;Google Maps has become an essential part of a lot of Smartphones. So far that we often wonder how we found our way around before internet was invented. But there is also the OpenStreetMap project that is community-driven like Wikipedia for example is. An implementation for phones would be &lt;a href="https://osmand.net/"&gt;OsmAnd&lt;/a&gt;. It celebrated its 10th anniversary last year and offers features like Wikipedia integration and voice guidance.&lt;/p&gt;

&lt;h1&gt;
  
  
  YouTube
&lt;/h1&gt;

&lt;p&gt;Finding an alternative to YouTube was maybe the hardest challenge. Almost everything concerning video and music is uploaded to Google's platform.&lt;/p&gt;

&lt;p&gt;Recently, I enjoy live content on Twitch more regularly. But this lands you in the realm of another Tech Giant. So, what is the resort?&lt;/p&gt;

&lt;p&gt;I decided to fall back to a Frontend to YouTube that limits sending data to Google. If you want to try it out, go to an Invidious instance like &lt;a href="https://yewtu.be/"&gt;this one&lt;/a&gt;. Be cautious as I experienced slow loading times. I can recommend using the &lt;a href="https://freetubeapp.io/"&gt;FreeTube&lt;/a&gt; application. It actually provides known features like saving videos and creating playlists.&lt;/p&gt;

&lt;p&gt;The F-Droid App &lt;a href="https://newpipe.net/"&gt;NewPipe&lt;/a&gt; is also worth mentioning.&lt;/p&gt;

&lt;h1&gt;
  
  
  Instant Messaging
&lt;/h1&gt;

&lt;p&gt;So far, so good. Until now, everything could be done by yourself. But what happens if you what to leave Facebook as the main communication channel with everything Messenger, Instagram and WhatsApp? It is definitely harder to convince others to make a change.&lt;/p&gt;

&lt;p&gt;But I gave it a shot. &lt;a href="https://www.signal.org/"&gt;Signal&lt;/a&gt; is a more than satisfying messaging app which gained popularity in the recent Black Lives Matters movement. I even went a step further by hosting a Matrix server on &lt;a href="https://element.io/"&gt;Element&lt;/a&gt;. Therefore, I have the control who can join the server and how encryption will be enforced.&lt;/p&gt;

&lt;h1&gt;
  
  
  Operating System
&lt;/h1&gt;

&lt;p&gt;Coming to the next Tech Giant to face: Microsoft. Windows 10 is known for collection data by default. You could change that or you could try out a Linux Operating System like &lt;a href="https://ubuntu.com/download/desktop"&gt;Ubuntu&lt;/a&gt; - which is recommended to developers anyways! But there are all kinds of Linux flavors from &lt;a href="https://archlinux.org/"&gt;Arch Linux&lt;/a&gt; for hardcore users to &lt;a href="https://pop.system76.com/"&gt;Pop!_OS&lt;/a&gt; which is based on Ubuntu but offers a more Windows-like UI.&lt;/p&gt;

&lt;p&gt;If you do not want to do the breakup right away, you can setup a dual boot. Because I was actually scared switching completely as I do not want to miss my gaming nights. But the Linux community is very vibrant one. That's why they developed &lt;a href="https://lutris.net/downloads/"&gt;Lutris&lt;/a&gt;. And it works! I can now lose SR in Overwatch on a Linux system as well 😂&lt;/p&gt;

&lt;h1&gt;
  
  
  What else?
&lt;/h1&gt;

&lt;p&gt;And I concede that my life will not be completely Google-free: I still have a Google Chromecast device because it is currently the only way how I can stream the content of an Oculus Quest to my TV. (In exchange, this is the only use case I use the Chromecast for.)&lt;/p&gt;

&lt;p&gt;This list is for from complete. To achieve a complete surveillance-free digital life, you would also have to set up a VPN etc. For more information, I recommend checking out &lt;a href="https://www.privacytools.io/"&gt;PrivacyTools&lt;/a&gt; and their subreddit. &lt;/p&gt;

&lt;p&gt;In the end, it is always a trade-off between privacy and convenience. But I think every step to a self-determined digital identity will do good for the future of a free and fair internet.&lt;/p&gt;

</description>
      <category>privacy</category>
      <category>discuss</category>
      <category>opensource</category>
      <category>ubuntu</category>
    </item>
    <item>
      <title>Less boilerplate: Crnk with Kotlin and Spring Boot</title>
      <dc:creator>Victor Warno</dc:creator>
      <pubDate>Sun, 21 Jun 2020 15:42:10 +0000</pubDate>
      <link>https://forem.com/schmowser/less-boilerplate-crnk-with-kotlin-and-spring-boot-2ml4</link>
      <guid>https://forem.com/schmowser/less-boilerplate-crnk-with-kotlin-and-spring-boot-2ml4</guid>
      <description>&lt;p&gt;I grew tired of writing the same code over and over again. &lt;/p&gt;

&lt;p&gt;When writing RESTful APIs, you tend to add GET and POST endpoints to your project and as it grows, so do the lines of repetitive code. Not only do your controllers explode - using plain Java leads to writing Getters and Setters in your object classes.&lt;/p&gt;

&lt;p&gt;For the latter, best practice is to use &lt;a href="https://projectlombok.org/" rel="noopener noreferrer"&gt;Lombok&lt;/a&gt;, a library that offers you a variety of Annotations to get rid of the boilerplate code for getting and setting properties. But what about those Controllers? &lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing Crnk
&lt;/h2&gt;

&lt;p&gt;Somebody told me about &lt;a href="https://github.com/crnk-project/crnk-framework" rel="noopener noreferrer"&gt;crnk.io&lt;/a&gt;. Crnk is a library where you only have to define your resources and relations between them, implement the repositories - everything else is taken care of by Crnk: the Controllers, validation, error handling, HATEOAS. It even follows the &lt;a href="https://jsonapi.org/" rel="noopener noreferrer"&gt;JSON:API specification&lt;/a&gt; for building APIs. So, the format of your responses is consistent throughout the whole application! Bonus points: You even get a nice UI to access your resources.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FSchmowser%2Fcrnk-kotlin%2Fmaster%2Fcrnk-ui.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FSchmowser%2Fcrnk-kotlin%2Fmaster%2Fcrnk-ui.png" alt="alt text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I was mesmerized but, personally, I missed a working example with Kotlin. So, I created one myself. If you want to start right away or need such a template, feel free to fork &lt;a href="https://github.com/Schmowser/crnk-kotlin" rel="noopener noreferrer"&gt;my repository on Github&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up Crnk with Kotlin and Spring Boot from scratch
&lt;/h2&gt;

&lt;p&gt;This is what you have to do if you want to set up Crnk with a Spring Boot project from scratch. With &lt;a href="https://start.spring.io/" rel="noopener noreferrer"&gt;Spring Initializr&lt;/a&gt; create a Spring Boot Kotlin project and execute the following steps: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Replace mavenCentral with jcenter in the gradle build file
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;repositories {
    jcenter()
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Import crnk maven bom
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;configure&amp;lt;io.spring.gradle.dependencymanagement.dsl.DependencyManagementExtension&amp;gt; {
    imports {
        mavenBom("io.crnk:crnk-bom:3.2.20200419165537")
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The versions can be found &lt;a href="https://bintray.com/crnk-project/maven/crnk-bom" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Import crnk dependencies
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dependencies {
    implementation("io.crnk:crnk-home")
    implementation("io.crnk:crnk-setup-spring-boot2")
    implementation("io.crnk:crnk-ui")
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Write the code!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Looking at the result, you will notice that you only have to write the model (data class) and to implement the repository (extends a &lt;code&gt;ResourceRepositoryBase&lt;/code&gt;). It is important that you need to define a &lt;code&gt;NoArgsConstructor&lt;/code&gt; in the data class in order to make it work for Kotlin. But then, all is set and you can say goodbye to keeping in mind all the intricacies of setting up new controllers each time you introduce new resources.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;More details and the source code for the template for a Spring Boot Kotlin project with Crnk can be found &lt;a href="https://github.com/Schmowser/crnk-kotlin" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>kotlin</category>
      <category>rest</category>
      <category>crnk</category>
      <category>dev</category>
    </item>
    <item>
      <title>How to write Multi-Threaded Tests in Java</title>
      <dc:creator>Victor Warno</dc:creator>
      <pubDate>Sun, 29 Mar 2020 18:03:18 +0000</pubDate>
      <link>https://forem.com/schmowser/how-to-write-multi-threaded-tests-in-java-2iki</link>
      <guid>https://forem.com/schmowser/how-to-write-multi-threaded-tests-in-java-2iki</guid>
      <description>&lt;p&gt;Spending a weekend at home gives you endless possibilities. We, for example, played board games, watched online courses and even rebuild Stonehenge from clay. But we are not multi-core CPUs that can do all these things at the same time (parallelism). Our human attention span is more like a Thread that has to switch from task to task efficiently (concurrency). And clay mixing blocks my mind from pretty much any other activity!&lt;/p&gt;

&lt;p&gt;And threads are what this post is about. This post tries to give you an example how to write tests with multiple threads. You could use it to prove that your application is thread-safe. Or like in my case: Ensure that a database lock is working how it's supposed to be.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;p&gt;Imagine having a resource that can be accessed by virtually everyone but should not be accessed by two at the same time. Say: toilet paper in the super market.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Entity&lt;/span&gt;
&lt;span class="nd"&gt;@Data&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ToiletPaper&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Id&lt;/span&gt;
    &lt;span class="nd"&gt;@GeneratedValue&lt;/span&gt;
    &lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="n"&gt;available&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you see, our ToiletPaper is simply identified by an ID and carries information on whether it is available or not.&lt;/p&gt;

&lt;p&gt;It is always good to have a repository full of toilet paper! We want to keep it simple and define two functions that fetch an available pack of toilet paper. The only difference is that one will have a PESSIMISTIC WRITE lock implemented.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Repository&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;ToiletPaperRepository&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;JpaRepository&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ToiletPaper&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Long&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nc"&gt;Optional&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ToiletPaper&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;findTopByAvailableTrue&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

    &lt;span class="nd"&gt;@Lock&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;LockModeType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;PESSIMISTIC_WRITE&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nc"&gt;Optional&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ToiletPaper&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;findFirstByAvailableTrue&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This lock will prevent any other process to read, update or delete data once a thread gets hold of it. &lt;/p&gt;

&lt;p&gt;Once we grabbed a toilet paper roll, we update its availability to false. Note that this toilet paper instance will not be found by the above queries anymore.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Transactional&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;ToiletPaper&lt;/span&gt; &lt;span class="nf"&gt;grabToiletPaper&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;toiletPaperRepository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;findTopByAvailableTrue&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;map&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;updateToiletPaperToUnavailable&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;orElseThrow&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;OutOfToiletPaperException:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;ToiletPaper&lt;/span&gt; &lt;span class="nf"&gt;updateToiletPaperToUnavailable&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ToiletPaper&lt;/span&gt; &lt;span class="n"&gt;toiletPaper&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;toiletPaper&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setAvailable&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;toiletPaperRepository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;save&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;toiletPaper&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Keep in mind that there is a similar &lt;code&gt;grabToiletPaper&lt;/code&gt; method that will invoke the Lock-implemented version.&lt;/p&gt;

&lt;h2&gt;
  
  
  A multi-threaded test
&lt;/h2&gt;

&lt;p&gt;Now, let us simulate two real-life supermarket situations: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Everyone reaches out for toilet paper at the same time.&lt;/li&gt;
&lt;li&gt;If someone accesses toilet paper, it cannot be accessed by someone else.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each supermarket customer will be represented by a Thread. And the instructions s*he will execute is defined in a class called &lt;code&gt;GreedyRunner&lt;/code&gt; or &lt;code&gt;PatientRunner&lt;/code&gt; that both will implement the &lt;code&gt;Runnable&lt;/code&gt; interface like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@AllArgsConstructor&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GreedyWorker&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;Runnable&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;CountDownLatch&lt;/span&gt; &lt;span class="n"&gt;threadsReadyCounter&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;CountDownLatch&lt;/span&gt; &lt;span class="n"&gt;threadsCalledBlocker&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;CountDownLatch&lt;/span&gt; &lt;span class="n"&gt;threadsCompletedCounter&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="n"&gt;threadId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;currentThread&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getId&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;threadsReadyCounter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;countDown&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Thread-{} ready!"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;threadId&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;threadsCalledBlocker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;await&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
            &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="nc"&gt;ToiletPaper&lt;/span&gt; &lt;span class="n"&gt;toiletPaper&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;toiletPaperService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;grabToiletPaper&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
                &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Thread-{} got Toilet Paper no. {}!"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;threadId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;toiletPaper&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getId&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;OutOfToiletPaperException&lt;/span&gt; &lt;span class="n"&gt;ootpe&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"No Toilet Paper in stock!"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;InterruptedException&lt;/span&gt; &lt;span class="n"&gt;ie&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Thread-{} got interrupted!"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;threadId&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;threadsCompletedCounter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;countDown&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You see that we defined three so-called &lt;a href="https://www.baeldung.com/java-countdown-latch"&gt;CountDownLatch&lt;/a&gt; objects. You can imagine these like Countdowns. You can define a number, for example 3. Calling the &lt;code&gt;await()&lt;/code&gt; function makes the thread wait until the CountDownLatch reaches 0. So, if we were to call the &lt;code&gt;countdown()&lt;/code&gt; three times, the execution would still be suspended during the first two &lt;code&gt;countdown()&lt;/code&gt; calls but continue as soon as the third &lt;code&gt;countdown()&lt;/code&gt;. So, what such a worker does is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;countdown &lt;code&gt;threadsReadyCounter&lt;/code&gt; - signalling it is ready to go&lt;/li&gt;
&lt;li&gt;wait until &lt;code&gt;threadsCalledBlocker&lt;/code&gt; reaches 0&lt;/li&gt;
&lt;li&gt;grab toilet paper and log whether that was successful &lt;/li&gt;
&lt;li&gt;countdown &lt;code&gt;threadsCompletedCounter&lt;/code&gt; - signalling it has completed its task&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If all workers execute this logic, we can ensure that all threads will start at the same time. This can show us how the database lock will influence the result. And this is how the multi-threaded test would look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Test&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;multiThreadedGrabToiletPaper_NoLock&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;InterruptedException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;CountDownLatch&lt;/span&gt; &lt;span class="n"&gt;readyCounter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CountDownLatch&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;NUMBER_OF_THREADS&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="nc"&gt;CountDownLatch&lt;/span&gt; &lt;span class="n"&gt;callBlocker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CountDownLatch&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="nc"&gt;CountDownLatch&lt;/span&gt; &lt;span class="n"&gt;completeCounter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CountDownLatch&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;NUMBER_OF_THREADS&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;workers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Stream&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;generate&lt;/span&gt;&lt;span class="o"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;GreedyWorker&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;readyCounter&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;callBlocker&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;completeCounter&lt;/span&gt;&lt;span class="o"&gt;)))&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;limit&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;NUMBER_OF_THREADS&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;collect&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Collectors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toList&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;

    &lt;span class="n"&gt;workers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;forEach&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;Thread:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;readyCounter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;await&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Open the Toilet Paper Hunt!"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;callBlocker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;countDown&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;completeCounter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;await&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hunt ended!"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First, we initialize the CountDownLatches. We want to ensure all workers start at the same time, so we define a countdown starting at &lt;code&gt;NUMBER_OF_THREADS&lt;/code&gt;. We create the same amount of workers and start them up. As we saw earlier, each one will countdown on the &lt;code&gt;readyCounter&lt;/code&gt; and the test will continue execution once every worker is ready.&lt;/p&gt;

&lt;p&gt;Now, we countdown the callBlocker which in turn makes each worker start their toilet paper grabbing logic! And wait until the mayham is over. This is what happens:&lt;/p&gt;

&lt;p&gt;5 GreedyWorkers - 3 ToiletPaper in database - No Lock on database:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="o"&gt;[&lt;/span&gt;           &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toiletpaperrush&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ToiletPaperIT&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Open&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="nc"&gt;Toilet&lt;/span&gt; &lt;span class="nc"&gt;Paper&lt;/span&gt; &lt;span class="nc"&gt;Hunt&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;       &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toiletpaperrush&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ToiletPaperIT&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt; &lt;span class="n"&gt;ready&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;       &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toiletpaperrush&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ToiletPaperIT&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;28&lt;/span&gt; &lt;span class="n"&gt;ready&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;       &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toiletpaperrush&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ToiletPaperIT&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt; &lt;span class="n"&gt;ready&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;       &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toiletpaperrush&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ToiletPaperIT&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;29&lt;/span&gt; &lt;span class="n"&gt;ready&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;       &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toiletpaperrush&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ToiletPaperIT&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;31&lt;/span&gt; &lt;span class="n"&gt;ready&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;       &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toiletpaperrush&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ToiletPaperIT&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;29&lt;/span&gt; &lt;span class="n"&gt;got&lt;/span&gt; &lt;span class="nc"&gt;Toilet&lt;/span&gt; &lt;span class="nc"&gt;Paper&lt;/span&gt; &lt;span class="n"&gt;no&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;       &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toiletpaperrush&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ToiletPaperIT&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt; &lt;span class="n"&gt;got&lt;/span&gt; &lt;span class="nc"&gt;Toilet&lt;/span&gt; &lt;span class="nc"&gt;Paper&lt;/span&gt; &lt;span class="n"&gt;no&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;       &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toiletpaperrush&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ToiletPaperIT&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt; &lt;span class="n"&gt;got&lt;/span&gt; &lt;span class="nc"&gt;Toilet&lt;/span&gt; &lt;span class="nc"&gt;Paper&lt;/span&gt; &lt;span class="n"&gt;no&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;       &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toiletpaperrush&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ToiletPaperIT&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;31&lt;/span&gt; &lt;span class="n"&gt;got&lt;/span&gt; &lt;span class="nc"&gt;Toilet&lt;/span&gt; &lt;span class="nc"&gt;Paper&lt;/span&gt; &lt;span class="n"&gt;no&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;       &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toiletpaperrush&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ToiletPaperIT&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;28&lt;/span&gt; &lt;span class="n"&gt;got&lt;/span&gt; &lt;span class="nc"&gt;Toilet&lt;/span&gt; &lt;span class="nc"&gt;Paper&lt;/span&gt; &lt;span class="n"&gt;no&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;           &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toiletpaperrush&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ToiletPaperIT&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Hunt&lt;/span&gt; &lt;span class="n"&gt;ended&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;5 PatientWorkers - 3 ToiletPaper in database - Lock on database:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="o"&gt;[&lt;/span&gt;           &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toiletpaperrush&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ToiletPaperIT&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Open&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="nc"&gt;Toilet&lt;/span&gt; &lt;span class="nc"&gt;Paper&lt;/span&gt; &lt;span class="nc"&gt;Hunt&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;       &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toiletpaperrush&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ToiletPaperIT&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;35&lt;/span&gt; &lt;span class="n"&gt;ready&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;       &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toiletpaperrush&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ToiletPaperIT&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;33&lt;/span&gt; &lt;span class="n"&gt;ready&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;       &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toiletpaperrush&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ToiletPaperIT&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;36&lt;/span&gt; &lt;span class="n"&gt;ready&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;      &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toiletpaperrush&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ToiletPaperIT&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;37&lt;/span&gt; &lt;span class="n"&gt;ready&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;       &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toiletpaperrush&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ToiletPaperIT&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;34&lt;/span&gt; &lt;span class="n"&gt;ready&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;       &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toiletpaperrush&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ToiletPaperIT&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;35&lt;/span&gt; &lt;span class="n"&gt;got&lt;/span&gt; &lt;span class="nc"&gt;Toilet&lt;/span&gt; &lt;span class="nc"&gt;Paper&lt;/span&gt; &lt;span class="n"&gt;no&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;      &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toiletpaperrush&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ToiletPaperIT&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;37&lt;/span&gt; &lt;span class="n"&gt;got&lt;/span&gt; &lt;span class="nc"&gt;Toilet&lt;/span&gt; &lt;span class="nc"&gt;Paper&lt;/span&gt; &lt;span class="n"&gt;no&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;       &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toiletpaperrush&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ToiletPaperIT&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;36&lt;/span&gt; &lt;span class="n"&gt;got&lt;/span&gt; &lt;span class="nc"&gt;Toilet&lt;/span&gt; &lt;span class="nc"&gt;Paper&lt;/span&gt; &lt;span class="n"&gt;no&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;       &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toiletpaperrush&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ToiletPaperIT&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;No&lt;/span&gt; &lt;span class="nc"&gt;Toilet&lt;/span&gt; &lt;span class="nc"&gt;Paper&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt; &lt;span class="n"&gt;stock&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;       &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toiletpaperrush&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ToiletPaperIT&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;No&lt;/span&gt; &lt;span class="nc"&gt;Toilet&lt;/span&gt; &lt;span class="nc"&gt;Paper&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt; &lt;span class="n"&gt;stock&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;           &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toiletpaperrush&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ToiletPaperIT&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Hunt&lt;/span&gt; &lt;span class="n"&gt;ended&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We see that the greedy ones got grasp on the same toilet paper roll although there were still others left. Patient workers - the case where only one thread could access one ToiletPaper at a time - grabbed toilet paper until the database was empty. But it was ensured that no two threads could access the same entity simultaneously.&lt;/p&gt;

&lt;p&gt;I hope that you got some insights on how to use &lt;code&gt;Runnable&lt;/code&gt;s and &lt;code&gt;CountDownLatch&lt;/code&gt;es to write a multi-threaded test. For everyone interested, I was inspired by this &lt;a href="https://dzone.com/articles/how-i-test-my-java-classes-for-thread-safety"&gt;example&lt;/a&gt;. And maybe you will remember this the next time you go on your toilet paper scavenger hunt in these trying times! 😉&lt;/p&gt;

</description>
      <category>programming</category>
      <category>testing</category>
      <category>database</category>
      <category>java</category>
    </item>
    <item>
      <title>Kickstarting your VR development career with A-Frame!</title>
      <dc:creator>Victor Warno</dc:creator>
      <pubDate>Sun, 29 Dec 2019 15:10:28 +0000</pubDate>
      <link>https://forem.com/schmowser/kickstarting-your-vr-development-career-with-a-frame-4f45</link>
      <guid>https://forem.com/schmowser/kickstarting-your-vr-development-career-with-a-frame-4f45</guid>
      <description>&lt;p&gt;Holidays make you think. All this time away from the oh-so-agile work environment lets your mind soar and leaves room for plenty of ideas left untouched. And so it happened that after I watched the touchingly beautiful &lt;em&gt;Frozen 2&lt;/em&gt; twice, I wondered: "What happened to my dream of working in Computer Vision from quite a while ago? Could I use the skills required in Web Development for CGI projects?"&lt;/p&gt;

&lt;h2&gt;
  
  
  VR meets HTML
&lt;/h2&gt;

&lt;p&gt;That's when I stumbled across &lt;a href="https://aframe.io/docs/1.0.0/introduction/#what-is-a-frame"&gt;A-Frame&lt;/a&gt;. It is a web framework to create experiences in virtual reality. Coming from a web developer background, it is exciting to hear that you can start right off by embedding it into your HTML files. Moreover, you have full access to DOM APIs and JavaScript. This way, you do not have to dive into game engines like &lt;em&gt;Unity&lt;/em&gt; or cope with the intricacies of C# / C++. &lt;/p&gt;

&lt;p&gt;More hot news: They released the stable &lt;a href="https://aframe.io/blog/aframe-v1.0.0/"&gt;v1.0.0&lt;/a&gt; just two weeks ago!&lt;/p&gt;

&lt;p&gt;But why develop 3D content, only to look at it in your 2D browser? Why not use that VR headset you got for Christmas to enhance your developer experience? That's what &lt;em&gt;WebVR&lt;/em&gt; was established for! This JavaScript API lets you access your VR device from your web browser. And A-Frame is basically just a library that incoporates and simplifies WebVR.&lt;/p&gt;

&lt;p&gt;That virtual and augmented reality for web browsers is still in its infancy can be seen in the rather patchy support of WebVR for different operating systems and headsets across the browser landscape. Having tried out &lt;em&gt;Brave&lt;/em&gt; for the last couple of weeks, I now notice that it does not render the output in the same browser tab of online HTML editors. &lt;em&gt;Google Chrome&lt;/em&gt; on the other hand would not let me enter VR mode with my Oculus Quest. &lt;a href="https://webvr.rocks/"&gt;WebVR Rocks&lt;/a&gt; lists all currently supported combinations. Thus, &lt;em&gt;Mozilla Firefox&lt;/em&gt; became the chosen one! Luckily, that allows me to have it working on MacOS as well (where I use &lt;em&gt;Firefox Nightly&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;As VR/AR for the Web should not head &lt;a href="https://www.youtube.com/watch?v=gIOyB9ZXn8s"&gt;Into the Unknown&lt;/a&gt;, it is good to know that the next-generation standard is about to be the lawful heir of everything immersive and is already in the making: &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/WebXR_Device_API"&gt;WebXR&lt;/a&gt;! Where &lt;em&gt;X&lt;/em&gt; will include all the buzzwords you can put in front of &lt;em&gt;Reality&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to setup your Oculus Quest for WebVR
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hgnJEu6d--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://thepracticaldev.s3.amazonaws.com/i/fqdkkwqws23gm4q6wvse.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hgnJEu6d--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://thepracticaldev.s3.amazonaws.com/i/fqdkkwqws23gm4q6wvse.jpg" alt="Alt Text" width="800" height="493"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What you'll need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Oculus VR headset - here: Oculus Quest&lt;/li&gt;
&lt;li&gt;Potent video card - My Windows machine provides a &lt;em&gt;GeForce RTX 2070&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Oculus Link cable - I used &lt;em&gt;Anker Powerline+ 1.8m USB C to USB 3.0 A, Nylon&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.oculus.com/setup/"&gt;Oculus software&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Oculus Link is still in Beta. To use it, make sure that you updated to the latest version on your headset. Hint: It only started to update after the device was fully charged and restarted afterwards.&lt;/p&gt;

&lt;p&gt;When you are using an Nvidia graphics card, it is recommended to have the latest version of &lt;em&gt;GeForce Experience&lt;/em&gt; as well.&lt;/p&gt;

&lt;p&gt;Connect the Quest with a compatible cable to your PC and complete the setup. Put on the Oculus Quest and head to&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Settings -&amp;gt; See All -&amp;gt; Enable Oculus Link (Beta)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This should throw you into Oculus Home. At the bottom, there should be a &lt;em&gt;Virtual Desktop&lt;/em&gt; button. From there a window pops up and you can access your desktop browser from within your headset. Now, you can click the &lt;em&gt;Enter VR&lt;/em&gt; button (usually located at the bottom right corner of your content). You are ready to watch your newly created content on your headset!&lt;/p&gt;

&lt;h2&gt;
  
  
  How to start your A-Frame project
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;html&amp;gt;
  &amp;lt;head&amp;gt;
    &amp;lt;script src="https://aframe.io/releases/1.0.3/aframe.min.js"&amp;gt;&amp;lt;/script&amp;gt;
  &amp;lt;/head&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;a-scene&amp;gt;
    &amp;lt;/a-scene&amp;gt;
  &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is actually all you need to start developing using A-Frame. Plain HTML. The &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tag above imports the library. Inside the &lt;code&gt;&amp;lt;a-scene&amp;gt;&lt;/code&gt;, you can drop any entities of your liking. &lt;/p&gt;

&lt;p&gt;The A-Frame community makes it really easy to directly play around with what the framework has to offer. I recommend the compact (and visually appealing) &lt;a href="//aframe.io/aframe-school"&gt;tutorial&lt;/a&gt; that introduces you to the core concepts. It makes use of the &lt;a href="https://glitch.com/"&gt;Glitch&lt;/a&gt; online editor which lets you modify sample implementations.&lt;/p&gt;

&lt;p&gt;What about existing applications? Of course, you can install A-Frame via npm. And if you do not want to abandon your front-end frameworks, there is even an introduction how to use &lt;a href="https://www.viget.com/articles/creating-your-first-webvr-app/"&gt;A-Frame with React&lt;/a&gt;! But be careful, some features could get in the way of each other. So, for example, A-Frame's hotreloading feature will interfere with Vue's hot loaders.&lt;/p&gt;

&lt;p&gt;But this is just a first step to a note-worthy journey into browser based virtual reality!&lt;/p&gt;

&lt;h2&gt;
  
  
  Show Yourself
&lt;/h2&gt;

&lt;p&gt;We are all set! Grab your XR headset and develop the next Killer VR/AR/MR application. I think having a shortcut from front-end development to creating VR content via A-Frame is worth a look - although web development contains much more than just the presentation and the whole industry won't jump on the AR waggon all of a sudden. &lt;/p&gt;

&lt;p&gt;What do you think about the recent evolutions in virtual reality and web browsers?&lt;/p&gt;

</description>
      <category>vr</category>
      <category>html</category>
      <category>webdev</category>
      <category>aframe</category>
    </item>
    <item>
      <title>Back pain, eye strain, end game!</title>
      <dc:creator>Victor Warno</dc:creator>
      <pubDate>Sun, 08 Sep 2019 21:00:39 +0000</pubDate>
      <link>https://forem.com/schmowser/back-pain-eye-strain-end-game-217i</link>
      <guid>https://forem.com/schmowser/back-pain-eye-strain-end-game-217i</guid>
      <description>&lt;p&gt;This was me around nine months ago:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FWJQsuOE.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FWJQsuOE.gif" alt="Alt text of image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I woke up after short hours of sleep and could not quite make out the opposite wall. It was as if half the room was a steam bath. My right eyesight had become cloudy - the doctor confirmed: inflammation of the iris.&lt;/p&gt;

&lt;p&gt;I was knocked out for several days damned to evade any screen time - no coding, no videos. Only in these moments, one cherishes the careless hours of healthiness that we otherwise spend in front of glaring screens and tables too high, equipped with malformed mouses and odd chairs, weakened by tasty-but-nasty food and sleep long gone.&lt;/p&gt;

&lt;p&gt;Although we are not working on construction sites (or are we?), we need to take care of our body and mind. And in this post, I just want to share how I learned to survive a developer's life.&lt;/p&gt;

&lt;p&gt;(And if you don't want to read that, just check out the videos below!)&lt;/p&gt;




&lt;h1&gt;
  
  
  Back pain &amp;amp; Neck pain
&lt;/h1&gt;

&lt;p&gt;The Hunchback of Notre Dame could have easily been a developer! Doesn't his posture scream overtime crouching over a MacBook to get that feature into the next release? I definitely felt that way.&lt;/p&gt;

&lt;p&gt;Sometimes we are that much into our passion that we just don't leave our workplace. Almost immediately we slouch into an awkward position and somehow remain in that position for hours. And the worst you can probably do for your muscles is not moving at all for a long time, forcing yourself into a position evolution definitely did not prepared us for.&lt;/p&gt;

&lt;p&gt;After a couple of months, I developed serious back pain. Craning my neck was also very uncomfortable. I learned that, ironically, the best cure against back pain is what aches so much: movement. So, I kept walking. And turning. And stretching. One step at a time until everything became manageable.&lt;/p&gt;

&lt;p&gt;But prevention is even better! I now try hard to walk around the office at least once every hour. This can be achieved by little things like drinking  out of a glass instead of having a jug of water at hand (so you have to walk to the dispenser from time to time). Even just putting that glass on the window board can give you a little amount of that sweet, sweet gymnastics when you actually have to stand up to get a drink. I gained a reputation for doing weird little dances during work just to give my body a shake.&lt;/p&gt;

&lt;p&gt;Please, please, please ask your employer (or yourself) to get you an adjustable table and chair! These factors are vital for a comfortable and healthy position for your back. The height of your monitor also plays a significant role in giving me neck pain. It has actually been too high, I was stretching my neck unnaturally. Rule of thumb: &lt;em&gt;Top of the screen should be on eye level!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You will find more tips in this video. There is not a problem that reams of paper cannot solve! 🤣&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/F8_ME4VwTiw"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h1&gt;
  
  
  Carpal Tunnel Syndrome
&lt;/h1&gt;

&lt;p&gt;Once I got rid of my back pain, there was another sensation awaiting me. Typing or using a mouse started a fire inside my forearm as if my tendons were replaced by tiny needles. Hello, &lt;em&gt;Carpel tunnel syndrome&lt;/em&gt;, my old friend?&lt;/p&gt;

&lt;p&gt;Fortunately not! But I was not keen on going down that road. During my last job, I solved this by putting my arm in some kind of DIY splint made out of cardboard. This time I tried to fight the cause and not the symptom: As long as you are not using an ergonomic vertical mouse, you are turning and twisting your forearm and wrist such that your tendons are constantly overstretched. A vertical mouse is not something I considered using, so I had to find out which kind of "mouse gripper" I am:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Palm Grip&lt;/em&gt; - Placing your whole hand onto the mouse, thereby the fingers are locked. Usually, the whole palm lays on the mouse.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Claw Grip&lt;/em&gt; - Similar, whereas index and middle finger are bend and tucked up - looking like a cat's paw. Palm does not lay on the mouse anymore enable fingers to move a little bit.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Fingertips Grip&lt;/em&gt; - Only fingertips touch the mouse, nothing else. Movement does not required any wrist movement.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The last two ones are the grips to go for! Try to do all mouse movements involving the forearm and elbow and not the wrist only. It will strain the already stretched tendons. (Be careful not to use your shoulders though.) This is where the newly arrived adjustable tables and chairs come into play. If the angle between hand and keyboard is to big, you will stretch your tendons. If the angle is to low, you risk locking arm and wrist.&lt;/p&gt;

&lt;p&gt;And what about typing? I am actually trying to type with my hands hovering over the keys. Do not rest your hands on the keyboard. They will just get stuck there forcing you to work with your wrist all the time. I know. It is a lot to remember. Visualizing all this with the following video will hopefully remove any doubts!&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/vG_3bS3ftVM"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h1&gt;
  
  
  Eye strain
&lt;/h1&gt;

&lt;p&gt;Back to my steamy eye. &lt;/p&gt;

&lt;p&gt;What did I learn from that? Obviously, I was focusing too hard on the big rectangle in front of me. My eyes dried out over time. I did not give them a chance to relax at all.&lt;/p&gt;

&lt;p&gt;First of all: the distance to the screen. If you are working with a laptop, get a stand and a Bluetooth keyboard to get some space between you and the machine! Many people also favor the &lt;em&gt;20-20-20 rule&lt;/em&gt; (i.e.: every 20 minutes look at something 20 feet away for at least 20 seconds). Besides the fact that I don't know how much a foot is, it is easy to forget. And I am not a fan of setting an alarm as it rips me out of the routine. &lt;/p&gt;

&lt;p&gt;I like to combine relaxing my eyes with the aforementioned walk. Ideally, a walk outside or to the balcony to focus something in the distance. What really helped was getting a seat next to a window. Just checking where all the noise comes from or what the weather is outside reminds me to lay my eyes onto the horizon!&lt;/p&gt;

&lt;p&gt;Or just water your eyes like a plant. From the incidence on, I always have eye-drops in my drawer by the desk. For emergency. Otherwise, I splash water into my face, close my eyes, rub them. This way, we will never get those red eyes again!&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/wyVc37ykstU"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h1&gt;
  
  
  Noise
&lt;/h1&gt;

&lt;p&gt;Luckily, my current environment is kind of quiet. But I also experienced spaces where concentrating and blocking out dialogues or machine noises become very hard. So, what to do? Buying expensive noise-canceling headphones? They can work surprisingly well at filtering out some voices and frequencies around you. What about music? Definitely a yes, if you don't crank it up the scale, of course - which would actually make &lt;em&gt;you&lt;/em&gt; a noise polluter!&lt;/p&gt;

&lt;p&gt;In the end, I went with the headphones. They even provide you with a tool to stop regular intruders to interrupt your working flow. It can be signal to the outside that you are in &lt;em&gt;the zone&lt;/em&gt; right now. And you get your peace.&lt;/p&gt;

&lt;p&gt;Listen to the following video with caution. Ironically, it has a weird audio mixing. 😆&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/z4Da0kuYnMI"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h1&gt;
  
  
  Sleep
&lt;/h1&gt;

&lt;p&gt;By now, we all now how unhealthy it is to not get enough sleep. So, the video I leave here is just how you can find out whether you are sleep deprived. &lt;/p&gt;

&lt;p&gt;I cannot tell you what the perfect amount of sleep is. Sleep has always been very individual. Falling asleep though is more researched. Reading a book in bed for example helps you fall asleep faster than checking dev.to (or any other site 😉 ) on your mobile does.&lt;/p&gt;

&lt;p&gt;Oh, and don't put on your favorite song as an alarm in the morning. 🙈&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/0HxvEcvfbho"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h1&gt;
  
  
  Nutrition &amp;amp; Sport
&lt;/h1&gt;

&lt;p&gt;That all was about the stuff you do at work. &lt;em&gt;Do not tell me about things I have to do in my free time!&lt;/em&gt; I won't. Everybody knows what we &lt;em&gt;should&lt;/em&gt; eat. And how much we &lt;em&gt;should&lt;/em&gt; work out. Of course, working out benefited my back health. But the most palpable change I noticed while and after putting my body in shape was the improvement of my mental state. Going on a 30-minute-run you can eliminate all the thoughts around work. Cutting the sweets and greasy edibles also stabilized my mood. But this would open up a whole new realm of self-care: How to not get depressed or insane.&lt;/p&gt;

&lt;p&gt;Apparently, you can train your gut to signal the brain which foods to crave. Check out this clip if your interested!&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/VzPD009qTN4"&gt;
&lt;/iframe&gt;
&lt;/p&gt;




&lt;p&gt;And I am far from perfect. I find myself slouching or not doing exercise after a long day of work. Heck, I am writing this article at 11pm, I have to get up at 6am tomorrow! &lt;/p&gt;

&lt;p&gt;But as always, we just need a constant reminder of what's in our hands. We need to talk about this more often. With colleagues, with employers, with the internet. Because after all work is done, all laptops are closed and all pull requests merged, we come home. And the only relics of our work should be great user experiences and not the aching of our bodies!&lt;/p&gt;




&lt;p&gt;TL;DR:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adjust your equipment!&lt;/li&gt;
&lt;li&gt;Tension is bad!&lt;/li&gt;
&lt;li&gt;Take breaks!&lt;/li&gt;
&lt;li&gt;Sleep!&lt;/li&gt;
&lt;li&gt;Talk about it!&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>productivity</category>
      <category>discuss</category>
      <category>healthydebate</category>
      <category>motivation</category>
    </item>
    <item>
      <title>Ready Developer One - Devoxx UK 2019</title>
      <dc:creator>Victor Warno</dc:creator>
      <pubDate>Mon, 20 May 2019 21:43:07 +0000</pubDate>
      <link>https://forem.com/schmowser/ready-developer-one-devoxx-uk-2019-4625</link>
      <guid>https://forem.com/schmowser/ready-developer-one-devoxx-uk-2019-4625</guid>
      <description>&lt;p&gt;This year I decided to dive deeper into the Dev community! From reading your awesome &lt;em&gt;dev.to&lt;/em&gt; articles to writing blog posts myself. But now, it was time for the next step: Visiting a Developer Conference to submerge myself in tech talks, hands-on coding and networking! I would like to share some experiences and insights from the conference. Of course, I cannot recite the whole awesomeness of the speaker's content but I will try to give you some TL;DR on my favorite ones!&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Day 1&lt;/em&gt; (Array starts at 0... but I only joined on Thursday being the second day of the conference 😉 )&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.devoxx.co.uk/"&gt;Devoxx UK&lt;/a&gt; is held at the Business Design Center in Angel, London. It is quite the busy area but once inside the Center, you find your way fairly quickly. This year, inside the entrance hall they prepped the DeLorean, the iconic car from &lt;em&gt;Back to the Future&lt;/em&gt;! - Does that mean time travel is a feature of the next &lt;em&gt;Oracle&lt;/em&gt; Java Release cycle?! 😀 I could have actually asked them as they had a booth at the conference - so did a bunch of other companies. Even the country of Estonia was represented (because apparantly they have migrated their governance 100% online!?). After getting explained what all those companies do, in exchange for &lt;em&gt;Black Duck&lt;/em&gt; socks, I headed directly to the conference rooms!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://drewtarvin.com/"&gt;Andrew Tarwin&lt;/a&gt;'s kick-off to making your work place worthwhile&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The opening keynote showed me that this conference is not only about the new fancy languages out there or the most treacherous pitfalls but that it also focuses on how we (should) work together. And Tarwin's answer would be: with more humor! It can make dull tasks enjoyable (e-mails) and can defuse critical situations (pull request comments). Just know your MAP (Medium - Audience - Purpose) and you can use humor for the better! And writing e-mails do feel like a refreshing task now. 😉&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://twitter.com/trisha_gee"&gt;Trisha Gee&lt;/a&gt;’s staccato of IntelliJ IDEA shortcuts&lt;/strong&gt; - &lt;a href="https://youtu.be/uu7j1_jhiU4?list=PLRsbF2sD7JVqkOs-GFGxBmNf0KECELaiU"&gt;Video&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This was the talk I was most excited about. I am an absolute IntelliJ Idea fanboy and no other than Trisha Gee from &lt;em&gt;JetBrains&lt;/em&gt; was honoring us with her witty sleights of hand that are Idea shortcuts. Did you know that Idea is a time machine? &lt;a href="https://www.jetbrains.com/help/idea/altering-the-program-s-execution-flow.html#drop_frame"&gt;Drop frame&lt;/a&gt; while Debugging if you stepped too far! Or &lt;a href="https://www.jetbrains.com/help/idea/using-language-injections.html"&gt;Inject Language&lt;/a&gt; to make JSON, SQL, or RegEx more readable. &lt;code&gt;Ctrl&lt;/code&gt;/&lt;code&gt;Cmd&lt;/code&gt; + &lt;code&gt;Shift&lt;/code&gt; + &lt;code&gt;Up&lt;/code&gt;? &lt;code&gt;Ctrl&lt;/code&gt;/&lt;code&gt;Cmd&lt;/code&gt; + &lt;code&gt;N&lt;/code&gt;? &lt;code&gt;Alt&lt;/code&gt; + &lt;code&gt;Enter&lt;/code&gt;? I do not want to use my mouse anymore! 😆&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://twitter.com/dgageot"&gt;David Gageot&lt;/a&gt;’s weapons for convenient CD&lt;/strong&gt; - &lt;a href="https://youtu.be/3nfNP00Tv1k?list=PLRsbF2sD7JVqkOs-GFGxBmNf0KECELaiU"&gt;Video&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Unfortunately, I did not have much contact with containerization but Gageot showcased several tools by &lt;em&gt;Google&lt;/em&gt; to make your life easier! Having played around with Docker, I could not imagine what a hassle it was to debug your code with slow Docker builds, countless configuration files and storage-intensive images. But in this descriptive talk, Gageot was able to demonstrate Kubernetes, Kaniko, Jib and many other helpful tools in a meaningful manner.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.linkedin.com/in/peter-godfrey-75662b83/?originalSubdomain=uk"&gt;Peter Godfrey&lt;/a&gt;’s Survival Guide for Apache Kafka&lt;/strong&gt; - &lt;a href="https://youtu.be/xsdoQkoao2U?list=PLRsbF2sD7JVqkOs-GFGxBmNf0KECELaiU"&gt;Video&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On our project, we recently started to work with Kafka. So, I was excited to bring home some useful tricks to improve our event streams. Godfrey pointed out that although this framework is made for low latency, quick and resilient work, it is not shipping with Durability out of the box. Therefore, he shared some configurations that can be tweaked to give you exactly that. For example, increasing the &lt;code&gt;acks&lt;/code&gt; parameter (acknowledgements) to have your data replicated to all cluster machines, or enabling &lt;code&gt;retries&lt;/code&gt; which are set to 0 by default. Exception handling, versioning and monitoring are also things to be considered. A very handy talk!&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;As rocking as the Devoxx sounds, it is nothing like a music festival&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So, networking is a thing. Maybe, &lt;em&gt;the&lt;/em&gt; thing. And usually, I do not have issues approaching people in public and making new friends. One of my favorite places to get to know new pals are music festivals after all. But a developer conference evidently has a different format. There are conference talks in similar time slots but scheduled much more densely than the gigs on a festival. Thus, there is little waiting time to kill and eventually, no room for any eye-catching goofy dancing for entertainment (or is there?). There is usually no conversation with a fan next to you. After one “developer gig” ended, I hustled to the next one, only to find myself just in time to marvel at the expertise of another speaker! In silence.&lt;/p&gt;

&lt;p&gt;So how do people do it? For some it is fairly simple by just introducing themselves. If that is too hard, pay attention to hooks – like some merchandise someone acquired and ask where they got it. Even just asking how to get to that booth that gives out all the ice cream can get you talking! Anything just to get started. I learned to skip slots and just roam around the conference floor. Picking up where other people go next and ask if I might join. And boom – there is time to talk! Plus: You do not have to miss out on any sessions. And maybe you will be visiting one you would never thought of going before!&lt;/p&gt;

&lt;p&gt;But at the end of the day, the network-iest of all the events awaited us: the DevRoxx Party!&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Day 2&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://twitter.com/bjschrijver"&gt;Bert Jan Schrijver&lt;/a&gt;’s deconstruction of DevOps&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When you are like me, you are probably asking yourself way too often what &lt;em&gt;DevOps&lt;/em&gt; actually is. Is it the thing that you do when you turn red Jenkins balls into blue ones? Schrijver's suggestion is that &lt;em&gt;DevOps&lt;/em&gt; is a culture: Having building, testing and deploying pipelines in a team where everyone feels responsible for the frameworks and processes behind bringing your software into production.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://twitter.com/SecurityPony"&gt;Siren Hofvander&lt;/a&gt;’s fight for a secure world&lt;/strong&gt; - &lt;a href="https://www.youtube.com/watch?v=jWyxMv6h3S4&amp;amp;feature=youtu.be"&gt;Video&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From opening key note to closing key note: Hofvander had missed her flight giving her the chance to be one of the last voices to be heard. Along the construction (and unfortunate) deconstruction of the &lt;em&gt;Titanic&lt;/em&gt;, she showed the audience that even the greatest minds in engineering, testing and design are not immune to tragedies in production. Therefore, she keeps drilling into projects and minds everywhere to make Security mainstream and keeping the awareness high for all the icebergs ahead!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://twitter.com/heathriel"&gt;Heather Wilde&lt;/a&gt;’s prophylaxis for modern era’s cholera named Burnout&lt;/strong&gt; - &lt;a href="https://youtu.be/zS-QsLsQGsI?list=PLRsbF2sD7JVqkOs-GFGxBmNf0KECELaiU"&gt;Video&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We have all these tools and all these interesting riddles in front of us, everyday. Who has time for a break then? - While being on a conference or hunting down a bug can put us in eustress (stimulating, beneficial stress), it can turn into disstress quickly. This is when we need a break. Wilde strongly identifies the different signs of an upcoming Burnout and - more importantly - how to recognize these in other people. Because the best thing to prevent or get out of this void is having someone to hold on to!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://twitter.com/venkat_s"&gt;Venkat Subramaniam&lt;/a&gt;’s fluency in all the languages and his bet for the future&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Subramaniam is a phenomenon. He talks fast but you understand every word. He writes code like it was a novel. And he can look into the future! But first he presented all the cool things you can do with JVM languages. Doesn't matter if it is Auto Casting in Kotlin, creating XML documents in Groovy or Lazy Evaluation in Scala. Subramaniam rides beautifully along these language features and makes me want to learn all the languages - like he says "not to use them all, but to be able to adapt to change easily". And what his forecast for the future of programming is, you ask? &lt;a href="https://youtu.be/1sjoiBA0MTw?list=PLRsbF2sD7JVqkOs-GFGxBmNf0KECELaiU"&gt;See&lt;/a&gt; for yourself.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Don't wait for the future, it is already here&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;After two days of being the spongiest absorber of wisdom, I feel inspired. Inspired by the energy of the presenters and the possibilities we have. But I liked that it was not only a promo event for the newest tools and coolest designs but also a roadmap with dangers and uncertainty ahead. It was pleasant to see that the human factor also never fell short throughout these two days. I also feel like I have to take time to look at the talks again, trying things out for myself. All in all, it is always refreshing to step out of your everyday tasks and let your mind stock up on new experiences.&lt;/p&gt;

&lt;p&gt;In the end, I was blessed to have met a lot of talkative and curious people. Doing various things and technologies in different companies all over the world. All had a story to tell and giving away tips and tricks. Throughout the conference, you keep meeting them again and passing familiar faces makes the conference feel more like a community-driven event (with an event-driven community 😉). There was always the chance to exchange numbers or scanning the QR-Code on your badge. And with LinkedIn and Co., nowadays, it is a breeze to keep in touch. To really live the old saying: You always meet twice. &lt;/p&gt;

&lt;p&gt;Therefore: See you next year, Devoxx!&lt;/p&gt;

</description>
      <category>dev</category>
      <category>learning</category>
      <category>conference</category>
      <category>devoxx</category>
    </item>
    <item>
      <title>Recycle your old laptop to upgrade your Raspberry Pi Setup!</title>
      <dc:creator>Victor Warno</dc:creator>
      <pubDate>Wed, 01 May 2019 20:14:08 +0000</pubDate>
      <link>https://forem.com/schmowser/recycle-your-old-laptop-to-upgrade-your-raspberry-pi-setup-54c5</link>
      <guid>https://forem.com/schmowser/recycle-your-old-laptop-to-upgrade-your-raspberry-pi-setup-54c5</guid>
      <description>&lt;h2&gt;
  
  
  Ingredients
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Old notebook&lt;/li&gt;
&lt;li&gt;Raspberry Pi with SD Card and Power Supply&lt;/li&gt;
&lt;li&gt;Ethernet Cable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some weeks ago, a friend of mine got herself a new notebook and she wondered what she could do with the old one now. As she did not want to just toss it in the trash, she turned to me. Whether I had a suggestion for a new purpose, she asked. &lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;div class="ltag__link__content"&gt;
    &lt;div class="missing"&gt;
      &lt;h2&gt;Article No Longer Available&lt;/h2&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Then, I remembered that I recently set up a Raspberry Pi as a Development Server inspired by the &lt;em&gt;dev.to&lt;/em&gt; post above. But as I had not wanted to dedicate a separate monitor, keyboard and mouse for the Raspberry Pi, I got an idea how to reuse that old notebook of hers. Use the laptop for interaction! Therefore, this will be a compact version of &lt;a href="https://www.instructables.com/id/How-to-connect-raspberry-pi-to-laptop-display/"&gt;&lt;em&gt;instructable&lt;/em&gt;'s guide&lt;/a&gt; to connect Raspberry Pies with Laptops. But I hope a helpful one, nonetheless.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup the Pi
&lt;/h2&gt;

&lt;p&gt;So, I have the Pi model 3B+ here which luckily ships with an onboard Wireless LAN adapter! I flashed the SD card with &lt;a href="https://www.raspberrypi.org/downloads/raspbian/"&gt;Raspbian&lt;/a&gt;. Somehow, none of the Ubuntu distributions worked with me as they would not recognize the wlan feature. But besides that, Sarthak Sharma's post is a great introduction to get your Pi going. Unfortunately, before having the following steps done, you will need a screen and a keyboard of some sort to enter these instructions. But this will hopefully be the last time.😉&lt;/p&gt;

&lt;p&gt;Most importantly, you have to know the IP address of your Raspberry Pi. You get it easily by opening a terminal and typing&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;hostname -I
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The address usually has this form: &lt;em&gt;xxx.xxx.xxx.xx&lt;/em&gt;. Jot it down, you will need it later. Now, install TightVNC - this is a remote control software package. And it is for free! With this we are going to start a remote server and access it from the laptop.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt-get update
sudo apt-get install tightvncserver
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After installation start up a server and specify a port (here: 1).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo vncserver :1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will be asked to set a password. For some reason, you have to choose an 8-character-password. Anything longer will be truncated. 😅&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup the Laptop
&lt;/h2&gt;

&lt;p&gt;Grab the old thing, boot it up and cram the ethernet cable inside! The other end will serve the connection to the Raspberry. In order to connect to the VNC server you just created, you need to use the &lt;a href="https://www.realvnc.com/de/connect/download/viewer/"&gt;VNC Viewer&lt;/a&gt;. One download and one installation later, you should be able to create a new connection where you specify hostname and port obtained above:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;xxx.xxx.xxx.xx:1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Encryption&lt;/em&gt; can be left at &lt;em&gt;Let VNC Server choose&lt;/em&gt;. Be sure to enter your 8-digit-password correctly and hit Enter! You should see what your Raspberry Pi would render. VNC Viewer usually saves the settings, so that you can easily reconnect the next time you need screen, keyboard and trackpad of your newly born Laptop.&lt;/p&gt;

&lt;p&gt;And that is how you save an old laptop from the trash can!&lt;/p&gt;

</description>
      <category>raspberrypi</category>
      <category>pi</category>
      <category>productivity</category>
      <category>tips</category>
    </item>
    <item>
      <title>Pair Programming, Trio Programming, Sextuplet Programming?!</title>
      <dc:creator>Victor Warno</dc:creator>
      <pubDate>Fri, 25 Jan 2019 22:10:20 +0000</pubDate>
      <link>https://forem.com/schmowser/pair-programming-trio-programming-sextuplet-programming-9k2</link>
      <guid>https://forem.com/schmowser/pair-programming-trio-programming-sextuplet-programming-9k2</guid>
      <description>&lt;p&gt;Unless you are a spider, it is hard to throw more than two eyes on your code all by yourself. (I get &lt;em&gt;entangled&lt;/em&gt; in my code from time to time anyway 😉 ) So once in a while, I can hear a &lt;em&gt;"Woah, dude. What is this?"&lt;/em&gt; from the desk next to mine. Followed by another &lt;em&gt;"I don't think your method is even called at all"&lt;/em&gt;. I slide my swivel chair to the baffled colleague.&lt;/p&gt;

&lt;p&gt;And 💥! You're in a pair programming session.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;2&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Looking at colourful lines of algorithms together is not something you necessarily have to plan. (Although all agile teams probably jot that down as a must-have action point at least once every month.) It just happens. It's in the nature of what you do. Gosh, you wouldn't use Git if it weren't for others. Remember when you did Pull Requests on a repository you're the sole contributor to? Oh, those insta-merge-times!&lt;/p&gt;

&lt;p&gt;So, be ready for some dinner for two. Actually, it is a feast, a feast for experiences and learning. As countless of developers before me have pointed out: You learn more by explaining your use of Promises or what other wizardry you can do. Not only as a beginner. Explaining is double the learning - that is true magic!&lt;/p&gt;

&lt;p&gt;Some of my tricks to make this experience even more rewarding are those which make sure both have a common ground to work with. Making a quick sketch on paper to visualize the software architecture? Insights - yes, please! Reformulating things that were explained and new to you? You got it!&lt;/p&gt;

&lt;p&gt;Even the smallest things can surprise some of the most experienced programmers. Switching from a method to its test in IntelliJ Idea without touching the mouse can raise a &lt;em&gt;"Wait, how did you do that?"&lt;/em&gt; and promotes shortcuts that can save time for all!&lt;/p&gt;

&lt;p&gt;As social as it is, often we can lose track of time and space. Sometimes, we are intensely discussing and generating code that we don't notice the disruption we create for the rest of the team. This is especially the case when you get along with your fellow reviewer and joke around and gasp synchronously at every compile error. So, be aware that other people's workflow can be disrupted. (That's why I am for free noise-cancelling headphones for every dev in the world! 🎉)&lt;/p&gt;

&lt;p&gt;And all that hustle and bustle can attract other predators. 😉&lt;/p&gt;

&lt;p&gt;&lt;em&gt;3&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Then, a third programmer joins the battle! My code is under attack by two professionals! (Which I am thankful for as I have a lot to learn.) As a Junior, it is actually quite interesting to be quiet for a while and listening to two developers debating. You get to know the lingo, how to talk about code, how to analyze and structure your thoughts in a meaningful way. &lt;/p&gt;

&lt;p&gt;It turns into another thing when three Seniors get together. Those debates can get hot tempered but also very revealing and inspiring. It is probably like a three-roomate situation. When you get along, everyone is winning. But unfortunately, this constellation favors 2-to-1 majorities which can tip the scales.&lt;/p&gt;

&lt;p&gt;Therefore, in threesomes I tend to play the listening part. When explaining happens, only one should do it with potential additional remarks at the end by the third person. Otherwise, it can get confusing. Maybe, it is time for a whiteboard session. But as you know: Three people drawing on whiteboards can lead to craning necks...&lt;/p&gt;

&lt;p&gt;&lt;em&gt;6&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I know that my code can look like a car accident. But I did not know that it attracts as many rubbernecks as a real one. Meanwhile, five other developers stand behind me and watch my Annotations do weird stuff. For people outside the bubble, it must look like I am successfully hacking into the FBI database. (Which I don't.)&lt;/p&gt;

&lt;p&gt;This situation does not occur too many times. But when the problem is significant and hard enough, it could attract plenty of viewers. And this mass can work as a whole and crack the nut. I noticed that these gatherings do not take too long. Not only do some colleagues lose interest, it can make all of us unproductive when sitting around one table for just one specific bug.&lt;/p&gt;

&lt;p&gt;Thus, last time I reviewed my findings with a handful of other excellent colleagues, I had screen-recorded the execution steps beforehand so that I do not stumble upon unforeseeable errors and waste anyone's time. Or replacing verbose curl commands with a GUI-like Postman setup. Making your work comprehensible for several is more tricky than having the time and focus to convey it to one person.&lt;/p&gt;

&lt;p&gt;Nevertheless, it is a comfortable thought that enough people care for your problem. Willing to group up with you. In these moments, I feel the team energy and capability that we all long for!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;1&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;At the end of the day, everyone returns to his or her own screen. You can take a break or go home or start another flow just for yourself. Other than most meetings, I come back to my desk with confidence after a pair programming session. Having been productive albeit not having produced a lot of lines of code. &lt;/p&gt;

&lt;p&gt;That is also a funny side effect to all that duo, trio and sextuplet coding. Cherishing your me-time!&lt;/p&gt;

</description>
      <category>programming</category>
      <category>dev</category>
      <category>learning</category>
      <category>career</category>
    </item>
    <item>
      <title>The forges behind Netflix, LinkedIn and Co.</title>
      <dc:creator>Victor Warno</dc:creator>
      <pubDate>Wed, 19 Dec 2018 22:33:15 +0000</pubDate>
      <link>https://forem.com/schmowser/the-forges-behind-netflix-linkedin-and-co-2a91</link>
      <guid>https://forem.com/schmowser/the-forges-behind-netflix-linkedin-and-co-2a91</guid>
      <description>&lt;p&gt;When people at home bring up Spotify and Netflix, they often discuss the content these platforms provide. But inside the developer community we do not only discuss the newest season of &lt;em&gt;House of Cards&lt;/em&gt; but rather the frameworks companies like this have contrived over time.&lt;/p&gt;

&lt;p&gt;I was amused by this discrepancy and was wondering at which point a tech company turns from content-deliverer to content-handler. Take LinkedIn. The profiles, search queries and communication channels scaled over the years and LinkedIn turned their monolithic application infrastructure into microservices. In order to cope with these challenges, LinkedIn developed &lt;a href="https://engineering.linkedin.com/blog/2016/04/kafka-ecosystem-at-linkedin" rel="noopener noreferrer"&gt;Kafka&lt;/a&gt;, a event-driven messaging system. They started off with several small queuing pipelines for the interaction between services, but then went on to develop a publisher-subscriber platform. &lt;a href="https://insidebigdata.com/2016/04/28/a-brief-history-of-kafka-linkedins-messaging-platform/" rel="noopener noreferrer"&gt;Instead of maintaining and scaling those pipelines one-by-one.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Netflix met a similar problem: As they have tons of services, even in different zones, and only few edge services that receive requests, this ginormous amount of calls have to be distributed to these services. Load balancing algorithms back then did not deliver satisfying performances, so they came up with own ones and  tied them up with &lt;a href="https://medium.com/netflix-techblog/announcing-ribbon-tying-the-netflix-mid-tier-services-together-a89346910a62" rel="noopener noreferrer"&gt;Ribbon&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Infrastructural change is not the only catalysator for innovation. Even if given language frameworks do not meet your requirements, you could think of introducing your own. That's &lt;a href="https://reactjs.org/blog/2013/06/05/why-react.html" rel="noopener noreferrer"&gt;how and why&lt;/a&gt; Facebook gave birth to React.&lt;/p&gt;

&lt;p&gt;And what about Spotify? While they did not contribute a huge technological framework, they demonstrate a way to incorporate the agile part of software development into the over-all structure of an organization. They decided to not only to use Agile Practices in small teams but on a big scale. So, Spotify introduced &lt;a href="https://www.growly.io/spotify-engineering-model-with-squads-tribes-chapters-and-guilds/" rel="noopener noreferrer"&gt;Squads, Chapters, Tribes and Guilds&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It is one thing to come up with these ideas. It is another to share them with others. All mentioned novelties have hit the open source field. The messaging system above is even just refered to as &lt;em&gt;Apache&lt;/em&gt; Kafka, named after the Open Source License which &lt;em&gt;Ribbon&lt;/em&gt; is also licensed under. Not to mention the role Facebook's React plays in the Frontend community. The trend in moving to Open Source and common knowledge is on-going. And these companies have a deep interest in giving access to their inventions.&lt;/p&gt;

&lt;p&gt;What other companies do you expect to emerge as a pusher for new technologies and frameworks or mindsets? Or maybe you had a solid problem that you or your team solved with a self-invented toolset? And why Open Source?&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>opensource</category>
      <category>technology</category>
    </item>
    <item>
      <title>@OneToMany relations in Hibernate and its perils</title>
      <dc:creator>Victor Warno</dc:creator>
      <pubDate>Sun, 02 Dec 2018 21:40:11 +0000</pubDate>
      <link>https://forem.com/schmowser/onetomany-relations-in-hibernate-and-its-perils-1a41</link>
      <guid>https://forem.com/schmowser/onetomany-relations-in-hibernate-and-its-perils-1a41</guid>
      <description>&lt;p&gt;Recently, I had trouble persisting an object with Hibernate. I would like to depict my journey along the well-known example of documenting the microphones of a karaoke bar! Here, we have two microphones (of course, a yellow one to the obligatory black one!) for our bar called Monster Karaoke. We create the microphones first, then the bar and ultimately save it to a corresponding JPA repository.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;Microphone&lt;/span&gt; &lt;span class="n"&gt;blackMicrophone&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Microphone&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;microphoneId&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;UUID&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;randomUUID&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"black"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

&lt;span class="nc"&gt;Microphone&lt;/span&gt; &lt;span class="n"&gt;yellowMicrophone&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Microphone&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;microphoneId&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;UUID&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;randomUUID&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"yellow"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Microphone&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;microphoneList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Arrays&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;asList&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;blackMicrophone&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;yellowMicrophone&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="nc"&gt;KaraokeBar&lt;/span&gt; &lt;span class="n"&gt;karaokeBar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;KaraokeBar&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;barId&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;UUID&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;randomUUID&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Monster Karaoke"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;microphoneList&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;microphoneList&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

&lt;span class="n"&gt;karaokeBarRepository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;save&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;karaokeBar&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A KaraokeBar object contains a list of Microphone objects which is annotated with Hibernate's &lt;code&gt;@OneToMany&lt;/code&gt;. But when executing the code, following happens:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;Request&lt;/span&gt; &lt;span class="n"&gt;processing&lt;/span&gt; &lt;span class="n"&gt;failed&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 
&lt;span class="n"&gt;nested&lt;/span&gt; &lt;span class="n"&gt;exception&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt; &lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;springframework&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;orm&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;jpa&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;JpaObjectRetrievalFailureException&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; 
&lt;span class="nc"&gt;Unable&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;find&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;schmowser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;radio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;domain&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Microphone&lt;/span&gt; &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="n"&gt;fb133ab8&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;72&lt;/span&gt;&lt;span class="n"&gt;ee&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="n"&gt;bf4&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ac5f&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;4701&lt;/span&gt;&lt;span class="n"&gt;cb99e766&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Couldn't be found? I see that we need to cascade persistence such that our magnificiently painted micros get persisted when the KaraokeBar instance is. But even after adding&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@OneToMany&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cascade&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CascadeType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;PERSIST&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Microphone&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;microphoneList&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;a &lt;code&gt;javax.persistence.EntityNotFoundException&lt;/code&gt; convinces us that the microphones are still not committed for persistence. And only now, I remember that we know someone who is responsible for persisting any entities to databases. It's the EntityManager within the &lt;code&gt;@PersistenceContext&lt;/code&gt;. After autowiring it and using entityManager.perist, this pops up:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;No EntityManager with actual transaction available for current thread - 
cannot reliably process 'persist' call
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yeah, we have to annotate the method with &lt;code&gt;@Transactional&lt;/code&gt; denoting that all transactional matters are handled in the background automatically! Furthermore, we have to define the owner side object (KaraokeBar) first, then setting it in our Microphone instances, and then setting the list in karaokeBar. Otherwise, this exception occurs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;org.hibernate.TransientPropertyValueException: 
Not-null property references a transient value - 
transient instance must be saved before current operation : 
de.schmowser.radio.domain.Microphone.karaokeBar -&amp;gt; de.schmowser.radio.domain.KaraokeBar
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It feels like we are close to letting our customers know which microphones our bar offers. Curiously, without the Repository.save command, the following code snippet compiles...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Microphone&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;microphoneList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Arrays&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;asList&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;blackMicrophone&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;yellowMicrophone&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;karaokeBar&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setMicrophoneList&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;microphoneList&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;entityManager&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;persist&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;karaokeBar&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;entityManager&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;persist&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;blackMicrophone&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;entityManager&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;persist&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;yellowMicrophone&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;karaokeBarRepository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;save&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;karaokeBar&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;...while &lt;em&gt;with&lt;/em&gt; saving, it does not. Having the last line included rewards us with a &lt;code&gt;java.lang.UnsupportedOperationException&lt;/code&gt;. This one is actually quite hard to decipher. Somehow, Hibernate neither likes us nor unmodifiable lists. Therefore, we give him what it wants: Something to modify.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Microphone&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;microphoneList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ArrayList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;
&lt;span class="n"&gt;microphoneList&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;blackMicrophone&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;microphoneList&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;yellowMicrophone&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hibernate is merciful and gives us what we desire!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nl"&gt;Hibernate:&lt;/span&gt; &lt;span class="n"&gt;insert&lt;/span&gt; &lt;span class="n"&gt;into&lt;/span&gt; &lt;span class="nf"&gt;karaoke_bar&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;karaokebar_id&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt; &lt;span class="o"&gt;(?,&lt;/span&gt; &lt;span class="o"&gt;?)&lt;/span&gt;
&lt;span class="nl"&gt;Hibernate:&lt;/span&gt; &lt;span class="n"&gt;insert&lt;/span&gt; &lt;span class="n"&gt;into&lt;/span&gt; &lt;span class="nf"&gt;microphone&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;karaokebar_id&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;microphone_id&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt; &lt;span class="o"&gt;(?,&lt;/span&gt; &lt;span class="o"&gt;?,&lt;/span&gt; &lt;span class="o"&gt;?)&lt;/span&gt;
&lt;span class="nl"&gt;Hibernate:&lt;/span&gt; &lt;span class="n"&gt;insert&lt;/span&gt; &lt;span class="n"&gt;into&lt;/span&gt; &lt;span class="nf"&gt;microphone&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;karaokebar_id&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;microphone_id&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt; &lt;span class="o"&gt;(?,&lt;/span&gt; &lt;span class="o"&gt;?,&lt;/span&gt; &lt;span class="o"&gt;?)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Is this anyway near your experience with Hibernate? How do you handle this storm of exceptions - generally and maybe more effectively?&lt;/p&gt;

</description>
      <category>hibernate</category>
      <category>java</category>
      <category>persistence</category>
      <category>beginners</category>
    </item>
    <item>
      <title>What does a mathematician say to a developer?</title>
      <dc:creator>Victor Warno</dc:creator>
      <pubDate>Wed, 14 Nov 2018 22:53:25 +0000</pubDate>
      <link>https://forem.com/schmowser/what-does-a-mathematician-say-to-a-developer-2ljl</link>
      <guid>https://forem.com/schmowser/what-does-a-mathematician-say-to-a-developer-2ljl</guid>
      <description>&lt;p&gt;I have been lurking on this website for quite some time. Then, I thought it is time to participate in all this and introduce myself: &lt;/p&gt;

&lt;p&gt;My name is Victor and on this day I have been doing the job as a developer for exactly half a year. Before, I was a student of mathematics. Therefore, I had to learn coding in a professional environment. (Yeah, research can also be professional, but refactoring and tests were a rarity!)&lt;/p&gt;

&lt;p&gt;It turns out that I find a lot of fun in what software developers do. They do not only find solutions but they also do it together. And everyday there is so much more to learn! This is when we come back to the starting question:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;What does a mathematician say to a developer?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In my case, it is mostly: Questions. Questions to my colleagues and supervisors. Questions about coding style, questions about agile (or not so agile) software development. And that is what this site is about, right? Asking questions to get smarter together!&lt;/p&gt;

&lt;p&gt;Do you stumble upon mathematics from time to time? &lt;/p&gt;

</description>
      <category>introduction</category>
    </item>
  </channel>
</rss>
