<?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>DEV Community: Anthony Bruno</title>
    <description>The latest articles on DEV Community by Anthony Bruno (@aussieguy).</description>
    <link>https://dev.to/aussieguy</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%2F19410%2F74c56bc1-2cb7-4ac0-be53-4260c76d7d17.png</url>
      <title>DEV Community: Anthony Bruno</title>
      <link>https://dev.to/aussieguy</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/aussieguy"/>
    <language>en</language>
    <item>
      <title>How I’m learning Clojure in 2024</title>
      <dc:creator>Anthony Bruno</dc:creator>
      <pubDate>Mon, 10 Jun 2024 00:00:00 +0000</pubDate>
      <link>https://dev.to/aussieguy/how-im-learning-clojure-in-2024-1h3h</link>
      <guid>https://dev.to/aussieguy/how-im-learning-clojure-in-2024-1h3h</guid>
      <description>&lt;p&gt;I’ve recently been learning a bit of Clojure and it’s been a lot of fun! I thought I would note down what has been useful for me, so that it might help others as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Jumping right in
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://tryclojure.org/" rel="noopener noreferrer"&gt;https://tryclojure.org/&lt;/a&gt; is a great intro to the language. It provides a REPL and a tutorial that takes you through the basic features of Clojure.&lt;/p&gt;

&lt;p&gt;Importantly, it forces you to get used to seeing lots of &lt;code&gt;(&lt;/code&gt; and &lt;code&gt;)&lt;/code&gt;!&lt;/p&gt;

&lt;h2&gt;
  
  
  Doing exercises
&lt;/h2&gt;

&lt;p&gt;Exercism provides small coding challenges for a bunch of languages, including &lt;a href="https://exercism.org/tracks/clojure" rel="noopener noreferrer"&gt;Clojure&lt;/a&gt;. Unlike other platforms (&lt;em&gt;cough&lt;/em&gt; leetcode &lt;em&gt;cough&lt;/em&gt;), Exercism is focused on learning and I found it a great way to practice writing Clojure.&lt;/p&gt;

&lt;p&gt;It provides a code editor and evaluates each challenge when you submit. There’s also a way to submit answers locally from your computer, but I found it quicker just to use the website.&lt;/p&gt;

&lt;h2&gt;
  
  
  Editor setup
&lt;/h2&gt;

&lt;p&gt;I ended up setting up Neovim for developing locally. This guide was a great inspiration:&lt;a href="https://endot.org/2023/05/27/vim-clojure-dev-2023/" rel="noopener noreferrer"&gt;https://endot.org/2023/05/27/vim-clojure-dev-2023/&lt;/a&gt;, although I did end up going with something a little bit simpler.&lt;/p&gt;

&lt;p&gt;My .vimrc can be seen &lt;a href="https://github.com/AussieGuy0/dotfiles/blob/e25b8da7c01ea1358723a19ca1319cab4888beff/.vimrc" rel="noopener noreferrer"&gt;here&lt;/a&gt;but probably the most important plugin is &lt;a href="https://github.com/Olical/conjure" rel="noopener noreferrer"&gt;Conjure&lt;/a&gt;, which provides REPL integration in Neovim.&lt;/p&gt;

&lt;p&gt;The REPL is one of the big differences compared to programming in other languages. Basically, you start a REPL in the project directory and then you can evaluate code in your editor in that REPL.&lt;/p&gt;

&lt;p&gt;This basically gives you really short iteration cycles, you can ‘play’ with your code, run tests, reload code in a running app and all without leaving your editor!&lt;/p&gt;

&lt;p&gt;To understand REPL driven development, I really liked this &lt;a href="https://www.youtube.com/watch?v=uBTRLBU-83A" rel="noopener noreferrer"&gt;video with teej_dv and lispyclouds&lt;/a&gt;. One key thing I learnt was using the&lt;code&gt;comment&lt;/code&gt; function to be able to evaluate code without affecting the rest of my program.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;; my super cool function
; given a number, adds 2 to it!
(defn add-2
  [n]
  (+ n 2)
)

; This tells Clojure to ignore what comes next
; but it still has to be syntactically correct!
(comment
  (add-2 3) ; &amp;lt;-- I can evaluate this to check my add-2 function :)
)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By opening a REPL and using the Conjure plugin mentioned before I can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;,eb&lt;/code&gt;: Evaluate the buffer I am in. Kinda like loading up the file I have opened into the REPL.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;,ee&lt;/code&gt;: Evaluate the expression my cursor is under.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;,tc&lt;/code&gt;: Run the test my cursor is over.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;,tn&lt;/code&gt;: Run all tests in current file.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I use the following alias in my &lt;code&gt;.bash_aliases&lt;/code&gt; to easily spin up a REPL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# From https://github.com/Olical/conjure/wiki/Quick-start:-Clojure
# Don't ask me questions about how this works, but it does!

alias cljrepl='clj -Sdeps '\''{:deps {nrepl/nrepl {:mvn/version "1.0.0"} cider/cider-nrepl {:mvn/version "0.42.1"}}}\'\'' \
    --main nrepl.cmdline \
    --middleware '\''["cider.nrepl/cider-middleware"]'\'' \
    --interactive'

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Docs
&lt;/h2&gt;

&lt;p&gt;For docs, I really like &lt;a href="https://clojuredocs.org/" rel="noopener noreferrer"&gt;https://clojuredocs.org/&lt;/a&gt;, which has the docs for the core library. I like the fact that users can submit code examples, which provides better information for each function.&lt;/p&gt;

&lt;h2&gt;
  
  
  Projects
&lt;/h2&gt;

&lt;p&gt;I’ve currently have 2 projects in Clojure to further my learning.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A bad terminal-based clone(ish) of &lt;a href="https://store.steampowered.com/app/2379780/Balatro/" rel="noopener noreferrer"&gt;Balatro&lt;/a&gt;. Balatro is a very addictive deck builder rougelike game. Doing this has been fun and it feels very natural to ‘build up’ over time. The source code can be seen &lt;a href="https://github.com/AussieGuy0/balatro-clj" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;A application that converts a subreddit into an RSS feed. The idea that this can be a webapp that produces daily RSS feeds for a collection of subreddits. &lt;a href="https://github.com/AussieGuy0/reddit-to-rss" rel="noopener noreferrer"&gt;Source code&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The End
&lt;/h2&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

</description>
      <category>clojure</category>
      <category>programming</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Full stack web development in a single Java file: An intro to Javalin and htmx</title>
      <dc:creator>Anthony Bruno</dc:creator>
      <pubDate>Sun, 11 Jun 2023 00:00:00 +0000</pubDate>
      <link>https://dev.to/aussieguy/full-stack-web-development-in-a-single-java-file-an-intro-to-javalin-and-htmx-2ich</link>
      <guid>https://dev.to/aussieguy/full-stack-web-development-in-a-single-java-file-an-intro-to-javalin-and-htmx-2ich</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiblz5krjvhatay3wl6ar.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiblz5krjvhatay3wl6ar.png" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In my programming career, I have used a wide variety of frontend frameworks. From JQuery and Angularjs (not Angular!). To Vue and React.&lt;/p&gt;

&lt;p&gt;A common theme with these was a SPA (Single Page Application) architecture. The server would respond with JSON, the frontend would parse it, do some javascript-y things, and ultimately render as html on the page.&lt;/p&gt;

&lt;p&gt;But this isn’t cool anymore! There has been a trend towards moving rendering to the server, demonstrated by technologies like&lt;a href="https://nextjs.org/" rel="noopener noreferrer"&gt;Next.js&lt;/a&gt; and &lt;a href="https://www.patterns.dev/posts/react-server-components" rel="noopener noreferrer"&gt;React Server Components&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;But did you know that a server can just respond with plain old HTML, without needing to refresh the whole page and not needing a complicated frontend framework to achieve this?&lt;/p&gt;

&lt;p&gt;Enter: &lt;a href="https://htmx.org/" rel="noopener noreferrer"&gt;htmx&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;htmx is a very basic frontend library, that operates based on special &lt;code&gt;hx-*&lt;/code&gt; attributes on HTML elements.&lt;/p&gt;

&lt;p&gt;An example of this is the following (ripped straight off htmx’s homepage):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;hx-post=&lt;/span&gt;&lt;span class="s"&gt;"/clicked"&lt;/span&gt; &lt;span class="na"&gt;hx-swap=&lt;/span&gt;&lt;span class="s"&gt;"outerHTML"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Click Me
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This can be described as: “When this button is clicked, make a POST request to /clicked and replace the button with the HTML response”.&lt;/p&gt;

&lt;p&gt;Basically, all of htmx revolves around:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Waiting for some sort of trigger (e.g. clicking a button, submitting a form, typing in a field)&lt;/li&gt;
&lt;li&gt;Making a request to the server&lt;/li&gt;
&lt;li&gt;Replacing an element on the page with the HTML response.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is a &lt;strong&gt;simple, but powerful paradigm.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It simplifies frontend devlopment, making it easy to learn and maintain, without the need for complex frontend build tools.&lt;/p&gt;

&lt;p&gt;In the blog post, I will describe a Java web app stack using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://j2html.com" rel="noopener noreferrer"&gt;j2html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://javalin.io/" rel="noopener noreferrer"&gt;Javalin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://htmx.org/" rel="noopener noreferrer"&gt;htmx&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;to enable fast and simple web app development. I will explain what each part of the stack does, and how we can put it all together to build a simple counter app in a single Java file!&lt;/p&gt;

&lt;h2&gt;
  
  
  Dependencies
&lt;/h2&gt;

&lt;p&gt;If you are using Maven, here’s the list of dependencies that you can chuck in your &lt;code&gt;pom.xml&lt;/code&gt; file. Don’t worry, this blog post will explain what each of them does!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Place the below in the &amp;lt;dependencies&amp;gt; section of your pom.xml --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;com.j2html&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;j2html&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;1.6.0&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;io.javalin&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;javalin&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;5.5.0&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.webjars.npm&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;htmx.org&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;1.9.2&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!-- Defining a logger as Javalin will complain if there is no SL4J logger --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.slf4j&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;slf4j-api&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;2.0.5&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.slf4j&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;slf4j-reload4j&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;2.0.5&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Server side HTML with j2html
&lt;/h2&gt;

&lt;p&gt;A way to generate HTML in Java is to use a templating engine like&lt;a href="https://www.thymeleaf.org/" rel="noopener noreferrer"&gt;Thymeleaf&lt;/a&gt;. However, this means the template files are outside Java, and as the blog title suggests, we want everything in Java!&lt;/p&gt;

&lt;p&gt;A nice alternative to a templating engine is &lt;strong&gt;j2html&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;j2html is a Java library that allows us to build HTML in a fluent and typesafe manner. If you know HTML, you know j2html!&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="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;static&lt;/span&gt; &lt;span class="n"&gt;j2html&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;TagCreator&lt;/span&gt;&lt;span class="o"&gt;.*;&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;Main&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Fluently build a HTML structure.&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
      &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello World!"&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="c1"&gt;// Let's render that HTML!&lt;/span&gt;
    &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;render&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;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&amp;lt;body&amp;gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Hello world&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let’s serve that html through a sever. We can do that using &lt;strong&gt;Javalin&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Handling requests with Javalin
&lt;/h2&gt;

&lt;p&gt;According to &lt;a href="https://javalin.io/" rel="noopener noreferrer"&gt;https://javalin.io/&lt;/a&gt;, Javalin is a simple web framework for Java and Kotlin. I agree!&lt;/p&gt;

&lt;p&gt;I feel like it is very similar to the &lt;a href="https://expressjs.com/" rel="noopener noreferrer"&gt;Express&lt;/a&gt; framework for Node.js. For instance, the following Express code:&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="c1"&gt;// Using Express as an example.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&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;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&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;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&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="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&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;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello World!&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="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Is the same as the following Javalin code:&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="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;io.javalin.Javalin&lt;/span&gt;&lt;span class="o"&gt;;&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;Main&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Javalin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;create&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;result&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello World"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;start&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;Now let’s combine j2html and Javalin. We can use Javalin’s &lt;code&gt;Context#html&lt;/code&gt; to allow the server to respond with HTML.&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="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;io.javalin.Javalin&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;static&lt;/span&gt; &lt;span class="n"&gt;j2html&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;TagCreator&lt;/span&gt;&lt;span class="o"&gt;.*;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Create a new Javalin instance.&lt;/span&gt;
  &lt;span class="c1"&gt;// By default it will run on port 8080, but can be changed.&lt;/span&gt;
  &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;javalin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Javalin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;create&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

  &lt;span class="c1"&gt;// Handle a GET request to the path "/".&lt;/span&gt;
  &lt;span class="n"&gt;javalin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Build the HTML, and render it.&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
              &lt;span class="n"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello world"&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="c1"&gt;// We prefix with the doctype to ensure the browser does not use quirks mode.&lt;/span&gt;
    &lt;span class="c1"&gt;// https://developer.mozilla.org/en-US/docs/Web/HTML/Quirks_Mode_and_Standards_Mode&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;rendered&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"&amp;lt;!DOCTYPE html&amp;gt;\n"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;render&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// Return the html in the response.&lt;/span&gt;
    &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;html&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rendered&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="o"&gt;});&lt;/span&gt;

  &lt;span class="n"&gt;javalin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;start&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;If we run this, we will see some output in the console.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; INFO [main] (JavalinLogger.kt:16) - Listening on http://localhost:8080/
 INFO [main] (JavalinLogger.kt:16) - You are running Javalin 5.5.0 (released May 1, 2023).
 INFO [main] (JavalinLogger.kt:16) - Javalin started in 273ms \o/

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you see the “Javalin” started command, we can put in the url &lt;code&gt;http://localhost:8080&lt;/code&gt; into a browser. This should show something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc4mw31csnf4qjs581jrc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc4mw31csnf4qjs581jrc.png" width="800" height="383"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Isn’t it beautiful?&lt;/p&gt;

&lt;h2&gt;
  
  
  Interactivity with htmx
&lt;/h2&gt;

&lt;p&gt;Lastly, lets add some interactivity with htmx!&lt;/p&gt;

&lt;p&gt;To add htmx to our project, we can add it as a &lt;a href="https://www.webjars.org/" rel="noopener noreferrer"&gt;WebJar&lt;/a&gt;. A WebJar is basically just a way to manage Javascript dependencies using standard Java build tools, like Maven or Gradle.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Was in the dependencies at the top of this blog post, but putting
     here in case you forgot! --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.webjars.npm&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;htmx.org&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;1.9.2&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To use this, we need to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Enable WebJar support in Javalin.&lt;/li&gt;
&lt;li&gt;Include it in our &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; element of our HTML.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;javalin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Javalin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;create&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Enable WebJar support.&lt;/span&gt;
    &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;staticFiles&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;enableWebJars&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
  &lt;span class="o"&gt;});&lt;/span&gt;

  &lt;span class="n"&gt;javalin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
              &lt;span class="c1"&gt;// The WebJars path follows the format:&lt;/span&gt;
              &lt;span class="c1"&gt;// /webjars/&amp;lt;artifactId&amp;gt;/&amp;lt;version&amp;gt;/&amp;lt;path-to-file&amp;gt;&lt;/span&gt;
              &lt;span class="c1"&gt;// We can find the &amp;lt;path-to-file&amp;gt; via npmjs.com 'Code' view.&lt;/span&gt;
              &lt;span class="c1"&gt;// For instance: https://www.npmjs.com/package/htmx.org?activeTab=code&lt;/span&gt;
              &lt;span class="n"&gt;script&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;withSrc&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/webjars/htmx.org/1.9.2/dist/htmx.min.js"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
              &lt;span class="n"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello world"&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="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;rendered&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"&amp;lt;!DOCTYPE html&amp;gt;\n"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;render&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

    &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;html&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rendered&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="o"&gt;});&lt;/span&gt;

  &lt;span class="n"&gt;javalin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;start&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;Now, let’s start actually using htmx! For this example, we’ll create a simple counter app. It will show a number, that can be incremented by pressing a button.&lt;/p&gt;

&lt;p&gt;Firstly, let’s create a method that produces the HTML for the count. This will make a bit more sense later on.&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="c1"&gt;// Create a H2 tag with an id.&lt;/span&gt;
  &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;H2Tag&lt;/span&gt; &lt;span class="nf"&gt;createCounterElement&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;count&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="nf"&gt;h2&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"count: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;withId&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"counter"&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;Next, we need a way to store the count on the server. The easiest way is to use an &lt;code&gt;AtomicInteger&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We can use this count and the &lt;code&gt;createCounter&lt;/code&gt; method we created before in the handler we have:&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="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;count&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;AtomicInteger&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;javalin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
          &lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
              &lt;span class="n"&gt;script&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;withSrc&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/webjars/htmx.org/1.9.2/dist/htmx.min.js"&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="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                  &lt;span class="n"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello world"&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
                  &lt;span class="n"&gt;createCounterElement&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&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;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;rendered&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"&amp;lt;!DOCTYPE html&amp;gt;\n"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;render&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
      &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;html&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rendered&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;We then need a way for the server to increment this counter. We can do this by defining a new handler on our server.&lt;/p&gt;

&lt;p&gt;Let’s make it accept &lt;code&gt;POST&lt;/code&gt; requests on the path &lt;code&gt;/increment&lt;/code&gt;. It will increment the count on the server and return only the html for the counter element. This is where that &lt;code&gt;createCounterElement&lt;/code&gt; method is useful!&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="n"&gt;javalin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;post&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/increment"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;newCounter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;createCounterElement&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;incrementAndGet&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
      &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;html&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;newCounter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;render&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;Lastly, and most importantly, we now use htmx to call this &lt;code&gt;increment&lt;/code&gt; handler, and swap out the relevant counter element on the screen.&lt;/p&gt;

&lt;p&gt;To do so, we can define a button with special &lt;code&gt;hx-*&lt;/code&gt; attributes like so:&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="n"&gt;button&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Increment"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;attr&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"hx-post"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"/increment"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;attr&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"hx-target"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"#counter"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;attr&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"hx-swap"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"outerHTML"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To explain each attribute:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://htmx.org/attributes/hx-post/" rel="noopener noreferrer"&gt;hx-post&lt;/a&gt;: When clicked, make a &lt;code&gt;POST&lt;/code&gt; request to the &lt;code&gt;/increment&lt;/code&gt; path.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://htmx.org/attributes/hx-target/" rel="noopener noreferrer"&gt;hx-target&lt;/a&gt;: Swap the element with the id &lt;code&gt;counter&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://htmx.org/attributes/hx-swap/" rel="noopener noreferrer"&gt;hx-swap&lt;/a&gt;: Using &lt;code&gt;outerHTML&lt;/code&gt; means htmx will swap the entire html of the counter element.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Putting all the code we have together, we should have something that looks like the following:&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="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;javalin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Javalin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;create&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
          &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;staticFiles&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;enableWebjars&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="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;counter&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;AtomicInteger&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;javalin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
          &lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
              &lt;span class="n"&gt;script&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;withSrc&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/webjars/htmx.org/1.9.2/dist/htmx.min.js"&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="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                  &lt;span class="n"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello world"&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
                  &lt;span class="n"&gt;createCounter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;()),&lt;/span&gt;
                  &lt;span class="n"&gt;button&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Increment"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                      &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;attr&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"hx-post"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"/increment"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                      &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;attr&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"hx-swap"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"outerHTML"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                      &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;attr&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"hx-target"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"#counter"&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;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;rendered&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"&amp;lt;!DOCTYPE html&amp;gt;\n"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;render&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
      &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;html&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rendered&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;});&lt;/span&gt;

    &lt;span class="n"&gt;javalin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;post&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/increment"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;newCounter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;createCounter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;incrementAndGet&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
      &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;html&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;newCounter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;render&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="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;H2Tag&lt;/span&gt; &lt;span class="nf"&gt;createCounterElement&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;count&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="nf"&gt;h2&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"count: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;withId&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"counter"&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;If we run the code, we should see something like the following:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvfcgs44q0msn8d0l1veb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvfcgs44q0msn8d0l1veb.png" width="800" height="249"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now press ‘increment’ and see what happens!&lt;/p&gt;

&lt;p&gt;(Spoilers: the number should increment!)&lt;/p&gt;

&lt;p&gt;If we have the network tab open, we can see the request to &lt;code&gt;/increment&lt;/code&gt;, with the html being returned.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff4hl7r0svhfgcdfu1nan.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff4hl7r0svhfgcdfu1nan.png" width="800" height="338"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The counter will persist even if you refresh the page, as the number is stored on the server!&lt;/p&gt;

&lt;h2&gt;
  
  
  The End?
&lt;/h2&gt;

&lt;p&gt;I hope you have enjoyed learning a bit about Javalin, j2html and htmx!&lt;/p&gt;

&lt;p&gt;If you want to see see an example of a todo app using Javalin, you can have a look at this github repository: &lt;a href="https://github.com/AussieGuy0/java-htmx-todo/" rel="noopener noreferrer"&gt;java-htmx-todo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqgkfkg0cxe878hehvnae.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqgkfkg0cxe878hehvnae.png" width="800" height="317"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>java</category>
      <category>html</category>
    </item>
    <item>
      <title>Migrating a classic Jekyll GitHub Pages site to GitHub actions</title>
      <dc:creator>Anthony Bruno</dc:creator>
      <pubDate>Mon, 15 May 2023 00:00:00 +0000</pubDate>
      <link>https://dev.to/aussieguy/migrating-a-classic-github-pages-site-to-github-actions-3269</link>
      <guid>https://dev.to/aussieguy/migrating-a-classic-github-pages-site-to-github-actions-3269</guid>
      <description>&lt;p&gt;I’ve had this site (&lt;a href="https://anthonybruno.dev/" rel="noopener noreferrer"&gt;https://anthonybruno.dev/&lt;/a&gt;) running inside &lt;a href="https://pages.github.com/" rel="noopener noreferrer"&gt;Github Pages&lt;/a&gt; for a long time now without many issues. Under the hood, it uses a ruby-based static site generator called &lt;a href="https://jekyllrb.com/" rel="noopener noreferrer"&gt;Jekyll&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;However, something that I have noticed is that you don’t have much control over what Jekyll and ruby version is used. This seems to be getting a little bit out of date as time goes on. GitHub lists the dependencies on &lt;a href="https://pages.github.com/versions/" rel="noopener noreferrer"&gt;this page&lt;/a&gt;. At time of writing, it uses Jekyll 3.9.3 (latest version is 4.3.2), and ruby 2.7.4 (latest version is 3.2.2).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffyhpjqvr7qln0xmted79.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffyhpjqvr7qln0xmted79.png" width="800" height="653"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Additionally, GitHub restricts what Jekyll plugins you can use and actually enables certain plugins that can’t be disabled. For instance, it brings in &lt;code&gt;jekyll-coffeescript&lt;/code&gt;… which is used to convert coffeescript…even though my site doesn’t have any coffeescript (it’s 2023!).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft3gdb8njelmlbtpi2nkd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft3gdb8njelmlbtpi2nkd.png" width="636" height="316"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For these reasons, I looked into alternatives, and I found out that you can use GitHub actions to deploy a site!&lt;/p&gt;

&lt;p&gt;I couldn’t find a nice guide on how to do this, so after working things out, I decided to write this guide.&lt;/p&gt;

&lt;p&gt;It’s pretty straightforward, we only really need to do 2 things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Adjust the repository settings to use GitHub actions for site deployments.&lt;/li&gt;
&lt;li&gt;Add a single YAML file to define how GitHub will build and deploy the site.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Steps
&lt;/h1&gt;

&lt;h2&gt;
  
  
  1. Repository Settings
&lt;/h2&gt;

&lt;p&gt;Firstly, we need toggle the deployment setting from the ‘default’ GitHub pages deploy to GitHub actions.&lt;/p&gt;

&lt;p&gt;We can do this via Settings -&amp;gt; Pages. We just need to change the ‘Source’ as shown in the screenshot below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5lfk2vrvjglza7lcs8ha.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5lfk2vrvjglza7lcs8ha.png" width="800" height="439"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note that this won’t really do anything, until we do the next step!&lt;/p&gt;

&lt;h2&gt;
  
  
  2. GitHub Actions Workflow
&lt;/h2&gt;

&lt;p&gt;The workflow is how we tell GitHub how to build and deploy the site. You can read a bit more about workflows in the &lt;a href="https://docs.github.com/en/actions/using-workflows/about-workflows" rel="noopener noreferrer"&gt;GitHub docs&lt;/a&gt;(there’s a bunch more cool things you can do with workflows!)&lt;/p&gt;

&lt;p&gt;To start, we need to define a YAML file in the path &lt;code&gt;&amp;lt;repo-root&amp;gt;/.github/workflows/&amp;lt;workflow-name&amp;gt;.yml&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;We can call the workflow file anything. I just went with the very creative name: &lt;code&gt;jekyll.yml&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The contents of the file should look something like the below. For those interested, I will explain it further down below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Jekyll Build and Deploy&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v3&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ruby/setup-ruby@v1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;ruby-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;2.7.4'&lt;/span&gt;
          &lt;span class="na"&gt;bundler-cache&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="c1"&gt;# runs 'bundle install' and caches installed gems automatically&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bundle exec jekyll build&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/upload-pages-artifact@v1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;_site/"&lt;/span&gt;

  &lt;span class="na"&gt;deploy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Add a dependency to the build job&lt;/span&gt;
    &lt;span class="na"&gt;needs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;build&lt;/span&gt;
    &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;github.ref == 'refs/heads/master'&lt;/span&gt; &lt;span class="c1"&gt;# Only deploys on master&lt;/span&gt;

    &lt;span class="c1"&gt;# Grant GITHUB_TOKEN the permissions required to make a Pages deployment&lt;/span&gt;
    &lt;span class="na"&gt;permissions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;pages&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&lt;/span&gt; &lt;span class="c1"&gt;# to deploy to Pages&lt;/span&gt;
      &lt;span class="na"&gt;id-token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&lt;/span&gt; &lt;span class="c1"&gt;# to verify the deployment originates from an appropriate source&lt;/span&gt;

    &lt;span class="c1"&gt;# Deploy to the github-pages environment&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;github-pages&lt;/span&gt;
      &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ steps.deployment.outputs.page_url }}&lt;/span&gt;

    &lt;span class="c1"&gt;# Specify runner + deployment step&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy to GitHub Pages&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;deployment&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/deploy-pages@v2&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Side-note: this requires a &lt;code&gt;Gemfile&lt;/code&gt; to be defined in the repository root. I’m not sure if my one was created when I first set up the GitHub pages (many years ago!), or I added it afterwards. In case you don’t have one, here’s mine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;source 'https://rubygems.org'
gem 'github-pages', group: :jekyll_plugins
gem 'jekyll-seo-tag'
gem 'rouge'
gem 'jekyll-feed'

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Explaining the workflow
&lt;/h3&gt;

&lt;p&gt;I’ll break it down section by section:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Jekyll Build and Deploy&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The name of the workflow, which is shown in GitHub’s UI.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Indicates that the workflow will run on any push to the GitHub repository. This includes commits in PRs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v3&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ruby/setup-ruby@v1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;ruby-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;2.7.4'&lt;/span&gt;
          &lt;span class="na"&gt;bundler-cache&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="c1"&gt;# runs 'bundle install' and caches installed gems automatically&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bundle exec jekyll build&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/upload-pages-artifact@v1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;_site/"&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The build job will:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Check out the repository (&lt;code&gt;actions/checkout@v3&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Set up ruby with the specified version. This step will also run &lt;code&gt;bundle install&lt;/code&gt; for us! (&lt;code&gt;ruby/setup-ruby@v1&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;bundle exec jekyll build&lt;/code&gt;. This runs Jekyll and produces the generated site in the folder &lt;code&gt;_site/&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Finally, uploads the generated site using &lt;code&gt;actions/upload-page-artifacts@1&lt;/code&gt;, which is a requirement to deploy the site.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;  &lt;span class="na"&gt;deploy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Add a dependency to the build job&lt;/span&gt;
    &lt;span class="na"&gt;needs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;build&lt;/span&gt;
    &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;github.ref == 'refs/heads/master'&lt;/span&gt; &lt;span class="c1"&gt;# Only deploys on master&lt;/span&gt;

    &lt;span class="c1"&gt;# Grant GITHUB_TOKEN the permissions required to make a Pages deployment&lt;/span&gt;
    &lt;span class="na"&gt;permissions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;pages&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&lt;/span&gt; &lt;span class="c1"&gt;# to deploy to Pages&lt;/span&gt;
      &lt;span class="na"&gt;id-token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&lt;/span&gt; &lt;span class="c1"&gt;# to verify the deployment originates from an appropriate source&lt;/span&gt;

    &lt;span class="c1"&gt;# Deploy to the github-pages environment&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;github-pages&lt;/span&gt;
      &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ steps.deployment.outputs.page_url }}&lt;/span&gt;

    &lt;span class="c1"&gt;# Specify runner + deployment step&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy to GitHub Pages&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;deployment&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/deploy-pages@v2&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It’s important to note that the deploy job:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Only runs after the build job is done.&lt;/li&gt;
&lt;li&gt;Will only run on &lt;code&gt;master&lt;/code&gt;, which is my repository’s default branch. Newer repositories will have &lt;code&gt;main&lt;/code&gt; as their default branch.&lt;/li&gt;
&lt;li&gt;Has suitable permissions to deploy to GitHub Pages.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The only step that this job has is: &lt;code&gt;actions/deploy-pages@v2&lt;/code&gt;. This deploys the site that we uploaded in the build step with &lt;code&gt;actions/upload-pages-artifact@v1&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Success!
&lt;/h2&gt;

&lt;p&gt;When you next push to your default branch, you should see the workflow running in the actions page of your repository.&lt;/p&gt;

&lt;p&gt;Here is an example of mine:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn0jqa0c5gdpt79ntczln.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn0jqa0c5gdpt79ntczln.png" width="800" height="550"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And the fact that you can read this page, means that the workflow is deploying the site. Yay!&lt;/p&gt;

&lt;p&gt;Now, you can run any version of ruby and Jekyll you want, use any plugin you want, and I can finally get rid of that weird coffeescript plugin. Double yay!&lt;/p&gt;

&lt;p&gt;For reference, please take a look at &lt;a href="https://github.com/AussieGuy0/AussieGuy0.github.io/pull/57" rel="noopener noreferrer"&gt;my PR&lt;/a&gt;, which converted this site to use Github Actions.&lt;/p&gt;

</description>
      <category>github</category>
      <category>guide</category>
    </item>
    <item>
      <title>Common Java patterns in Kotlin</title>
      <dc:creator>Anthony Bruno</dc:creator>
      <pubDate>Sun, 09 Aug 2020 00:00:00 +0000</pubDate>
      <link>https://dev.to/aussieguy/common-java-patterns-in-kotlin-342j</link>
      <guid>https://dev.to/aussieguy/common-java-patterns-in-kotlin-342j</guid>
      <description>&lt;p&gt;Recently, I’ve been using Kotlin for a project at work. As someone coming from a Java background, I’ve been taking notes on certain patterns that are used in Java, that can be done nicer in Kotlin. I feel like when using a new language, it’s easy to fall into the trap of writing non-idiomatic code simply because it’s what I would’ve done in another language.&lt;/p&gt;

&lt;p&gt;I wrote this article with the idea that this is what I would’ve wanted when starting with Kotlin, and I plan on updating it as I learn more techniques. Anyway, let’s begin!&lt;/p&gt;

&lt;h2&gt;
  
  
  Multi-line Strings
&lt;/h2&gt;

&lt;p&gt;Sometimes, it is nice to embed SQL or have HTML snippets in our application. In these cases, we want to be able to have a &lt;code&gt;String&lt;/code&gt; that spans multiple lines. If we had it on a single line, it would be near impossible to read!&lt;/p&gt;

&lt;h3&gt;
  
  
  Java
&lt;/h3&gt;

&lt;p&gt;In Java 11 and below, we have to resort to simple &lt;code&gt;String&lt;/code&gt; &lt;code&gt;+&lt;/code&gt; concatenation. Make sure you don’t forget to add new line endings &lt;code&gt;\n&lt;/code&gt; or else when the String is built, it will all end upon one line!&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="c1"&gt;// Java 11 and older&lt;/span&gt;
&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"SELECT w.id, w.title, w.date, we.weight, e.name\n"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
        &lt;span class="s"&gt;"FROM workouts as w\n"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
        &lt;span class="s"&gt;"LEFT JOIN workout_exercises as we ON w.id = we.workout_id\n"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
        &lt;span class="s"&gt;"LEFT JOIN exercises as e on we.exercise_id = e.id\n"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
        &lt;span class="s"&gt;"WHERE w.user_id = ?"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, starting from Java 13, we have a much nicer way of writing 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="c1"&gt;// Java 13 and above&lt;/span&gt;
&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"""
        SELECT w.id, w.title, w.date, we.weight, e.name
        FROM workouts as w
        LEFT JOIN workout_exercises as we ON w.id = we.workout_id
        LEFT JOIN exercises as e on we.exercise_id = e.id
        WHERE w.user_id = ?
        """&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is an example of a &lt;a href="https://openjdk.java.net/jeps/378" rel="noopener noreferrer"&gt;Text Block&lt;/a&gt;, which is a preview feature in Java 13 and 14. At the time of writing, this feature will be finalised in Java 15.&lt;/p&gt;

&lt;h3&gt;
  
  
  Kotlin
&lt;/h3&gt;

&lt;p&gt;For Kotlin, the syntax is similar to what is available in Java 13+.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;query&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"""
    SELECT w.id, w.title, w.date, we.weight, e.name
    FROM workouts as w
    LEFT JOIN workout_exercises as we ON w.id = we.workout_id
    LEFT JOIN exercises as e on we.exercise_id = e.id
    WHERE w.user_id = ?
"""&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trimIndent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You might be asking why we have to call the &lt;code&gt;trimIndent&lt;/code&gt; function at the end.This is because if we don’t, Kotlin will construct the &lt;code&gt;String&lt;/code&gt; including the initial whitespace indentation on each line. As we are only inserting that indentation for readability purposes, we have to call &lt;code&gt;trimIndent&lt;/code&gt; which will remove this initial whitespace from each line.&lt;/p&gt;

&lt;p&gt;I think this is a case where the Java way of Text Blocks is a bit better, as it will automatically trim the whitespace for us. However, Kotlin is &lt;strong&gt;here now&lt;/strong&gt; and (at the time of writing) Java 15 is still a month or so away!&lt;/p&gt;

&lt;h2&gt;
  
  
  String Concatenation
&lt;/h2&gt;

&lt;p&gt;Another common thing we like to do with &lt;code&gt;String&lt;/code&gt;s is to construct them with variables. For instance, we receive some input from the user and we want to create a message based on that input.&lt;/p&gt;

&lt;h3&gt;
  
  
  Java
&lt;/h3&gt;

&lt;p&gt;Unfortunately, Java does not have a nice, modern way to do this and we have to resort to simply using &lt;code&gt;+&lt;/code&gt; to build our String.&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;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"bob"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"My name is "&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="s"&gt;" and my age is"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We do have other options that are useful in certain situations, such as &lt;a href="https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/StringBuilder.html" rel="noopener noreferrer"&gt;StringBuilder&lt;/a&gt; and &lt;a href="https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/String.html#format(java.lang.String,java.lang.Object...)" rel="noopener noreferrer"&gt;String#format&lt;/a&gt;. But for simple, straight forward situations, we can only use &lt;code&gt;+&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Kotlin
&lt;/h3&gt;

&lt;p&gt;In Kotlin, we can use template expressions inside a &lt;code&gt;String&lt;/code&gt;. This greatly improves readability when a &lt;code&gt;String&lt;/code&gt; is concatenated with multiple values.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"bob"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;age&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;message&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"My name is $name and my age is $age"&lt;/span&gt;

&lt;span class="c1"&gt;// Can also use ${expression} for more complex usages&lt;/span&gt;
&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;message&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"My name is $name and my age in 10 years will be ${age + 10}"&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Static Utility Methods
&lt;/h2&gt;

&lt;p&gt;When we want utility methods that we want to use without having create a new Object, it is common practice to add them as static methods on a class.&lt;/p&gt;

&lt;p&gt;Frequently, ‘Util’ classes exist that only contain static methods. This is a pattern employed by popular libraries like &lt;a href="https://github.com/google/guava" rel="noopener noreferrer"&gt;GoogleGuava&lt;/a&gt; and &lt;a href="https://github.com/apache/commons-lang" rel="noopener noreferrer"&gt;ApacheCommons&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Java
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;StringUtils&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="nf"&gt;getLastLetter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isEmpty&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;IllegalArgumentException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Provided string must not be empty"&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;str&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;charAt&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="o"&gt;()&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="o"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;StringUtils&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getLastLetter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"abc"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// =&amp;gt; c&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Kotlin
&lt;/h3&gt;

&lt;p&gt;In Kotlin, we have a few options.&lt;/p&gt;

&lt;p&gt;Firstly, we can have a top-level function. That is, a function that is not attached to a class. This language feature does not exist in Java.&lt;/p&gt;

&lt;p&gt;We can call the function from anywhere we want, without needing to create a new object, or prefix a class name in front of the function call.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Using a top-level function&lt;/span&gt;

&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;getLastLetter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;Char&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isEmpty&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nc"&gt;IllegalArgumentException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Provided string must not be empty"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;getLastLetter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"abc"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// =&amp;gt; c&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we can add a method to an &lt;code&gt;object&lt;/code&gt;. This is roughly equivalent to the static method way we saw in Java, and the calling code is the same.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Using an Object&lt;/span&gt;
&lt;span class="c1"&gt;// https://kotlinlang.org/docs/tutorials/kotlin-for-py/objects-and-companion-objects.html&lt;/span&gt;
&lt;span class="kd"&gt;object&lt;/span&gt; &lt;span class="nc"&gt;StringUtils&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;getLastLetter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;Char&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isEmpty&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nc"&gt;IllegalArgumentException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Provided string must not be empty"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&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="nc"&gt;StringUtils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getLastLetter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"abc"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// =&amp;gt; c&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, we have an extension function. This is a cool feature that allows us to attach a method to an existing class, without the need of creating a subclass or a new wrapped type!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Using an extension function&lt;/span&gt;
&lt;span class="c1"&gt;// https://kotlinlang.org/docs/reference/extensions.html&lt;/span&gt;
&lt;span class="c1"&gt;// Preferred!&lt;/span&gt;
&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getLastLetter&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;Char&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isEmpty&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nc"&gt;IllegalArgumentException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Provided string must not be empty"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="s"&gt;"abc"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getLastLetter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// =&amp;gt; c&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This extension function feature was one the initial features I saw when looking at Kotiln where I thought that it was really useful!&lt;/p&gt;

&lt;h2&gt;
  
  
  Singletons
&lt;/h2&gt;

&lt;p&gt;In some cases, we want to be able to define and use &lt;a href="https://en.wikipedia.org/wiki/Singleton_pattern" rel="noopener noreferrer"&gt;singleton’s&lt;/a&gt; in our code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Java
&lt;/h3&gt;

&lt;p&gt;With Java, we can do this by creating a class with a private constructor. The class then provides a public static field that can be accessed from calling code.&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="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BeanFactory&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;BeanFactory&lt;/span&gt; &lt;span class="no"&gt;INSTANCE&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;BeanFactory&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nf"&gt;BeanFactory&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Prevent outside world creating a new BeanFactory&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Beans&lt;/span&gt; &lt;span class="nf"&gt;createBakedBeans&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="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;BakedBeans&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;h3&gt;
  
  
  Kotlin
&lt;/h3&gt;

&lt;p&gt;In Kotlin, we greatly reduce boilerplate code by simply defining a new &lt;code&gt;object&lt;/code&gt;type.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;object&lt;/span&gt; &lt;span class="nc"&gt;BeanFactory&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;createBakedBeans&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;Beans&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;BakedBeans&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;For more information about &lt;code&gt;object&lt;/code&gt;, please read &lt;a href="https://kotlinlang.org/docs/reference/object-declarations.html" rel="noopener noreferrer"&gt;the relevant docs&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I’ve covered how to write common Java techniques in idiomatic Kotlin. Often, the equivalent Kotlin code is shorter and more readable.&lt;/p&gt;

&lt;p&gt;My advice for Java developers starting with Kotlin: &lt;strong&gt;always be learning!&lt;/strong&gt; If you find yourself encountering a new problem in Kotlin and you solve it by writing Java-ish code, slow down and see if there’s a better way to do it in Kotlin.Have a search on Google or talk to your favourite coworker about it.This way, you will continuously learn best practices while still being productive!&lt;/p&gt;

</description>
      <category>java</category>
      <category>kotlin</category>
    </item>
    <item>
      <title>My time at DDDAdelaide 2019</title>
      <dc:creator>Anthony Bruno</dc:creator>
      <pubDate>Thu, 09 Jan 2020 00:00:00 +0000</pubDate>
      <link>https://dev.to/aussieguy/my-time-at-dddadelaide-2019-1g15</link>
      <guid>https://dev.to/aussieguy/my-time-at-dddadelaide-2019-1g15</guid>
      <description>&lt;p&gt;&lt;a href="https://dddadelaide.com" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftw7r5aaqh6xamolt3w1u.png" alt="DDD Logo" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Recently (yes, I say recently even though it happened last year!) I attended the very first edition of DDDAdelaide. It’s awesome finally seeing Adelaide getting a software development conference. It was really well put together, and I had a great time. I would highly recommend anyone going to the next one!&lt;/p&gt;

&lt;p&gt;This article covers my key takeaways from some of the talks I saw. I’ve also included each presenter’s Twitter and a link to the slides where possible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Shifting Left: DevSecOps as an Approach to Building Secure Products
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://twitter.com/JakobTheDev" rel="noopener noreferrer"&gt;Jakob Pennington&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Fantastic talk about moving security testing from near/after the release stage, to the development stage. As a programmer by trade, I know security is important but it sometimes feels like it is left behind a bit in the engineering process. The suggestion to add security testing as part of automated CI/CD is definitely something I want to explore doing.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Recommendation to have a separate environment for security testing&lt;/li&gt;
&lt;li&gt;Security tools: Burp Suite (expensive!), Owasp Zap (free!)&lt;/li&gt;
&lt;li&gt;Tools to help manage dependencies: Snyk, Dependabot&lt;/li&gt;
&lt;li&gt;‘Sans Appsec’ as a resource for application security&lt;/li&gt;
&lt;li&gt;Guidelines: Security shouldn’t get in devs way and track security defects tracked as tickets&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  GraphQL, gRPC or REST? Resolving the API Developer’s Dilemma
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://twitter.com/robcrowley" rel="noopener noreferrer"&gt;Rob Crowley&lt;/a&gt; - &lt;a href="https://speakerdeck.com/robcrowley/graphql-grpc-or-rest-resolving-the-api-developers-dilemma" rel="noopener noreferrer"&gt;Slides&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Rob initially goes into the history of API technology, with some funny commentary on how we think the newest thing that comes out is the ‘best’ (&lt;em&gt;‘SOAP is dead, long live REST’&lt;/em&gt; to &lt;em&gt;‘REST is dead long live GraphQL’&lt;/em&gt;)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;REST is generally a good choice for starting an API&lt;/li&gt;
&lt;li&gt;GraphQL is not the best choice for server to server communication&lt;/li&gt;
&lt;li&gt;There exists some challenges regarding caching with GraphQL&lt;/li&gt;
&lt;li&gt;The speed of a GraphQL response is limited by the slowest field&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;GraphQL eliminates the need for versioning&lt;/em&gt; - we didn’t need versioning in other API types either! 

&lt;ul&gt;
&lt;li&gt;We should strive for ‘Graceful Evolution’. (e.g. Don’t add required inputs/don’t remove outputs/don’t change type of field/follow Robustness Principle)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Deprecations are still hard, even with GraphQL&lt;/li&gt;

&lt;li&gt;Integration Pattern - Martin Fowler&lt;/li&gt;

&lt;li&gt;Recommendations: 

&lt;ul&gt;
&lt;li&gt;REST: Most of your API is CRUD&lt;/li&gt;
&lt;li&gt;GraphQL: Excels with multiple clients with Heterogeneous data requirements&lt;/li&gt;
&lt;li&gt;GRPC: Good for synchronous comms between microservices&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Need to look into GRPC more!&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Main takeaway:&lt;/strong&gt; There is no universal best API style, but there is always a best API style for you problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Modern Authentication 101
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://dasith.me/" rel="noopener noreferrer"&gt;Dasith Wijesiriwardena&lt;/a&gt; - &lt;a href="https://www.slideshare.net/DasithWijesiriwarden/ddd-melbourne-2019-modern-authentication-101-161977250" rel="noopener noreferrer"&gt;Slides&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A nice overview of how to handle authentication. Dasith provided an in-depth description on the problems with the classic model of authentication, and described modern alternatives.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Really nice flow chart on what OAuth flow you should use, depending on the device, what type of app it is, etc.&lt;/li&gt;
&lt;li&gt;Can see myself going back to the slides for reference!&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  TypeScript: Beyond 101
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://twitter.com/jaimefebres" rel="noopener noreferrer"&gt;Jaime Febres&lt;/a&gt; - &lt;a href="https://github.com/emiaj/AdvancedTypescript-Adelaide" rel="noopener noreferrer"&gt;Source Code&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As a Java guy, TypeScript is something that really resonates with me. I’m always eager to hear more about it!&lt;/p&gt;

&lt;p&gt;Jaime showed some cool things that are achievable in TypeScript. The &lt;code&gt;keyof&lt;/code&gt;feature was something that found immediate use for me for a project I have at home.&lt;/p&gt;

&lt;p&gt;The speaker also had a good sense of humor, with a couple of digs at JavaScript’s ‘type’ system.&lt;/p&gt;

&lt;h2&gt;
  
  
  Making React Apps Accessible: It’s easier than you think
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://twitter.com/jessbudd4" rel="noopener noreferrer"&gt;Jess Bud&lt;/a&gt; - &lt;a href="https://noti.st/jessbudd/UUp8f2" rel="noopener noreferrer"&gt;Slides&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Like security, I feel like accessibility is one of those things that are an after thought in web dev. Jess brings some stats to show that things shouldn’t be that way!&lt;/p&gt;

&lt;p&gt;What I like about this talk, is while there was a focus on React, the techniques shown can be applied to any front end framework. Also, I’ll always love a web dev talk that promotes the use of semantic HTML!&lt;/p&gt;

</description>
      <category>conference</category>
      <category>typescript</category>
      <category>graphql</category>
    </item>
    <item>
      <title>Add RSS to GitHub Pages and link it to Dev.to</title>
      <dc:creator>Anthony Bruno</dc:creator>
      <pubDate>Sun, 20 Oct 2019 00:00:00 +0000</pubDate>
      <link>https://dev.to/aussieguy/add-rss-to-github-pages-and-link-it-to-dev-to-16mo</link>
      <guid>https://dev.to/aussieguy/add-rss-to-github-pages-and-link-it-to-dev-to-16mo</guid>
      <description>&lt;p&gt;I’ve been posting to &lt;a href="https://dev.to"&gt;Dev.to&lt;/a&gt; for a little while now. I’ve always posted to my website first, then more or less copy and pasted the markdown into the Dev.to editor. I thought there must be a better way, and luckily stumbled upon a setting that allows you to automatically link blog posts from GitHub Pages (or any RSS feed) to Dev.to!&lt;/p&gt;

&lt;p&gt;We’ll go through the steps of enabling RSS on a GitHub pages site, and then we’ll link it up to a Dev.to blog.&lt;/p&gt;

&lt;h1&gt;
  
  
  Adding RSS To GitHub Pages
&lt;/h1&gt;

&lt;p&gt;Adding RSS support to a GitHub Pages is very simple. All we have to do is add the following line to the &lt;code&gt;_config.yml&lt;/code&gt; file in the root directory of the project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;plugins:
  - jekyll-feed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To test locally, we can add the following entry to the project’s&lt;code&gt;Gemfile&lt;/code&gt;. (If you haven’t yet set up a local environment for your GitHub pages site, please follow &lt;a href="https://help.github.com/en/articles/testing-your-github-pages-site-locally-with-jekyll" rel="noopener noreferrer"&gt;this guide.&lt;/a&gt;)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gem 'jekyll-feed'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can do a &lt;code&gt;bundle install&lt;/code&gt;, which will install the required gem.&lt;/p&gt;

&lt;p&gt;When we run the site using &lt;code&gt;bundle exec jekyll serve&lt;/code&gt;, go to the page&lt;code&gt;localhost:4000/feed.xml&lt;/code&gt;. You should see something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;feed&amp;gt;
    &amp;lt;generator uri="https://jekyllrb.com/" version="3.8.5"&amp;gt;Jekyll&amp;lt;/generator&amp;gt;
    &amp;lt;link href="https://yoursite.com/feed.xml" rel="self" type="application/atom+xml"/&amp;gt;
    &amp;lt;link href="https://yoursite.com/" rel="alternate" type="text/html"/&amp;gt;```


    &amp;lt;!-- Full xml omitted --&amp;gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Side note: Technically, this is an &lt;a href="https://en.wikipedia.org/wiki/Atom_(Web_standard)" rel="noopener noreferrer"&gt;Atom feed&lt;/a&gt; but this will work fine for our use case.&lt;/p&gt;

&lt;p&gt;Once we have confirmed it works, we can push it to GitHub via the following command:&lt;code&gt;git commit -am "Add jekyll-feed gem"; git push&lt;/code&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Linking RSS on Dev.to
&lt;/h1&gt;

&lt;p&gt;Firstly, we need to go to&lt;a href="https://dev.to/settings/publishing-from-rss"&gt;https://dev.to/settings/publishing-from-rss&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We then just have to paste in ‘&lt;a href="https://yoursite.com/feed.xml%E2%80%99" rel="noopener noreferrer"&gt;https://yoursite.com/feed.xml’&lt;/a&gt; into the box, and press ‘update’.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6vuguiwqb0gsdevmj8hc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6vuguiwqb0gsdevmj8hc.png" alt="RSS Setting page on Dev.to" width="600" height="368"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I did enable the ‘Mark the RSS source as canonical URL by default’. This means it will mark my blog posts on my website as the original source, which helps my website appear in Google.&lt;/p&gt;

&lt;p&gt;After a small wait, posts from GitHub pages should appear in the Dashboard. They initially come in as drafts and posts can be published individually.&lt;/p&gt;

&lt;h2&gt;
  
  
  Possible Improvements
&lt;/h2&gt;

&lt;p&gt;While the RSS integration works really well, there’s a couple of small issues I encountered.&lt;/p&gt;

&lt;p&gt;When I initially set up RSS on the Dev.to side, it said it fetched my feed but I didn’t see any entries in my dashboard. It wasn’t until I checked a bit later that posts were sent across from my blog. I certainly don’t have a problem with waiting, but I thought I did something wrong as there was no clear messaging that it takes a little while.&lt;/p&gt;

&lt;p&gt;Another thing is that I have some entries from my blog that I don’t want to publish on Dev.to. However, if I delete the entries from my dashboard, they just come right back. It’d be good if there was some way to ‘ignore’ a blog post from an RSS feed.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;To reiterate the steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add the &lt;code&gt;- jekyll-feed&lt;/code&gt; to the plugins section in &lt;code&gt;_config.yml&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Go to &lt;a href="https://dev.to/settings/publishing-from-rss"&gt;https://dev.to/settings/publishing-from-rss&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Enter &lt;a href="https://yoursite/feed.xml" rel="noopener noreferrer"&gt;https://yoursite/feed.xml&lt;/a&gt; as the RSS Feed URL&lt;/li&gt;
&lt;li&gt;Press update.&lt;/li&gt;
&lt;li&gt;Check your Dashboard to see your posts! (may take a little while)&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>guide</category>
    </item>
    <item>
      <title>How to generate tons of random CSV files in Java</title>
      <dc:creator>Anthony Bruno</dc:creator>
      <pubDate>Mon, 11 Feb 2019 08:25:02 +0000</pubDate>
      <link>https://dev.to/aussieguy/how-to-generate-tons-of-random-csv-files-in-java-56e4</link>
      <guid>https://dev.to/aussieguy/how-to-generate-tons-of-random-csv-files-in-java-56e4</guid>
      <description>&lt;p&gt;&lt;em&gt;This post was originally posted on &lt;a href="http://anthonybruno.dev/2017/12/28/generating-csvs-with-SDGen-and-Faker.html"&gt;my blog&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The CSV format is a simple but commonly used format for exchanging data. Many applications support the import and export of information as CSV files. Due to the popularity of this format, there is a requirement for developers to generate large amounts of CSV files for testing. This is where my latest open source project &lt;a href="https://github.com/AussieGuy0/SDgen"&gt;SDGen&lt;/a&gt; comes into play.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/AussieGuy0/SDgen"&gt;SDGen&lt;/a&gt; is a Java library that helps developers generate randomized data files for testing purposes. It supports CSV and Fixed Width formats, with more formats such as JSON planned for the future.&lt;/p&gt;

&lt;p&gt;This guide will show you how to generate a simple CSV file using &lt;a href="https://github.com/AussieGuy0/SDgen"&gt;SDGen&lt;/a&gt; and &lt;a href="https://github.com/DiUS/java-faker"&gt;Faker&lt;/a&gt;. Faker will be used to assist creating random values.&lt;/p&gt;

&lt;h2&gt;
  
  
  Maven
&lt;/h2&gt;

&lt;p&gt;For a Maven project, we can add the required libraries by inserting the following xml into the pom.xml file of a project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;dependencies&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;au.com.anthonybruno&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;SdGen&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;0.3.0&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;com.github.javafaker&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;javafaker&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;0.14&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependencies&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Instructions
&lt;/h2&gt;

&lt;p&gt;Firstly, we need to get the Faker instance by writing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight java"&gt;&lt;code&gt;    &lt;span class="nc"&gt;Faker&lt;/span&gt; &lt;span class="n"&gt;faker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Faker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;instance&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We can then use the faker instance to generate values such as URLs &lt;code&gt;faker.internet().url()&lt;/code&gt; and planet names &lt;code&gt;faker.space().planet()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Next, we'll use &lt;code&gt;SDGen&lt;/code&gt;'s fluent builder to create the schema for the CSV file we want to create. To begin, we write:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight java"&gt;&lt;code&gt;    &lt;span class="nc"&gt;Gen&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;start&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We can then add fields (aka columns) using the &lt;code&gt;addField&lt;/code&gt; method. &lt;code&gt;addField&lt;/code&gt; takes 2 parameters: A &lt;code&gt;String&lt;/code&gt; name, which will be to identify the field in the produced file and a &lt;code&gt;Generator&lt;/code&gt;. A &lt;code&gt;Generator&lt;/code&gt; is a simple interface with a single method &lt;code&gt;generate&lt;/code&gt;. This is the way that random values are created and added to a field. &lt;/p&gt;

&lt;p&gt;We are going to make a simple CSV file of people. To do that, we will add a 'First Name' and a 'Last Name' column using the corresponding &lt;code&gt;Faker&lt;/code&gt; methods to generate values for these:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight java"&gt;&lt;code&gt;    &lt;span class="nc"&gt;Gen&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;start&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addField&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"First Name"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;faker&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="na"&gt;firstName&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addField&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Last Name"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;faker&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="na"&gt;lastName&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Note: Using lambdas (e.g. &lt;code&gt;() -&amp;gt; faker.name().firstName()&lt;/code&gt; is the equivalent of writing:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Generator&lt;/span&gt;&lt;span class="o"&gt;()&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="nc"&gt;Object&lt;/span&gt; &lt;span class="nf"&gt;generate&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;faker&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="na"&gt;firstName&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;We also want to add an 'Age' field. To do this, we can use &lt;code&gt;SDGen&lt;/code&gt;'s inbuilt &lt;code&gt;IntGenerator&lt;/code&gt;. We can give it a sensible minimum and maximum value to limit the range of numbers it will generate. &lt;code&gt;SDGen&lt;/code&gt; provides generators for all primitive types.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;Gen&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;start&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addField&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"First Name"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;faker&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="na"&gt;firstName&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addField&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Last Name"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;faker&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="na"&gt;lastName&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addField&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Age"&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;IntGenerator&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Next, we specify how many rows to generate by using the &lt;code&gt;generate&lt;/code&gt; method.  We also want to select the format of the generated data. We will be using &lt;code&gt;asCsv&lt;/code&gt; to generate the data in CSV format. &lt;code&gt;SDGen&lt;/code&gt; also supports the Fixed Width format and will support other data formats such as JSON in the future.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;Gen&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;start&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addField&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"First Name"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;faker&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="na"&gt;firstName&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addField&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Last Name"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;faker&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="na"&gt;lastName&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addField&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Age"&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;IntGenerator&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="o"&gt;))&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="mi"&gt;1000&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;//1000 rows will be generated&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;asCsv&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Finally, we specify how the data will be output. We will use the &lt;code&gt;toFile&lt;/code&gt; method to put the information into a file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;Gen&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;start&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addField&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"First Name"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;faker&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="na"&gt;firstName&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addField&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Last Name"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;faker&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="na"&gt;lastName&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addField&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Age"&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;IntGenerator&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="o"&gt;))&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="mi"&gt;1000&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;asCsv&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toFile&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"people.csv"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And that's it! Running the code will produce a CSV file in the project's working directory. Here is some data that was produced when I ran it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;First Name,Last Name,Age
Corrine,Berge,78
Gerald,Carter,63
Enid,Padberg,66
Eleanora,Murray,79
Coy,Okuneva,76
Jovan,Reynolds,77
Lane,Haag,48
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;For more information about SDGen, please visit it on &lt;a href="https://github.com/AussieGuy0/SDgen"&gt;Github&lt;/a&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  Details
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Faker: &lt;a href="https://github.com/DiUS/java-faker"&gt;Github&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;SDGen: &lt;a href="https://github.com/AussieGuy0/SDgen"&gt;Github&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>java</category>
      <category>opensource</category>
    </item>
    <item>
      <title>A quick look at Java 11's HttpClient</title>
      <dc:creator>Anthony Bruno</dc:creator>
      <pubDate>Wed, 16 Jan 2019 09:23:08 +0000</pubDate>
      <link>https://dev.to/aussieguy/a-quick-look-at-java-11s-httpclient-1f79</link>
      <guid>https://dev.to/aussieguy/a-quick-look-at-java-11s-httpclient-1f79</guid>
      <description>&lt;p&gt;&lt;em&gt;This article was originally posted on &lt;a href="http://anthonybruno.dev/2019/01/16/A-quick-look-at-java-11's-HttpClient.html" rel="noopener noreferrer"&gt;my blog&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Java 11 was released in September 2018 and is the first Long-Term-Support version after Java 8. One of its features is &lt;a href="https://docs.oracle.com/en/java/javase/11/docs/api/java.net.http/java/net/http/HttpClient.html" rel="noopener noreferrer"&gt;HttpClient&lt;/a&gt;, a new way to make HTTP requests. This post will give a quick overview of  HttpClient, and how it's a much-needed replacement for &lt;a href="https://docs.oracle.com/javase/8/docs/api/java/net/URLConnection.html" rel="noopener noreferrer"&gt;URLConnection&lt;/a&gt;!&lt;/p&gt;

&lt;h2&gt;
  
  
  The task
&lt;/h2&gt;

&lt;p&gt;I've created a page on my website &lt;a href="http://anthonybruno.dev/last-update" rel="noopener noreferrer"&gt;http://anthonybruno.dev/last-update&lt;/a&gt; that simply has a Unix timestamp of the last time the site was built.&lt;/p&gt;

&lt;p&gt;The task is simple, create some code that requests this page and returns the&lt;br&gt;
timestamp!&lt;/p&gt;
&lt;h2&gt;
  
  
  Using URLConnection
&lt;/h2&gt;

&lt;p&gt;Below is the code that uses &lt;code&gt;URLConnection&lt;/code&gt;.&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="c1"&gt;// 1. Create URL object&lt;/span&gt;
&lt;span class="no"&gt;URL&lt;/span&gt; &lt;span class="n"&gt;updateUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="no"&gt;URL&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"http://anthonybruno.com.au/last-update"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// 2. We use openConnection() on the url to get a HttpURLConnection, &lt;/span&gt;
&lt;span class="c1"&gt;//    that we have to cast(?!). Also, this doesn't actually make a &lt;/span&gt;
&lt;span class="c1"&gt;//    network request(?!?!?)&lt;/span&gt;
&lt;span class="nc"&gt;HttpURLConnection&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HttpURLConnection&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;updateUrl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;openConnection&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// 3. We can then set things like set request methods, headers.&lt;/span&gt;
&lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setRequestMethod&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"GET"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// 4. Then we actually connect! Note: connect doesn't return anything, it&lt;/span&gt;
&lt;span class="c1"&gt;//    mutates the connection object!&lt;/span&gt;
&lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;connect&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;statusCode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getResponseCode&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;statusCode&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;RuntimeException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Got non 200 response code! "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;statusCode&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// 5. Content is returned in an InputStream (Don't forget to close it!)&lt;/span&gt;
&lt;span class="nc"&gt;InputStream&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getInputStream&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;

&lt;span class="nc"&gt;Instant&lt;/span&gt; &lt;span class="n"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;processIntoInstant&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// 6. Remember to disconnect! Note: HttpURLConnnection is not autoclosable!&lt;/span&gt;
&lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;disconnect&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After creating the &lt;code&gt;URL&lt;/code&gt; object, things quickly go awry. It's extremely&lt;br&gt;
counter-intuitive to use a method called &lt;code&gt;openConnection()&lt;/code&gt;, that doesn't actually open a connection! Having to cast the returned &lt;code&gt;URLConnection&lt;/code&gt; object to &lt;code&gt;HttpURLConnection&lt;/code&gt; to access methods like &lt;code&gt;setRequestMethod&lt;/code&gt; and &lt;code&gt;disconnect&lt;/code&gt; is plain silly. Finally, calling &lt;code&gt;connect()&lt;/code&gt; (which actually makes a network request!) doesn't return anything, instead, you have to get response information from the &lt;code&gt;connection&lt;/code&gt; object itself.&lt;/p&gt;
&lt;h2&gt;
  
  
  Using HttpClient
&lt;/h2&gt;

&lt;p&gt;Below is the code that uses &lt;code&gt;HttpClient&lt;/code&gt;. You'll see a big difference.&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="c1"&gt;// 1. Create HttpClient object&lt;/span&gt;
&lt;span class="nc"&gt;HttpClient&lt;/span&gt; &lt;span class="n"&gt;httpClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;HttpClient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;newHttpClient&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// 2. Create URI object&lt;/span&gt;
&lt;span class="no"&gt;URI&lt;/span&gt; &lt;span class="n"&gt;uri&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;URI&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;create&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;updateUrl&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// 3. Build a request&lt;/span&gt;
&lt;span class="nc"&gt;HttpRequest&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;HttpRequest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;newBuilder&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;GET&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="c1"&gt;// 4. Send the request and get a HttpResponse object back!&lt;/span&gt;
&lt;span class="c1"&gt;//    Note: HttpResponse.BodyHandlers.ofString() just parses the response body&lt;/span&gt;
&lt;span class="c1"&gt;//          as a String&lt;/span&gt;
&lt;span class="nc"&gt;HttpResponse&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;httpClient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;send&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;HttpResponse&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;BodyHandlers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ofString&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;statusCode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;statusCode&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;statusCode&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;RuntimeException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Got non 200 response code! "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;statusCode&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;Instant&lt;/span&gt; &lt;span class="n"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;processIntoInstant&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, isn't that much nicer than the &lt;code&gt;URlConnection&lt;/code&gt; code we saw before? We first set up a &lt;code&gt;HttpClient&lt;/code&gt; object, which will send our requests. We then instantiate a &lt;code&gt;HttpRequest&lt;/code&gt; object, which holds the request method, headers, etc. We send the &lt;code&gt;HttpRequest&lt;/code&gt;, using the previously created &lt;code&gt;HttpClient&lt;/code&gt;, giving us a nice &lt;code&gt;HttpResponse&lt;/code&gt; object back.&lt;/p&gt;

&lt;p&gt;The second parameter in &lt;code&gt;httpClient.send&lt;/code&gt; is a &lt;code&gt;BodyHandler&lt;/code&gt;, which is&lt;br&gt;
responsible for parsing the response body into the format you want. Java provides a bunch of default ones in &lt;code&gt;BodyHandlers&lt;/code&gt;, that covers common use cases like parsing to &lt;code&gt;String&lt;/code&gt;, &lt;code&gt;File&lt;/code&gt; and &lt;code&gt;InputStream&lt;/code&gt;. Of course, it's possible to create your own, which deserves an article by itself.&lt;/p&gt;

&lt;p&gt;The idea of creating a client, creating requests and receiving responses is quite a bit more intuitive than using &lt;code&gt;URlConnection&lt;/code&gt;! &lt;code&gt;HttpClient&lt;/code&gt; also supports asynchronous requests, HTTP/2 and websockets. It's an enticing reason to migrate from 8 to 11!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Code used in this article can be found &lt;a href="https://github.com/AussieGuy0/trash-heap/blob/master/code/java/http/src/main/java/au/com/anthonybruno/http/Main.java" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>java</category>
      <category>programming</category>
    </item>
    <item>
      <title>Reading files in a Chrome Extension</title>
      <dc:creator>Anthony Bruno</dc:creator>
      <pubDate>Sun, 04 Mar 2018 01:16:15 +0000</pubDate>
      <link>https://dev.to/aussieguy/reading-files-in-a-chrome-extension--2c03</link>
      <guid>https://dev.to/aussieguy/reading-files-in-a-chrome-extension--2c03</guid>
      <description>&lt;p&gt;Often, it is desirable for a Chrome extension to be bundled with files that need to be read. These files may contain data or configuration information to help the extension function. This short guide will show you how you can set up your Chrome extension to read files.&lt;/p&gt;

&lt;h2&gt;
  
  
  Add file path(s) to manifest.json
&lt;/h2&gt;

&lt;p&gt;Firstly, you must add the file paths to the web_accessible_resources property in the manifest.json file. The file paths are relative to the extension's root (where the manifest.json is located). For instance, if I wanted to include a file called &lt;code&gt;info.json&lt;/code&gt; that is located in a folder data, it would look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"web_accessible_resources"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"data/info.json"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A cool feature is that these paths support wildcards. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"web_accessible_resources"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"data/*.json"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;will allow access to any json file in the data folder.&lt;/p&gt;

&lt;h2&gt;
  
  
  Read from the file
&lt;/h2&gt;

&lt;p&gt;The next step is to read the data from the file. To do this, we need to get the&lt;br&gt;
URL of the file and make a request to it.&lt;/p&gt;

&lt;p&gt;To get the URL of the file we can use &lt;code&gt;chrome.runtime.getURL('path/to/file')&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Then, we make a GET request to the URL. In this example, we will use the ES6 feature &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API" rel="noopener noreferrer"&gt;Fetch&lt;/a&gt; but methods such as &lt;code&gt;XmlHttpRequest&lt;/code&gt; will also work.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;chrome&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;runtime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getURL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;path/to/file&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="c1"&gt;//assuming file contains json&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;doSomething&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And there we have it!&lt;/p&gt;

&lt;p&gt;To reiterate the steps simply:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add file path to the &lt;code&gt;web_accessible_resources&lt;/code&gt; property in the &lt;code&gt;manifest.json&lt;/code&gt; file&lt;/li&gt;
&lt;li&gt;Get the URL of the file using &lt;code&gt;chrome.runtime.getURL('path/to/file')&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Make a GET request to the URL
&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>javascript</category>
    </item>
    <item>
      <title>The non-broken promise of static typing</title>
      <dc:creator>Anthony Bruno</dc:creator>
      <pubDate>Tue, 19 Sep 2017 13:16:22 +0000</pubDate>
      <link>https://dev.to/aussieguy/the-non-broken-promise-of-static-typing</link>
      <guid>https://dev.to/aussieguy/the-non-broken-promise-of-static-typing</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally posted on &lt;a href="http://anthonybruno.com.au/2017/09/19/The-non-broken-promise-of-static-typing.html"&gt;my blog&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A while back I read an article about how static typing does not prevent&lt;br&gt;
bugs being added to software. The article is appropriately named: &lt;a href="https://dev.to/danlebrero/the-broken-promise-of-static-typing"&gt;The broken promise of static typing&lt;/a&gt;. The author conducted research by generating and comparing 'bug density' scores for GitHub repositories. The bug density score was determined by getting the average number of issues labelled 'bug' per repository. &lt;/p&gt;

&lt;p&gt;The results showed that there were not any less bugs in statically typed languages vs dynamically typed languages. The author concludes on the results:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"the lack of evidence in the charts that more advanced type languages are going to save us from writing bugs is very disturbing."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;While this article brings up good points and makes an effort at original research, I've always felt that the claims made were wrong. I strongly believe less bugs will occur when a statically typed language is used. However, I've never had any proper evidence to back up my claims...&lt;strong&gt;until now!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Enter: &lt;a href="https://blog.acolyer.org"&gt;The Morning Paper&lt;/a&gt;, a blog that summarises tech white papers. It recently released an article talking about the same subject called: &lt;a href="https://blog.acolyer.org/2017/09/19/to-type-or-not-to-type-quantifying-detectable-bugs-in-javascript/"&gt;To type or not to type: quantifying detectable bugs in JavaScript&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The article covers a study of the same name. In it, researchers looked at 400 fixed bugs in JavaScript projects hosted on GitHub. For each bug, the researchers tried to see if adding type annotations (using TypeScript and Flow) would detect the bug. The results? A substantial &lt;strong&gt;15%&lt;/strong&gt; of bugs could be detected using type annotations. With this reduction in bugs, it's hard to deny the value of static typing.&lt;/p&gt;

&lt;p&gt;While these results show a benefit from using static typing, people will continue to prefer a specific type system. So, let's hear from you! What type system do you prefer, and why?&lt;/p&gt;

</description>
      <category>typesystem</category>
      <category>programming</category>
      <category>discuss</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Add file/directory auto-completion to user input in Bash</title>
      <dc:creator>Anthony Bruno</dc:creator>
      <pubDate>Wed, 19 Apr 2017 00:00:00 +0000</pubDate>
      <link>https://dev.to/aussieguy/add-file-directory-auto-completion-to-user-input-in-bash-703</link>
      <guid>https://dev.to/aussieguy/add-file-directory-auto-completion-to-user-input-in-bash-703</guid>
      <description>&lt;p&gt;The most common way to get input from a user in a Bash script is to use the read function like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/bin/bash
echo "Type a word and press enter"
read INPUT
echo "Your word was $INPUT"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, this is not the best method to use when you want the user to input a directory path. This is because pressing &lt;code&gt;tab&lt;/code&gt; enters a literal tab instead of auto-completing the directory path like what happens in the terminal.&lt;/p&gt;

&lt;p&gt;To add directory auto-completion to your bash script, all you have to do is add the &lt;code&gt;-e&lt;/code&gt; flag to the read function like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/bin/bash
echo "Type a file or directory (use tab to autocomplete path!) and press enter"
read -e INPUT
echo "Your path was $INPUT"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>bash</category>
      <category>guide</category>
    </item>
    <item>
      <title>Three Ways To Add an ActionListener In Java Swing</title>
      <dc:creator>Anthony Bruno</dc:creator>
      <pubDate>Sat, 20 Aug 2016 00:00:00 +0000</pubDate>
      <link>https://dev.to/aussieguy/three-ways-to-add-an-actionlistener-in-java-swing-19h5</link>
      <guid>https://dev.to/aussieguy/three-ways-to-add-an-actionlistener-in-java-swing-19h5</guid>
      <description>&lt;p&gt;When building GUI’s, the interface needs a way to listen and respond to events. Events are triggered when the user interacts with the GUI, such as pressing buttons and inserting text. One of these types of events in Java Swing is the ActionEvent. A commonly used component that generates a ActionEvent is a JButton, which is simply a button that produces an event when pressed. This article serves to explain three different ways an ActionListener can be added to a component.&lt;/p&gt;

&lt;h2&gt;
  
  
  Component as ActionListener
&lt;/h2&gt;

&lt;p&gt;This is when the component itself listens for actions. To do this, simply implement the ActionListener interface in the component, for instance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class ButtonExample extends JButton implements ActionListener {

    public ButtonExample() {
        addActionListener(this);
    }

    public void actionPerformed(ActionEvent ae) {
        //handle event here
    }

}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Components implementing the ActionListener therefore become both the source and listener. You would want to use this method if events are relatively simple and internal (e.g. not connecting multiple components).&lt;/p&gt;

&lt;p&gt;This method of adding an ActionListener breaks the &lt;a href="https://en.wikipedia.org/wiki/Single_responsibility_principle" rel="noopener noreferrer"&gt;Single responsibility principle&lt;/a&gt; as the component is both responsible for creating events and handling it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Inner ActionListener
&lt;/h2&gt;

&lt;p&gt;This method is when you use the ‘new’ keyword to create a new ActionListener for each component.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;component.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent ae) {
            //handle event here
        }
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This implementation is great for simple listeners and it also separates the listener from the component. Avoid this if your trying to add ActionListeners to sub-components, for example, sub-components of a JPanel. This can result in messy code as every component is creating it’s own version of an ActionListener.&lt;/p&gt;

&lt;h2&gt;
  
  
  Separate ActionListener
&lt;/h2&gt;

&lt;p&gt;This technique requires you to create a separate class that implements ActionListener. A component that needs this ActionListener simply creates a new instance of this class and adds it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class ButtonExample extends JButton {

      public ButtonExample() {
          addActionListener(new ButtonHandler());
      }   
}

public class ButtonHandler implements ActionListener {
      public ButtonHandler() {

      }   

      public void actionPerformed(ActionEvent ae) {
          //handle event here
      }   
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the cleanest way to add an ActionListener. It separates the component from the listener, creates a reusable listener that can be used across different classes and allows for complex interactions between components.&lt;/p&gt;

</description>
      <category>java</category>
      <category>swing</category>
      <category>guide</category>
    </item>
  </channel>
</rss>
