<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>melgenek</title>
    <description>melgenek&apos;s blog</description>
    <link>https://melgenek.dev/</link>
    <atom:link href="https://melgenek.dev/feed.xml" rel="self" type="application/rss+xml" />
    
      <item>
        <title>Getting a development domain and TLS certificates for free</title>
        <description>&lt;p&gt;Recently I have been experimenting with Http/3 protocol which uses TLS by default.
Having self-signed TLS certificates makes browsers unhappy about the traffic, that’s why I needed a way to get a trusted certificate.
While it took me more time than expected, I decided to write down the taken steps.&lt;/p&gt;

&lt;nav&gt;
  &lt;p&gt;&lt;span class=&quot;toc-title&quot;&gt;Table of Contents&lt;/span&gt;&lt;/p&gt;
&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#getting-the-domain-and-certificates&quot; id=&quot;markdown-toc-getting-the-domain-and-certificates&quot;&gt;Getting the domain and certificates&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#what-has-just-happened&quot; id=&quot;markdown-toc-what-has-just-happened&quot;&gt;What has just happened&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#summary&quot; id=&quot;markdown-toc-summary&quot;&gt;Summary&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;/nav&gt;

&lt;h2 id=&quot;getting-the-domain-and-certificates&quot;&gt;Getting the domain and certificates&lt;/h2&gt;

&lt;p&gt;This section walks through the process of getting a domain name and TLS certificates.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;To start with, we need to have access to a DNS provider and a domain. I chose &lt;a href=&quot;https://www.duckdns.org/&quot;&gt;DuckDNS&lt;/a&gt; because it is absolutely
free and allows creating TXT DNS records, that are used to pass &lt;a href=&quot;https://letsencrypt.org/docs/challenge-types/#dns-01-challenge&quot;&gt;the ACME DNS challenge&lt;/a&gt;.
At DuckDNS we create our own domain and copy the token that looks like UUIDv4 string. This token is needed to update the DNS records via the DuckDNS api.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Next we pass the ACME challenge and get the TLS certificates utilising Let’s Encrypt and CertBot. &lt;a href=&quot;https://letsencrypt.org/&quot;&gt;Let’s Encrypt&lt;/a&gt; is the certificate authority
that issues certificates that are valid in all the browsers.
&lt;a href=&quot;https://certbot.eff.org/&quot;&gt;CertBot&lt;/a&gt; is a tool that is usually used to pass ACME challenges on a wide variety of server platforms.
Fortunately for us, &lt;a href=&quot;https://github.com/maksimstojkovic/docker-letsencrypt&quot;&gt;there is a docker container&lt;/a&gt; dedicated to getting certificates at Let’s Encrypt for DuckDNS domains.
The usage is as easy as running this command in the terminal:&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;pre class=&quot;shiki everforest-light&quot; style=&quot;background-color:#fdf6e3;color:#5c6a72&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;docker&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; run&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; -it&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; --rm&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;-e &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;DUCKDNS_TOKEN=&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;&quot;396db3e9-5ecc-4d0c-a708-70a926b1389c&quot;&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;-e &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;DUCKDNS_DOMAIN=&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;&quot;melgenek.duckdns.org&quot;&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;-v &lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;pwd&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;/melgenek_certs:/etc/letsencrypt&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;maksimstojkovic/letsencrypt:latest&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker run&lt;/code&gt; we specified the token that DuckDNS provides for accessing their API and my domain.
As a result of running this command the ACME challenge is succeeds,
and the volume attached to the container contains the certificates.
The private key and the public certificate can be found in the files &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;./melgenek_certs/live/melgenek.duckdns.org/privkey.pem&lt;/code&gt; 
and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;./melgenek_certs/live/melgenek.duckdns.org/cert.pem&lt;/code&gt; respectively.&lt;/p&gt;

&lt;h2 id=&quot;what-has-just-happened&quot;&gt;What has just happened&lt;/h2&gt;

&lt;p&gt;The docker container that we used in the previous section did the needed magic to validate the DNS record and get the certificates.
In order to get the understanding of what the ACME flow looks like, let’s generate one more certificate using the plain CertBot.
After passing the challenge, Let’s Encrypt is sure that the domain is ours and gives us a certificate.&lt;/p&gt;

&lt;p&gt;The first step is to start the CertBot flow. The CertBot is installed as &lt;a href=&quot;https://certbot.eff.org/docs/install.html&quot;&gt;a standalone binary&lt;/a&gt; 
and can be run from terminal. The command specifies for which domain we want to pass the DNS challenge and where to store the certificates.&lt;/p&gt;

&lt;pre class=&quot;shiki everforest-light&quot; style=&quot;background-color:#fdf6e3;color:#5c6a72&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;certbot&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; certonly&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; --manual&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;    --preferred-challenges&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; dns&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;    --register-unsafely-without-email&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;    -d&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; &quot;melgenek.duckdns.org&quot;&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;    --work-dir&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; &quot;./melgenek_certs/work_dir&quot;&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;    --logs-dir&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; &quot;./melgenek_certs/logs_dir&quot;&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;    --config-dir&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; &quot;./melgenek_certs/config_dir&quot;&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;    --agree-tos&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;As a result of the running the command CertBot generates a secret value and asks us to put it into the DNS record.&lt;/p&gt;

&lt;pre class=&quot;shiki everforest-light&quot; style=&quot;background-color:#fdf6e3;color:#5c6a72&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;Please&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; deploy&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; a&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; DNS&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; TXT&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; record&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; under&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; the&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; name&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;_acme-challenge.melgenek.duckdns.org&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; with&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; the&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; following&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; value:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;NaM0ODwHZfL6b1pjM_rrgfCSwVcy_CALKkxR2YzyE7A&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;Before&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; continuing,&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; verify&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; the&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; record&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; is&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; deployed.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; -&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;Press&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; Enter&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; to&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; Continue&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;CertBot proposes to set the TXT record at the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_acme-challenge.melgenek.duckdns.org&lt;/code&gt; subdomain. 
The validation of such a record would result in issuing a wildcard certificate for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*.melgenek.duckdns.org&lt;/code&gt;.
We are setting the TXT record for the domain itself so that the certificate is valid only for the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;melgenek.duckdns.org&lt;/code&gt; domain.
The next cUrl call creates the TXT record in DuckDns.&lt;/p&gt;

&lt;pre class=&quot;shiki everforest-light&quot; style=&quot;background-color:#fdf6e3;color:#5c6a72&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;curl&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; &quot;https://www.duckdns.org/update?domains=melgenek.duckdns.org&amp;#x26;token=396db3e9-5ecc-4d0c-a708-70a926b1389c&amp;#x26;txt=NaM0ODwHZfL6b1pjM_rrgfCSwVcy_CALKkxR2YzyE7A&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Before proceeding with the ACME challenge, we can check that the DNS record is actually set using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dig&lt;/code&gt;. 
In the lookup result we see that the TXT record is exactly what we expect it to be.&lt;/p&gt;

&lt;pre class=&quot;shiki everforest-light&quot; style=&quot;background-color:#fdf6e3;color:#5c6a72&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;dig&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; melgenek.duckdns.org&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; TXT&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;;; &lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;ANSWER&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; SECTION:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;melgenek.duckdns.org.&lt;/span&gt;&lt;span style=&quot;color:#DF69BA&quot;&gt;   59&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;      IN&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;      TXT&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;     &quot;NaM0ODwHZfL6b1pjM_rrgfCSwVcy_CALKkxR2YzyE7A&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Clicking “Enter” in the terminal where CertBot is waiting for input would trigger Let’s Encrypt validation of the TXT record.
Passing this validation successfully produces certificates the specified folder &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;./melgenek_certs/config_dir/live/melgenek.duckdns.org&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The challenge secret is a not reused in the future, so it makes sense to clean up the TXT record. 
This is done by adding the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;clear=true&lt;/code&gt; query param to the previous cUrl query.&lt;/p&gt;

&lt;pre class=&quot;shiki everforest-light&quot; style=&quot;background-color:#fdf6e3;color:#5c6a72&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;curl&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; &quot;https://www.duckdns.org/update?domains=melgenek.duckdns.org&amp;#x26;token=396db3e9-5ecc-4d0c-a708-70a926b1389c&amp;#x26;txt=NaM0ODwHZfL6b1pjM_rrgfCSwVcy_CALKkxR2YzyE7A&amp;#x26;clear=true&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;

&lt;p&gt;In this article we described a simple way of getting perfectly valid TLS certificates as wells as a domain that can be used for development purposes.
Hopefully, this information helps build exciting software and learn new technologies.&lt;/p&gt;
</description>
        <pubDate>Wed, 28 Jul 2021 00:00:00 +0000</pubDate>
        <link>https://melgenek.dev/developer-dns-tls</link>
        <guid isPermaLink="true">https://melgenek.dev/developer-dns-tls</guid>
      </item>
    
      <item>
        <title>Enhancing DynamoDb client with Scala 3</title>
        <description>&lt;p&gt;After 8 years of development, Dotty is going to become Scala 3 soon.
It’s the right time to try out Scala 3 and its new features. In this article, I am going to show
a practical example of making DynamoDb more type-safe and convenient using &lt;a href=&quot;https://dotty.epfl.ch/docs/reference/metaprogramming/macros.html&quot;&gt;macros&lt;/a&gt;,
&lt;a href=&quot;https://dotty.epfl.ch/docs/reference/contextual/derivation.html&quot;&gt;type class derivations&lt;/a&gt;, &lt;a href=&quot;https://dotty.epfl.ch/docs/reference/contextual/extension-methods.html&quot;&gt;extensions methods&lt;/a&gt;, 
and a handful of implicits.&lt;/p&gt;

&lt;nav&gt;
  &lt;p&gt;&lt;span class=&quot;toc-title&quot;&gt;Table of Contents&lt;/span&gt;&lt;/p&gt;
&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#introduction&quot; id=&quot;markdown-toc-introduction&quot;&gt;Introduction&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#encoding-attributes-implicits&quot; id=&quot;markdown-toc-encoding-attributes-implicits&quot;&gt;Encoding attributes. Implicits&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#obtaining-class-field-names-macros&quot; id=&quot;markdown-toc-obtaining-class-field-names-macros&quot;&gt;Obtaining class field names. Macros&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#avoiding-map-construction-type-class-derivation&quot; id=&quot;markdown-toc-avoiding-map-construction-type-class-derivation&quot;&gt;Avoiding map construction. Type class derivation&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#convenience-operators-extension-methods&quot; id=&quot;markdown-toc-convenience-operators-extension-methods&quot;&gt;Convenience operators. Extension methods&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#conclusion&quot; id=&quot;markdown-toc-conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;/nav&gt;

&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;To start with, let’s look at how to put and get an item from DynamoDb utilizing the plain aws-sdk client. 
The examples assume that there is a case class:&lt;/p&gt;
&lt;pre class=&quot;shiki everforest-light&quot; style=&quot;background-color:#fdf6e3;color:#5c6a72&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; NewYear&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(year: &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Int&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;, wish: &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; gift&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; String&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; &quot;A fairy pony&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;val&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; year &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; NewYear&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#DF69BA&quot;&gt;2020&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;&quot;I wish Scala 3 was released soon&quot;&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The case class is defined in the file &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NewYear.scala&lt;/code&gt;. The instance of the case class &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;val year=...&lt;/code&gt; as well as the case class itself are &lt;a href=&quot;https://dotty.epfl.ch/docs/reference/dropped-features/package-objects.html&quot;&gt;at the top-level&lt;/a&gt; as well.
This is the first notable feature of Scala 3: the package objects were removed from the language. The values and methods don’t need to be defined inside an object or class anymore.&lt;/p&gt;

&lt;p&gt;The instances of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NewYear&lt;/code&gt; are going to be stored in the dynamo table &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;new-years&lt;/code&gt;. 
I am omitting the code of creating the dynamo table, the whole example can be found in the &lt;a href=&quot;https://github.com/melgenek/dotty-dynamodb&quot;&gt;github repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now we know the entities that are going to be stored in the database. We can take a look at the put/get code:&lt;/p&gt;
&lt;pre class=&quot;shiki everforest-light&quot; style=&quot;background-color:#fdf6e3;color:#5c6a72&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;ddb.putItem(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;  PutItemRequest&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.builder()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    .tableName(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;TableName&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    .item(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Map&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;      &quot;year&quot;&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; AttributeValue&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.builder().n(year.year.toString).build(),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;      &quot;wish&quot;&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; AttributeValue&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.builder().s(year.wish).build()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    ).asJava)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    .build()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;val&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; item &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; ddb.getItem(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;  GetItemRequest&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.builder()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    .tableName(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;TableName&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    .key(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Map&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;      &quot;year&quot;&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; AttributeValue&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.builder().n(&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;&quot;2020&quot;&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;).build()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    ).asJava)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    .build()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;What problems can we see here?&lt;/p&gt;

&lt;p&gt;Firstly, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AttributeValues&lt;/code&gt; are being built explicitly, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;year&lt;/code&gt; of type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Int&lt;/code&gt; is transformed into a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;String&lt;/code&gt; in order to be set as the value of the attribute.
Not only we can make a mistake of choosing the DynamoDb type by confusing the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.n&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.s&lt;/code&gt; value setters on the builder, but also the code looks ugly and verbose.
It’s a great use case for type classes to provide a unified way of converting scala types to the `  AttributeValue`.&lt;/p&gt;

&lt;p&gt;Secondly, the attribute names are passed as strings. The key of our table is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;year&lt;/code&gt;. 
A typo in the key of the get request can lead to no results being returned. 
You can argue that having constants for the attribute names is enough. 
However, keeping the same name of the key in the item map and the case class field is going to be crucial to write cases classes in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.item&lt;/code&gt; without an explicit construction of the map.&lt;/p&gt;

&lt;p&gt;Here comes the last issue that we’ll try solving in this article. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.item&lt;/code&gt; ignores the instance of the class that we defined and expects a map.
This case class has only 2 fields, so building a map is quite an easy task. Having 20 fields will definitely be error-prone 
because an additional field in the case class requires an additional line inside the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.item&lt;/code&gt; map.&lt;/p&gt;

&lt;p&gt;After making some improvements employing the features of Scala 3, we can get a neat code like this&lt;/p&gt;
&lt;pre class=&quot;shiki everforest-light&quot; style=&quot;background-color:#fdf6e3;color:#5c6a72&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;ddb.putItem(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;  PutItemRequest&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.builder()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    .tableName(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;TableName&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    .item(year)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    .build()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;val&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; item &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; ddb.getItem(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;  GetItemRequest&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.builder()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    .tableName(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;TableName&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    .key[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;NewYear&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;](_.year, &lt;/span&gt;&lt;span style=&quot;color:#DF69BA&quot;&gt;2021&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    .build()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In the following sections, I’ll explain how to create the utilities for the code above to work.&lt;/p&gt;

&lt;h2 id=&quot;encoding-attributes-implicits&quot;&gt;Encoding attributes. Implicits&lt;/h2&gt;

&lt;p&gt;I’m going to introduce the improvements step by step. To start with, we’ll make the attribute building more pleasant.
In order to do this, we’ll have &lt;a href=&quot;https://dotty.epfl.ch/docs/reference/contextual/type-classes.html&quot;&gt;a type class&lt;/a&gt; for the conversion of a scala type to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AttributeValue&lt;/code&gt; and back. 
Every type that can be converted to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AttributeValue&lt;/code&gt; will have an implementation of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AttributeCodec&lt;/code&gt; trait:&lt;/p&gt;
&lt;pre class=&quot;shiki everforest-light&quot; style=&quot;background-color:#fdf6e3;color:#5c6a72&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;trait&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; AttributeCodec&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;A&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;] {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; encode&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(a: &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;A&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; AttributeValue&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; decode&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(a: &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;AttributeValue&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; A&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;given&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; AttributeCodec&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt;with&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; encode&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(a: &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; AttributeValue&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; AttributeValue&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.builder().s(a).build()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; decode&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(a: &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;AttributeValue&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; String&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; a.s()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;implicit&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; val&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; intCodec&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; AttributeCodec&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Int&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt; new&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; AttributeCodec&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Int&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;] {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; encode&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(a: &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Int&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; AttributeValue&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; AttributeValue&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.builder().n(a.toString).build()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; decode&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(a: &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;AttributeValue&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; Int&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; a.n().toInt&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You can see that I defined two instances:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;the instance for the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;String&lt;/code&gt; type is defined with Scala 3 syntax&lt;/li&gt;
  &lt;li&gt;the instance for the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Int&lt;/code&gt; uses the old Scala 2 syntax&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Scala 3 syntax is slightly nicer, the instance names can be omitted. They are never used after all, 
because the instances are found in the implicit scope via summoning. In the new Scala, the method &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;implicitly&lt;/code&gt;
is renamed to be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;summon&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;shiki everforest-light&quot; style=&quot;background-color:#fdf6e3;color:#5c6a72&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;summon[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;AttributeCodec&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Int&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;]].encode(&lt;/span&gt;&lt;span style=&quot;color:#DF69BA&quot;&gt;2021&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#939F91;font-style:italic&quot;&gt;// AttributeValue.builder().n(2021.toString).build()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We can make the encoding look even better by adding a so-called “summoner” method to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AttributeCodec&lt;/code&gt;. 
There is a new keyword &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;using&lt;/code&gt; that marks the implicit function parameters. It replaces the old &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;implicit&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;shiki everforest-light&quot; style=&quot;background-color:#fdf6e3;color:#5c6a72&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;object&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; AttributeCodec&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; apply&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;A&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;](&lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; codec: &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;AttributeCodec&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;A&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;])&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; AttributeCodec&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;A&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; codec&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#939F91;font-style:italic&quot;&gt;  // The old syntax&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#939F91;font-style:italic&quot;&gt;  // def apply[A](implicit codec: AttributeCodec[A]): AttributeCodec[A] = codec&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;After this first round of enhancements our application is in the following state:&lt;/p&gt;
&lt;pre class=&quot;shiki everforest-light&quot; style=&quot;background-color:#fdf6e3;color:#5c6a72&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;ddb.putItem(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;  PutItemRequest&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.builder()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    .tableName(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;TableName&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    .item(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Map&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;      &quot;year&quot;&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; AttributeCodec&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Int&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;].encode(year.year),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;      &quot;wish&quot;&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; AttributeCodec&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;].encode(year.wish)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    ).asJava)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    .build()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;val&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; item &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; ddb.getItem(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;  GetItemRequest&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.builder()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    .tableName(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;TableName&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    .key(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Map&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;      &quot;year&quot;&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; AttributeCodec&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Int&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;].encode(&lt;/span&gt;&lt;span style=&quot;color:#DF69BA&quot;&gt;2021&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    ).asJava)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    .build()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;obtaining-class-field-names-macros&quot;&gt;Obtaining class field names. Macros&lt;/h2&gt;

&lt;p&gt;Our next step is the derivation of the attribute names based on the case class field names.
When we complete implementing this macro, the code will use fields instead of strings.&lt;/p&gt;
&lt;pre class=&quot;shiki everforest-light&quot; style=&quot;background-color:#fdf6e3;color:#5c6a72&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;ddb.putItem(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;  PutItemRequest&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.builder()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    .tableName(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;TableName&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    .item(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Map&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;      FieldName&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;NewYear&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;](_.year) &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; AttributeCodec&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Int&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;].encode(year.year),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;      FieldName&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;NewYear&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;](_.wish) &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; AttributeCodec&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;].encode(year.wish)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    ).asJava)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    .build()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;val&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; item &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; ddb.getItem(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;  GetItemRequest&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.builder()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    .tableName(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;TableName&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    .key(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Map&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;      FieldName&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;NewYear&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;](_.year) &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; AttributeCodec&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Int&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;].encode(&lt;/span&gt;&lt;span style=&quot;color:#DF69BA&quot;&gt;2021&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    ).asJava)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    .build()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;As you can see the attribute name is defined via the accessor of the field &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FieldName[NewYear](_.year)&lt;/code&gt;. 
The automatic acquisition of the field name is performed with a &lt;a href=&quot;https://dotty.epfl.ch/docs/reference/metaprogramming/macros.html&quot;&gt;macro&lt;/a&gt;:&lt;/p&gt;
&lt;pre class=&quot;shiki everforest-light&quot; style=&quot;background-color:#fdf6e3;color:#5c6a72&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;inline&lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt; def&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; apply&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;](&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;inline&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; f: &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; Any&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; String&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;{getName(&lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;f)}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;apply&lt;/code&gt; method that is defined with the modifier &lt;a href=&quot;https://dotty.epfl.ch/docs/reference/metaprogramming/inline.html&quot;&gt;inline&lt;/a&gt; and calls the macro implementation &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getName&lt;/code&gt;.
The methods that are implemented via macros are always required to be defined with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;inline&lt;/code&gt; modifier. 
The second &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;inline&lt;/code&gt; modifier on the parameter is optional. Let’s look at a simple example to understand why it’s needed in this situation.
The following code prints the parameter that is passed to the method:&lt;/p&gt;
&lt;pre class=&quot;shiki everforest-light&quot; style=&quot;background-color:#fdf6e3;color:#5c6a72&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#35A77C&quot;&gt; scala&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#35A77C&quot;&gt;quoted&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#35A77C&quot;&gt;_&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;object&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; InlineFunctions&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;  inline&lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt; def&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; showExpr&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(expr: &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Any&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; String&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;{showExprImpl(&lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;expr)}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;  inline&lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt; def&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; showExprInlined&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;inline&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; expr: &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Any&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; String&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;{showExprImpl(&lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;expr)}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;  private&lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt; def&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; showExprImpl&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(expr: &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Expr&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Any&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;])(&lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; Quotes&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; Expr&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;    &apos;&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;{ &lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Expr&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(expr.show)} &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; &quot; = &quot;&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; $expr }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The implementation of the macro is defined in the method &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;showExprImpl&lt;/code&gt;. The first parameter has the type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Expr&lt;/code&gt;. 
This type represents the abstract syntax tree for all the constructs that compose our code. For example, it’s subtype &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Literal&lt;/code&gt; represents a single value, and the subtype &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Block&lt;/code&gt; contains multiple statements.
The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;${expr}&lt;/code&gt; is the same as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$expr&lt;/code&gt;. It’s called “splicing” and calculates the value of an expression. For example, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;${Expr(&quot;hello&quot;)}&lt;/code&gt; is just the string &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hello&lt;/code&gt;.
The transformation can be reversed with the use of quotes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;{expr}&lt;/code&gt; which is the same as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;expr&lt;/code&gt;. Thus &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;{&quot;hello&quot;}&lt;/code&gt; is equal to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Expr(&quot;hello&quot;)&lt;/code&gt;.
In essence the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;showExprImpl&lt;/code&gt; prints the string representation of the expression and its value using the splices and quotes. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Quotes&lt;/code&gt; context parameter contains some low-level operations and is used implicitly by these operations.
I defined 2 different functions: one with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;inline&lt;/code&gt; parameter and another one without it. Let’s call them and see the output.&lt;/p&gt;
&lt;pre class=&quot;shiki everforest-light&quot; style=&quot;background-color:#fdf6e3;color:#5c6a72&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; InlineFunctions&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#35A77C&quot;&gt;_&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;object&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; InlineMain&lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt; extends&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; App&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;  val&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; a &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#DF69BA&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;  val&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; b &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#DF69BA&quot;&gt; 2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;  println(showExprInlined(a &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; b))  &lt;/span&gt;&lt;span style=&quot;color:#939F91;font-style:italic&quot;&gt;//  demo.inline.InlineMain.a.+(demo.inline.InlineMain.b) = 3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;  println(showExpr(a &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; b))  &lt;/span&gt;&lt;span style=&quot;color:#939F91;font-style:italic&quot;&gt;// expr$proxy2 = 3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The value of the sum operation is the same. The expressions that are passed to our macro are different though.
The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;inline&lt;/code&gt; modifier preserves the original expression. That’s exactly what we need in order to get the field name from the function such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(w:NewYear) =&amp;gt; w.year&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;After we had a quick look at the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;inline&lt;/code&gt; modifier, splices, and quotes, it’s time to move on and implement the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getName&lt;/code&gt; method.&lt;/p&gt;
&lt;pre class=&quot;shiki everforest-light&quot; style=&quot;background-color:#fdf6e3;color:#5c6a72&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;private&lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt; def&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; getName&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;](f: &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Expr&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; Any&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;])(&lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; Type&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;], &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Quotes&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; Expr&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;  import&lt;/span&gt;&lt;span style=&quot;color:#35A77C&quot;&gt; quotes&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#35A77C&quot;&gt;reflect&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#35A77C&quot;&gt;_&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;  val&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; acc &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt; new&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; TreeAccumulator&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;] {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;    def&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; foldTree&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(names: &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;, tree: &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Tree&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)(owner: &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Symbol&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; String&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; tree &lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt;match&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;      case&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; Select&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(_, name) &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; name&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;      case&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; _ &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; foldOverTree(names, tree)(owner)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;  val&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; fieldName &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; acc.foldTree(&lt;/span&gt;&lt;span style=&quot;color:#3A94C5&quot;&gt;null&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;, f.asTerm)(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Symbol&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.spliceOwner)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;  Expr&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(fieldName)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In the implementation, we dived even deeper into the Scala magic by calling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f.asTerm&lt;/code&gt; so as to get access to the AST that the compiler sees.
This is so-called &lt;a href=&quot;https://dotty.epfl.ch/docs/reference/metaprogramming/tasty-reflect.html&quot;&gt;TASTy Reflect&lt;/a&gt;. It provides an even more comprehensive view of the structure of the code. 
The power comes with a cost. Using TASTy Reflect can break type correctness guarantees and may fail at macro expansion time.
In this particular use case, we are safe because we are only interested in reading the syntax tree, not in its modification.
The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.asTerm&lt;/code&gt; call produces the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Tree&lt;/code&gt; instance. Similarly to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Expr&lt;/code&gt;, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Tree&lt;/code&gt; has multiple subclasses that together represent our code.
For instance, the call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FieldName[NewYear](_.year)&lt;/code&gt; is expanded to&lt;/p&gt;
&lt;pre class=&quot;shiki everforest-light&quot; style=&quot;background-color:#fdf6e3;color:#5c6a72&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Inlined&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;EmptyTree&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;List&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(),&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Block&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;List&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;DefDef&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;($anonfun,&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;List&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(),&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;List&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;List&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;ValDef&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(_$&lt;/span&gt;&lt;span style=&quot;color:#DF69BA&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;TypeTree&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;TypeRef&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;ThisType&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;TypeRef&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;NoPrefix&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;,module &lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; demo&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)),&lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; NewYear&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)],&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;EmptyTree&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;))),&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;TypeTree&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;TypeRef&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;TermRef&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;ThisType&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;TypeRef&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;NoPrefix&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;,module &lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;root&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)),module scala),&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Any&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)],&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Select&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Ident&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(_$&lt;/span&gt;&lt;span style=&quot;color:#DF69BA&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;),year))),&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Closure&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;List&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(),&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Ident&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;($anonfun),&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;EmptyTree&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This AST has quite many nesting levels. That’s why we use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TreeAccumulator&lt;/code&gt; that traverses this tree for us.
When the traversal reaches the desired &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Select&lt;/code&gt; instance, it returns the name of the field.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NewYear&lt;/code&gt; has a method defined outside the constructor and in the current implementation the call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FieldName[NewYear](_.gift)&lt;/code&gt; is perfectly valid. It returns the string &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gift&lt;/code&gt; even though the field is not defined in the primary constructor. 
In order to prevent any fields and methods to be passed into the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getName&lt;/code&gt; method, we define a compile-time validation that issues a compilation error when the field is not a part of the primary constructor.
Here is the final implementation of the macro including the validation:&lt;/p&gt;
&lt;pre class=&quot;shiki everforest-light&quot; style=&quot;background-color:#fdf6e3;color:#5c6a72&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#35A77C&quot;&gt; scala&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#35A77C&quot;&gt;quoted&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Expr&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.{&lt;/span&gt;&lt;span style=&quot;color:#35A77C&quot;&gt;ofTuple&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#35A77C&quot;&gt;summon&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#35A77C&quot;&gt; scala&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#35A77C&quot;&gt;quoted&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#35A77C&quot;&gt;_&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;object&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; FieldName&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;  inline&lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt; def&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; apply&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;](&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;inline&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; f: &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; Any&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; String&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;{getName(&lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;f)}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;  private&lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt; def&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; getName&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;](f: &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Expr&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; Any&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;])(&lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; Type&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;], &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Quotes&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; Expr&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;    import&lt;/span&gt;&lt;span style=&quot;color:#35A77C&quot;&gt; quotes&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#35A77C&quot;&gt;reflect&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#35A77C&quot;&gt;_&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;    val&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; acc &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt; new&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; TreeAccumulator&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;] {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;      def&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; foldTree&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(names: &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;, tree: &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Tree&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)(owner: &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Symbol&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; String&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; tree &lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt;match&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;        case&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; Select&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(_, name) &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; name&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;        case&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; _ &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; foldOverTree(names, tree)(owner)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;    val&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; fieldName &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; acc.foldTree(&lt;/span&gt;&lt;span style=&quot;color:#3A94C5&quot;&gt;null&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;, f.asTerm)(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Symbol&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.spliceOwner)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;    val&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; primaryConstructorFields &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; TypeTree&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.of[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;].symbol.caseFields.map(_.name)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;!&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;primaryConstructorFields.contains(fieldName))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;      report.error(&lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt;s&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;&quot;The field &apos;&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;fieldName&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;&apos; is not one of the primary constructor parameter.&quot;&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;, f)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;    Expr&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(fieldName)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;avoiding-map-construction-type-class-derivation&quot;&gt;Avoiding map construction. Type class derivation&lt;/h2&gt;

&lt;p&gt;Earlier in this article, I mentioned that it is crucial to know how to derive the field name and omit to have the attribute names as strings.
The reason is that we will be generating the map based on the case class.&lt;/p&gt;
&lt;pre class=&quot;shiki everforest-light&quot; style=&quot;background-color:#fdf6e3;color:#5c6a72&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;trait&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; ItemCodec&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;] {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; encode&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(t: &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; Map&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;AttributeValue&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There will be an instance of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ItemCodec&lt;/code&gt; trait created for any case class. Unlike &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AttributeCodec&lt;/code&gt;, which had the explicitly defined instances, the type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ItemCodec&lt;/code&gt; instances are derived automatically.
In Scala 2 you would use libraries like Magnolia in order to construct the macros and generate these instances. Scala 3 introduces some convenience utilities in the language itself.
One of them is the trait &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Mirror&lt;/code&gt;. The language provides an instance of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Mirror.Product&lt;/code&gt; for every case class. For our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NewYear&lt;/code&gt; the implementation of this trait looks like this:&lt;/p&gt;
&lt;pre class=&quot;shiki everforest-light&quot; style=&quot;background-color:#fdf6e3;color:#5c6a72&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; NewYearMirror&lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt; extends&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; Mirror&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;  type&lt;/span&gt;&lt;span style=&quot;color:#3A94C5&quot;&gt; MirroredMonoType&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;    =&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; NewYear&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;  type&lt;/span&gt;&lt;span style=&quot;color:#3A94C5&quot;&gt; MirroredLabel&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;       =&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; &quot;NewYear&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;  type&lt;/span&gt;&lt;span style=&quot;color:#3A94C5&quot;&gt; MirroredElemLabels&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;  =&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;&quot;year&quot;&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;&quot;wish&quot;&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;  type&lt;/span&gt;&lt;span style=&quot;color:#3A94C5&quot;&gt; MirroredElemTypes&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;   =&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Int&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;What we need to do is go field by field, and encode every field into the format that the DynamoDb client understands:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;for every field get the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AttributeCodec&lt;/code&gt;. For example, for the field &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;year&lt;/code&gt; we need to summon an instance &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AttributeCodec[Int]&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;set the encoded value in the map with the key &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;year&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NewYearMirror&lt;/code&gt; provides enough information to write such a type class derivation, because we have both field names and field types.&lt;/p&gt;
&lt;pre class=&quot;shiki everforest-light&quot; style=&quot;background-color:#fdf6e3;color:#5c6a72&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;private&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; inline&lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt; def&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; getAttributeNamesAndCodecs&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;N&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; &amp;#x3C;:&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; Tuple&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; &amp;#x3C;:&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; Tuple&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; List&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;AttributeCodec&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Any&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;])] &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;  inline&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; (erasedValue[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;N&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;], erasedValue[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;]) &lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt;match&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;    case&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; (_: &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;EmptyTuple&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;, _: &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;EmptyTuple&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; Nil&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;    case&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; (_: (nameHead &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;*:&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; nameTail), _: (typeHead &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;*:&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; typeTail)) &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;      val&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; attributeLabel &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; constValue[nameHead].toString&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;      val&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; attributeCodec &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; summonInline[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;AttributeCodec&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[typeHead]].&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;asInstanceOf&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;AttributeCodec&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Any&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;]]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;      (attributeLabel, attributeCodec) &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; getAttributeNamesAndCodecs[nameTail, typeTail]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;inline&lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt; given&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; derived[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; &amp;#x3C;:&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; Product&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;](&lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; m: &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Mirror&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;ProductOf&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;])&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; ItemCodec&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;  val&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; namesAndCodecs &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; getAttributeNamesAndCodecs[m.&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;MirroredElemLabels&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;, m.&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;MirroredElemTypes&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;  new&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; ItemCodec&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;] {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;    override&lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt; def&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; encode&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(t: &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; Map&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;AttributeValue&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;      namesAndCodecs.zip(t.productIterator)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;        .map { &lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; ((name, codec), value) &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;          name &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; codec.encode(value)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;        .toMap&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The most interesting parts of these two methods are how to go over fields one by one, and how to transform the field type to be a value.&lt;/p&gt;

&lt;p&gt;Let’s understand the traversal first. We have a type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;type MirroredElemLabels  = (&quot;year&quot;, &quot;wish&quot;)&lt;/code&gt; which is a tuple. 
In Scala 3 there is an extractor for the tuple type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*:&lt;/code&gt;. It works the same way as for sequences so that there are a head and a tail element. 
In order to pattern match the tuple, we need to have its value. The &lt;a href=&quot;https://dotty.epfl.ch/docs/reference/metaprogramming/inline.html#erasedvalue&quot;&gt;erasedValue&lt;/a&gt; pretends to give us the value.  In fact, it would always raise a NotImplementedError exception when called.
That’s why we only pattern match the types and don’t use the values of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;erasedValue&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The second puzzle is how it’s possible to have the type of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;year&quot;&lt;/code&gt; instead of a type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;String&lt;/code&gt;, and how to transform the type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;year&quot;&lt;/code&gt; to the value &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;year&lt;/code&gt;.
In Scala 3 there are singleton types that’s why the type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;year&quot;&lt;/code&gt; is valid. These types have only one instance, in this case, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;year&lt;/code&gt;. In order to acquire this value we call the function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;constValue&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;convenience-operators-extension-methods&quot;&gt;Convenience operators. Extension methods&lt;/h2&gt;

&lt;p&gt;All the planned functional improvements have been implemented. We can only add some operators to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GetItemRequest&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PutItemRequest&lt;/code&gt; as if they were natively scala.
Scala 2 approach is to define the implicit classes that wrap the objects and expose additional methods on them.
Scala 3 has a dedicated keyword for adding such operators. It’s called &lt;a href=&quot;https://dotty.epfl.ch/docs/reference/contextual/extension-methods.html&quot;&gt;extension methods&lt;/a&gt;.&lt;/p&gt;
&lt;pre class=&quot;shiki everforest-light&quot; style=&quot;background-color:#fdf6e3;color:#5c6a72&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;extension[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;] (b: &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;GetItemRequest&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Builder&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;  inline&lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt; def&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; key&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; GetItemRequestBuilderExtension&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;    new&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; GetItemRequestBuilderExtension&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;](b)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; GetItemRequestBuilderExtension&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;](b: &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;GetItemRequest&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Builder&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;  inline&lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt; def&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; apply&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;A&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; AttributeCodec&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;](&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;inline&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; k: &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; A&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;, v: &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;A&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; GetItemRequest&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Builder&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; =&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    b.key(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Map&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;      FieldName&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;](k) &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; AttributeCodec&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;A&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;].encode(v)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    ).asJava)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;extension[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; ItemCodec&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;] (b: &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;PutItemRequest&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Builder&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; item&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(t: &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; PutItemRequest&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Builder&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; =&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    b.item(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;ItemCodec&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;].encode(t).asJava)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here is the resulting code that uses this syntactic sugar.&lt;/p&gt;
&lt;pre class=&quot;shiki everforest-light&quot; style=&quot;background-color:#fdf6e3;color:#5c6a72&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;ddb.putItem(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;  PutItemRequest&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.builder()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    .tableName(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;TableName&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    .item(year)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    .build()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;val&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; item &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; ddb.getItem(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;  GetItemRequest&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.builder()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    .tableName(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;TableName&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    .key[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;NewYear&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;](_.year, &lt;/span&gt;&lt;span style=&quot;color:#DF69BA&quot;&gt;2021&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    .build()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;In this article, we got acquainted with some Scala 3 features based on a real world example of using the DynamoDb client.
We also had a gentle introduction to the macros and type class derivations. If you need more information around this topic, then take a look at &lt;a href=&quot;https://blog.philipp-martini.de/blog/magic-mirror-scala3/&quot;&gt;this arctile&lt;/a&gt; 
and &lt;a href=&quot;https://lampepfl.github.io/scala3-macro-tutorial/&quot;&gt;the macro tutorial&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The result of the exercise that is described in this article is in &lt;a href=&quot;https://github.com/melgenek/dotty-dynamodb&quot;&gt;github&lt;/a&gt;.&lt;/p&gt;
</description>
        <pubDate>Thu, 31 Dec 2020 00:00:00 +0000</pubDate>
        <link>https://melgenek.dev/scala-3-dynamodb</link>
        <guid isPermaLink="true">https://melgenek.dev/scala-3-dynamodb</guid>
      </item>
    
      <item>
        <title>Serverless Tapir</title>
        <description>&lt;p&gt;This blog post could start with a drawing of a tapir that has a pair of tiny angel wings and sits on a cloud.
Unfortunately, I cannot draw. But I can code. So in this article will tell how to run a Tapir program with AWS Lambda
and API Gateway.&lt;/p&gt;

&lt;nav&gt;
  &lt;p&gt;&lt;span class=&quot;toc-title&quot;&gt;Table of Contents&lt;/span&gt;&lt;/p&gt;
&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#introduction&quot; id=&quot;markdown-toc-introduction&quot;&gt;Introduction&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#implementing-the-interpreter&quot; id=&quot;markdown-toc-implementing-the-interpreter&quot;&gt;Implementing the interpreter&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#packaging-the-lambda&quot; id=&quot;markdown-toc-packaging-the-lambda&quot;&gt;Packaging the Lambda&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#deployment&quot; id=&quot;markdown-toc-deployment&quot;&gt;Deployment&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#summary&quot; id=&quot;markdown-toc-summary&quot;&gt;Summary&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;/nav&gt;

&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://tapir.softwaremill.com/en/latest/index.html&quot;&gt;Tapir&lt;/a&gt; is an amazing scala framework that allows defining
http endpoints as scala values. Let’s look at the example that I borrowed from the official documentation:&lt;/p&gt;

&lt;pre class=&quot;shiki everforest-light&quot; style=&quot;background-color:#fdf6e3;color:#5c6a72&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#35A77C&quot;&gt; sttp&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#35A77C&quot;&gt;tapir&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#35A77C&quot;&gt;_&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#35A77C&quot;&gt; sttp&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#35A77C&quot;&gt;tapir&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#35A77C&quot;&gt;json&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#35A77C&quot;&gt;circe&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#35A77C&quot;&gt;_&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#35A77C&quot;&gt; io&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#35A77C&quot;&gt;circe&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#35A77C&quot;&gt;generic&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#35A77C&quot;&gt;auto&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#35A77C&quot;&gt;_&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color:#3A94C5&quot;&gt; Limit&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; Int&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color:#3A94C5&quot;&gt; AuthToken&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; String&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; BooksFromYear&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(genre: &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;, year: &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Int&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; Book&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(title: &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;val&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; booksListing&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; Endpoint&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;BooksFromYear&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Limit&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;AuthToken&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;), &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;List&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Book&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;], &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Nothing&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;  endpoint&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    .get&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    .in((&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;&quot;books&quot;&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; /&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; path[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;](&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;&quot;genre&quot;&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; path[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Int&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;](&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;&quot;year&quot;&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)).mapTo(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;BooksFromYear&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    .in(query[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Limit&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;](&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;&quot;limit&quot;&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;).description(&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;&quot;Maximum number of books to retrieve&quot;&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    .in(header[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;AuthToken&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;](&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;&quot;X-Auth-Token&quot;&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    .errorOut(stringBody)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    .out(jsonBody[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;List&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Book&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;]])&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is a representation of a single endpoint with a noticeable feature that it does not have any logic attached.
The endpoint is solely a description of input parameters and outputs like response bodies.&lt;/p&gt;

&lt;p&gt;In order to make this definition runnable, we have to use an interpreter. 
Here is an example implementation in akka-http:&lt;/p&gt;

&lt;pre class=&quot;shiki everforest-light&quot; style=&quot;background-color:#fdf6e3;color:#5c6a72&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#35A77C&quot;&gt; sttp&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#35A77C&quot;&gt;tapir&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#35A77C&quot;&gt;server&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#35A77C&quot;&gt;akkahttp&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#35A77C&quot;&gt;_&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#35A77C&quot;&gt; akka&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#35A77C&quot;&gt;http&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#35A77C&quot;&gt;scaladsl&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#35A77C&quot;&gt;server&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Route&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#35A77C&quot;&gt; scala&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#35A77C&quot;&gt;concurrent&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Future&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;val&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; booksListingRoute&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; Route&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; =&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    booksListing.toRoute { &lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; (bfy: &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;BooksFromYear&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;, limit: &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Limit&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;, at: &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;AuthToken&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;      Future&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.successful(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Right&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;List&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Book&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;&quot;The Sorrows of Young Werther&quot;&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;))))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The logic of the route is generic, there is no explicit use of the akka-http response codes or marshallers.
There are in fact many options of server interpreters such as play, http4s, finatra and vert.x.
However, these frameworks help only with writing the code. The next steps are most likely the docker packaging,
the definition of the kubernetes manifests and deployment scripts.&lt;/p&gt;

&lt;p&gt;Deploying an application takes a signification amount of effort.
I want to have the code up and running quickly and easily, preferably with a single bash command. 
Tapir, AWS Lambda and &lt;a href=&quot;https://github.com/aws/aws-cdk&quot;&gt;AWS CDK&lt;/a&gt; will help me with this venture. The complete code can be
found in &lt;a href=&quot;https://github.com/melgenek/serverless-tapir&quot;&gt;the github repo&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;implementing-the-interpreter&quot;&gt;Implementing the interpreter&lt;/h2&gt;

&lt;p&gt;We start with an interpreter that transform Tapir code in an AWS Lambda. We will follow these steps:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;define the logic to transform a Tapir request into the Lambda-specific request.&lt;/li&gt;
  &lt;li&gt;then Tapir parses this request and gives me the inputs like query and path params, an input body and headers.&lt;/li&gt;
  &lt;li&gt;the next step is to execute the user-defined logic using these inputs as arguments.&lt;/li&gt;
  &lt;li&gt;finally, the response from the user-defined logic is transformed back into the response that Lambda understands.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;AWs Lambda itself does not know anything about http. It is just an execution environment.
We utilize the API Gateway &lt;a href=&quot;https://docs.aws.amazon.com/apigateway/latest/developerguide/welcome.html&quot;&gt;Http API&lt;/a&gt;.
It parses the request and invokes our lambda as soon as the request is ready to be processed.
Http API passes the parsed request &lt;a href=&quot;https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html&quot;&gt;in a predefined format&lt;/a&gt;.
I use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;com.amazonaws&quot; % &quot;aws-lambda-java-events&quot;&lt;/code&gt; to have the predefined java classes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;APIGatewayV2HTTPEvent&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;APIGatewayV2HTTPResponse&lt;/code&gt;
that correspond to the Http API request and response models.&lt;/p&gt;

&lt;p&gt;As mentioned above the implementation starts mapping the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;APIGatewayV2HTTPEvent&lt;/code&gt; into Tapir’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ServerRequest&lt;/code&gt;.&lt;/p&gt;

&lt;pre class=&quot;shiki everforest-light&quot; style=&quot;background-color:#fdf6e3;color:#5c6a72&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; HttpApiServerRequest&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(event: &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;APIGatewayV2HTTPEvent&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt;extends&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; ServerRequest&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; method&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; Method&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; Method&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(event.getRequestContext.getHttp.getMethod.toUpperCase)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; protocol&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; String&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; event.getRequestContext.getHttp.getProtocol&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; uri&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; URI&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; =&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;    new&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; URI&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt;s&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;&quot;https://&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;${&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;event.getRequestContext.getDomainName&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;}${&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;event.getRawPath&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;${&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;event.getRawQueryString&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; connectionInfo&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; ConnectionInfo&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; ConnectionInfo&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    local &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; None&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    remote &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; Some&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;InetSocketAddress&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.createUnresolved(event.getRequestContext.getHttp.getSourceIp, &lt;/span&gt;&lt;span style=&quot;color:#DF69BA&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    secure &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; Some&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#3A94C5&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;  )&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;  lazy&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; val&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; headers&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; Seq&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)] &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; event.getHeaders.asScala.toList&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; header&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(name: &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; Option&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; event.getHeaders.getIgnoreCase(name)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;A couple of moments are worth clarification here.&lt;/p&gt;

&lt;p&gt;First of all, Http API passes all the headers with lower cased names, so the header lookup is done ignoring the case.&lt;/p&gt;

&lt;p&gt;Secondly, in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ConnectionInfo&lt;/code&gt; we have only the remote client, there is no port given to the lambda. 
The communication to Http API is always secure.&lt;/p&gt;

&lt;p&gt;The next step after defining the server request is the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DecodeInputsContext&lt;/code&gt;. 
As the name suggests, this class is used by Tapir during the inputs extraction.&lt;/p&gt;

&lt;pre class=&quot;shiki everforest-light&quot; style=&quot;background-color:#fdf6e3;color:#5c6a72&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; HttpApiDecodeInputsContext&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(event: &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;APIGatewayV2HTTPEvent&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;, pathConsumed: &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Int&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#DF69BA&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt;extends&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; DecodeInputsContext&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; method&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; Method&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; Method&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(event.getRequestContext.getHttp.getMethod.toUpperCase)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; nextPathSegment&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Option&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;], &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;DecodeInputsContext&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;    val&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; path &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; event.getRawPath.drop(pathConsumed)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;    val&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; nextStart &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; path.dropWhile(_ &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; &apos;&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;    val&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; segment &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; nextStart.split(&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;&quot;/&quot;&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#DF69BA&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt;match&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;      case&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; Array&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; None&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;      case&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; Array&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(s) &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; Some&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(s)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;      case&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; Array&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(s, _) &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; Some&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(s)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;    val&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; charactersConsumed &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; segment.map(_.length).getOrElse(&lt;/span&gt;&lt;span style=&quot;color:#DF69BA&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; (path.length &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; nextStart.length)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    (segment, &lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; HttpApiDecodeInputsContext&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(event, pathConsumed &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; charactersConsumed))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; header&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(name: &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; List&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    event.getHeaders.getIgnoreCase(name).flatMap(_.split(&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;&quot;,&quot;&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;).toList).toList&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; headers&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; Seq&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)] &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; event.getHeaders.asScala.toList&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; queryParameter&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(name: &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; Seq&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    event.getQueryStringParameters.getIgnoreCase(name).flatMap(_.split(&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;&quot;,&quot;&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;).toList).toList&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; queryParameters&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; QueryParams&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; QueryParams&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.fromMap(event.getQueryStringParameters.asScala.toMap)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; bodyStream&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; Any&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; =&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;    throw&lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt; new&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; UnsupportedOperationException&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;&quot;Trying to read streaming body from a non-streaming request&quot;&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; serverRequest&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; ServerRequest&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt; new&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; HttpApiServerRequest&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(event)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Multivalued headers and query params are combined with commas in Http API. So we split them back into a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;List&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The body is always passed into the lambda as a string so the whole incoming request is consumed before the lambda invocation.
That’s why the body cannot be streamed, and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bodyStream&lt;/code&gt; has no implementation.&lt;/p&gt;

&lt;p&gt;Now that we know how to map the lambda input into the input that Tapir understands, let’s implement the routes.
The same way akka http has &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;akka.http.scaladsl.server.Route&lt;/code&gt;, or http4s has &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;org.http4s.HttpRoutes&lt;/code&gt;, we will also
have a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Route&lt;/code&gt; type:&lt;/p&gt;

&lt;pre class=&quot;shiki everforest-light&quot; style=&quot;background-color:#fdf6e3;color:#5c6a72&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color:#3A94C5&quot;&gt; Route&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; PartialFunction&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;APIGatewayV2HTTPEvent&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;APIGatewayV2HTTPResponse&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Tapir also requires a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MonadError&lt;/code&gt; implementation. For akka http there is an instance of a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MonadError&lt;/code&gt; based on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Future&lt;/code&gt;.
That’s why the akka http routes return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Futures&lt;/code&gt; as results. A lambda function that runs on top of the Lambda Java runtime requires
functions to be simple blocking functions with a signature &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;def onEvent(event: APIGatewayV2HTTPEvent): APIGatewayV2HTTPResponse&lt;/code&gt;.
I chose &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Try&lt;/code&gt; to be the result type of the Lambda logic. The example conversion of a function with some business logic
into a Lambda route would be:&lt;/p&gt;

&lt;pre class=&quot;shiki everforest-light&quot; style=&quot;background-color:#fdf6e3;color:#5c6a72&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#35A77C&quot;&gt; scala&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#35A77C&quot;&gt;util&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.{&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Success&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Try&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#35A77C&quot;&gt; sttp&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#35A77C&quot;&gt;tapir&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#35A77C&quot;&gt;server&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#35A77C&quot;&gt;httpapi&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#35A77C&quot;&gt;_&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;def&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; logic&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(bfy: &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;BooksFromYear&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;, limit: &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Limit&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;, at: &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;AuthToken&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; Try&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Either&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;List&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Book&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;]]] &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;  Success&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Right&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;List&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Book&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;&quot;The Sorrows of Young Werther&quot;&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;))))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;val&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; serverEndpoint &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; bookListing.serverLogic((logic _).tupled)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;val&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; booksListingRoute&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; Route&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; serverEndpoint.toRoute&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Route&lt;/code&gt; is a partial function. If the http request matches the Tapir endpoint definition then we execute the logic for
this endpoint. If no then we try another route. This check is expressed via the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isDefinedAt&lt;/code&gt; method of the partial function.
We use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sttp.tapir.server.internal.DecodeInputs&lt;/code&gt;, pass the context and let Tapir parse the request for us.&lt;/p&gt;

&lt;pre class=&quot;shiki everforest-light&quot; style=&quot;background-color:#fdf6e3;color:#5c6a72&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;def&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; isDefinedAt&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(event: &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;APIGatewayV2HTTPEvent&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; Boolean&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;  DecodeInputs&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(e.input, &lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; HttpApiDecodeInputsContext&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(event)) &lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt;match&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;    case&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; _: &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;DecodeInputsResult&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Values&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#3A94C5&quot;&gt; true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;    case&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; _: &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;DecodeInputsResult&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Failure&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#3A94C5&quot;&gt; false&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;When the http request matches our endpoint, it’s time to run the actual application logic. The result of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DecodeInputs&lt;/code&gt;
is just a sequence of values. Thus, we map these values into scala classes, so that we get a tuple of case classes,
like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(BooksFromYear, Limit, AuthToken)&lt;/code&gt; in the example above. This conversion is the responsibility of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sttp.tapir.server.internal.InputValues&lt;/code&gt;.&lt;/p&gt;

&lt;pre class=&quot;shiki everforest-light&quot; style=&quot;background-color:#fdf6e3;color:#5c6a72&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;def&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; apply&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(event: &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;APIGatewayV2HTTPEvent&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; APIGatewayV2HTTPResponse&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;  DecodeInputs&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(e.input, &lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; HttpApiDecodeInputsContext&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(event)) &lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt;match&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;    case&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; values: &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;DecodeInputsResult&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Values&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;      InputValues&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(e.input, values) &lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt;match&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;        case&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; InputValuesResult&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Value&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(params, _) &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; valueToResponse(params.asAny)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;        case&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; InputValuesResult&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Failure&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(input, failure) &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; handleDecodeFailure(input, failure)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;    case&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; DecodeInputsResult&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Failure&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(input, failure) &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; handleDecodeFailure(input, failure)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The next step, after the inputs are successfully parsed, is to pass these inputs into the user-defined logic.&lt;/p&gt;

&lt;pre class=&quot;shiki everforest-light&quot; style=&quot;background-color:#fdf6e3;color:#5c6a72&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;def&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; valueToResponse&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(value: &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Any&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; APIGatewayV2HTTPResponse&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;  endpoint.logic(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;TryMonadError&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)(value.&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;asInstanceOf&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;I&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;]) &lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt;match&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;    case&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; Success&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Right&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(result)) &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; OutputToHttpApiResponse&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;ServerDefaults&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;StatusCodes&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.success, endpoint.output, result)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;    case&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; Success&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Left&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(err)) &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; OutputToHttpApiResponse&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;ServerDefaults&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;StatusCodes&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.error, endpoint.errorOutput, err)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;    case&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; Failure&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(e) &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; OutputToHttpApiResponse&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;StatusCode&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;InternalServerError&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;, e.getMessage)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The only thing left is to map the Tapir’s output to the response type that Http API understands. 
This is what &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OutputToHttpApiResponse&lt;/code&gt; does in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;valueToResponse&lt;/code&gt; method. The implementation requires some lines of code and 
it can be found &lt;a href=&quot;https://github.com/melgenek/serverless-tapir/blob/master/lambda/src/main/scala/sttp/tapir/server/httpapi/OutputToHttpApiResponse.scala&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We put the functionality that is described in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;toRoute&lt;/code&gt; function. 
The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Route&lt;/code&gt; is a partial function, so we can compose multiple routes into a single one via the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;orElse&lt;/code&gt; method.
If none of the routes matches the request, we use the predefined &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EmptyRoute&lt;/code&gt; that answers with the 404 response code.&lt;/p&gt;

&lt;pre class=&quot;shiki everforest-light&quot; style=&quot;background-color:#fdf6e3;color:#5c6a72&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;implicit&lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; RichHttpApiServerEndpoint&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;I&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;E&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;O&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;](endpoint: &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;ServerEndpoint&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;I&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;E&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;O&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Nothing&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Try&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;]) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; toRoute&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; Route&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#939F91;font-style:italic&quot;&gt;    // the partial function that is described above&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;implicit&lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; RichHttpApiServerEndpoints&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;I&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;E&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;O&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;](serverEndpoints: &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;List&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;ServerEndpoint&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[_, _, _, &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Nothing&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Try&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;]]) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; toRoutes&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; Route&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    serverEndpoints&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;      .map(_.toRoute)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;      .foldRight(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;EmptyRoute&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)(_ orElse _)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Let’s also provide an interface that has to be implemented in order to have a complete lambda. This interface requires
a list of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ServerEndpoints&lt;/code&gt; and then uses these endpoints to process a request.&lt;/p&gt;

&lt;pre class=&quot;shiki everforest-light&quot; style=&quot;background-color:#fdf6e3;color:#5c6a72&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;trait&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; HttpApiFunction&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;  val&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; serverEndpoints&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; List&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;ServerEndpoint&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[_, _, _, &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Nothing&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Try&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;]]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; onEvent&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(event: &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;APIGatewayV2HTTPEvent&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; APIGatewayV2HTTPResponse&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    serverEndpoints.toRoutes(event)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;object&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; BookFunction&lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt; extends&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; HttpApiFunction&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;  override&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; val&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; serverEndpoints &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; List&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(booksListingRoute)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Lambdas will have the handler that points to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;your.package.BookFunction::onEvent&lt;/code&gt;. The class will be instantiated
by the Java runtime and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;onEvent&lt;/code&gt; function will be invoked for every http request.&lt;/p&gt;

&lt;h2 id=&quot;packaging-the-lambda&quot;&gt;Packaging the Lambda&lt;/h2&gt;

&lt;p&gt;I am not using lambda layers, so the Lambda function has to contain all of the dependencies.
The fat jar is packaged using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sbt-assembly&lt;/code&gt; plugin. The only interesting part of this process is the merge conflict resolution.
The reference configurations are concatenated, and some files with conflict names are discarded.&lt;/p&gt;

&lt;pre class=&quot;shiki everforest-light&quot; style=&quot;background-color:#fdf6e3;color:#5c6a72&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;assemblyMergeStrategy in assembly &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;  case&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; PathList&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;&quot;META-INF&quot;&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;, _@&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;_*&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; MergeStrategy&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.discard&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;  case&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; PathList&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(ps&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;@_*&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; ps.last endsWith &lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;&quot;reference-overrides.conf&quot;&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; MergeStrategy&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.concat&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;  case&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; PathList&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(ps&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;@_*&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; ps.last endsWith &lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;&quot;module-info.class&quot;&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; MergeStrategy&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.discard&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;  case&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;    val&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; oldStrategy &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; (assemblyMergeStrategy in assembly).value&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    oldStrategy(x)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;deployment&quot;&gt;Deployment&lt;/h2&gt;

&lt;p&gt;The interpreter is ready, it can be used to compose Tapir endpoints together into a single &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Route&lt;/code&gt;. The Lambda
function is also bundled into a fat jar. Everything is ready for uploading and running this jar. We can go into the AWS ui,
click a couple of buttons, create the lambda and upload the code. However, this is a manual process. The whole idea of the experiment,
that is described in this article, is to have an easy and automatic process of deploying applications.&lt;/p&gt;

&lt;p&gt;In order to automate the lambda creation process, we will use &lt;a href=&quot;https://github.com/aws/aws-cdk&quot;&gt;AWS Cloud Development Kit&lt;/a&gt;.
This is a tool that allows defining the AWS infrastructure in Java and transforming this definition into CloudFormation stacks.
CloudFormation then makes sure that the infrastructure is created in AWS.&lt;/p&gt;

&lt;p&gt;Let’s create a function that receives an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HttpApiFunction&lt;/code&gt; and the name of the Lambda function. This function creates a so-called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;App&lt;/code&gt;,
that contains all the resources. Then it synthesizes the Cloudformation template based on the code.&lt;/p&gt;

&lt;pre class=&quot;shiki everforest-light&quot; style=&quot;background-color:#fdf6e3;color:#5c6a72&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;def&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; deploy&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(httpApiFunction: &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;HttpApiFunction&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;, title: &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; Unit&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;  val&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; app &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt; new&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; awscdk.core.&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;App&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;  ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;  app.synth()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;All the resources have scopes. The top-level scope is the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;App&lt;/code&gt;. Each app is a set of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Stacks&lt;/code&gt;. Every &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Stack&lt;/code&gt; corresponds to a Cloudformation
stack. For us, it is enough to create a single Stack.&lt;/p&gt;

&lt;pre class=&quot;shiki everforest-light&quot; style=&quot;background-color:#fdf6e3;color:#5c6a72&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;val&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; stack &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt; new&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; Stack&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(app, &lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt;s&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;title&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;-stack&quot;&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The first meaningful resource that we create is the lambda function. It is a lambda that is based on the Java 8 runtime.
It sets the handler method to be the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;def onEvent(event: APIGatewayV2HTTPEvent): APIGatewayV2HTTPResponse&lt;/code&gt; of our lambda class.
Additionally, we set the local path of the fat jar file that we have bundled. This jar is automatically uploaded by CDK into an s3 bucket.
Then this s3 object is used as the source for the lambda function.&lt;/p&gt;

&lt;pre class=&quot;shiki everforest-light&quot; style=&quot;background-color:#fdf6e3;color:#5c6a72&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;val&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; function &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; lambda.&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Function&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Builder&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.create(stack, &lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt;s&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;title&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;-lambda&quot;&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;  .memorySize(&lt;/span&gt;&lt;span style=&quot;color:#DF69BA&quot;&gt;192&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;  .timeout(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Duration&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.seconds(&lt;/span&gt;&lt;span style=&quot;color:#DF69BA&quot;&gt;30&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;  .functionName(title)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;  .runtime(lambda.&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Runtime&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;JAVA_8&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;  .handler(&lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt;s&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;${&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;httpApiFunction.getClass.getName.replace(&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;&quot;$&quot;&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;::onEvent&quot;&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;  .code(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Code&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.fromAsset(&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;&quot;lambda/target/scala-2.13/assembly.jar&quot;&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;  .build()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;After the lambda is present, we create the API Gateway Http API.&lt;/p&gt;

&lt;pre class=&quot;shiki everforest-light&quot; style=&quot;background-color:#fdf6e3;color:#5c6a72&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;val&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; api &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; HttpApi&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Builder&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.create(stack, &lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt;s&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;title&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;-api&quot;&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;  .apiName(title)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;  .build()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;After both lambda and API are set up, we need to bind them together so that Http API passes the requests into lambda.
For this to happen, we create a Lambda integration.&lt;/p&gt;

&lt;pre class=&quot;shiki everforest-light&quot; style=&quot;background-color:#fdf6e3;color:#5c6a72&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;val&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; integration &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; LambdaProxyIntegration&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Builder&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.create()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;  .handler(function)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;  .payloadFormatVersion(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;PayloadFormatVersion&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;VERSION_2_0&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;  .build()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The last step is to define all the http routes and point them to the same lambda function.
Tapir’s ability to transform endpoints into Open API helps us construct the routes. For every path in the Open API specification,
we create a route in the Http API.&lt;/p&gt;

&lt;pre class=&quot;shiki everforest-light&quot; style=&quot;background-color:#fdf6e3;color:#5c6a72&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#35A77C&quot;&gt; sttp&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#35A77C&quot;&gt;tapir&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#35A77C&quot;&gt;docs&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#35A77C&quot;&gt;openapi&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#35A77C&quot;&gt;_&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;private&lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt; def&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; apiRoutes&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(httpApiFunction: &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;HttpApiFunction&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;, integration: &lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;LambdaProxyIntegration&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; List&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;AddRoutesOptions&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;  val&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; openAPI &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; httpApiFunction.serverEndpoints.map(_.endpoint).toOpenAPI(&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;&quot;any name&quot;&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;&quot;v1&quot;&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;  openAPI.paths&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    .map { &lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; (path, pathItem) &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;    val&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; methods &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;      pathItem.get.map(_ &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; HttpMethod&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;GET&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;++&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;        pathItem.post.map(_ &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; HttpMethod&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;POST&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;++&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;        pathItem.delete.map(_ &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; HttpMethod&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;DELETE&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;    AddRoutesOptions&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.builder()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;      .methods(methods.toList.asJava)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;      .path(path)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;      .integration(integration)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;      .build()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;    .toList&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That’s it. Now we pass our lambda class into the deployment function, run the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cdk deploy&lt;/code&gt; command in the terminal,
and after a short time, our code is up and running in AWS.&lt;/p&gt;

&lt;pre class=&quot;shiki everforest-light&quot; style=&quot;background-color:#fdf6e3;color:#5c6a72&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;object&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; Main&lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt; extends&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; App&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;  HttpApiCdkServer&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.deploy(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;BookFunction&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;&quot;my-bookshop&quot;&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Cdk also allows adding outputs into stacks. One of such outputs can be the url of the Http API that we deployed.&lt;/p&gt;

&lt;pre class=&quot;shiki everforest-light&quot; style=&quot;background-color:#fdf6e3;color:#5c6a72&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;CfnOutput&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;Builder&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;.create(stack, &lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;&quot;api-url&quot;&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;).exportName(&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;&quot;url&quot;&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;).value(api.getUrl).build()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This output is shown after the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cdk deploy&lt;/code&gt; succeeds.&lt;/p&gt;

&lt;pre class=&quot;shiki everforest-light&quot; style=&quot;background-color:#fdf6e3;color:#5c6a72&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;✅&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;  my-bookshop-stack&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;Outputs:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;my-bookshop-stack.apiurl&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; https://2qpnchfg11.execute-api.us-east-1.amazonaws.com/&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Calling this url results in the request being handled by our lambda that is described above.&lt;/p&gt;

&lt;pre class=&quot;shiki everforest-light&quot; style=&quot;background-color:#fdf6e3;color:#5c6a72&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;curl&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; -v&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; -H&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; &quot;X-Auth-Token: Bearer token&quot;&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;  https://2qpnchfg11.execute-api.us-east-1.amazonaws.com/books/novel/2020?limit=&lt;/span&gt;&lt;span style=&quot;color:#DF69BA&quot;&gt;10&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;Result:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;  {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;    &quot;title&quot;&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;&quot;The Sorrows of Young Werther&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;

&lt;p&gt;In this article, I showed how to run the Tapir application in Lambda and automatically deploy the code with CDK.
I believe that the use of CDK brings a lot of benefit into scala applications because it keeps the
infrastructure close to the code. The infrastructure has the same version as the code does. 
This helps us to be sure that the required infrastructure is created at the deployment time. 
In addition, CDK gives a way to deploy with a command.&lt;/p&gt;

&lt;p&gt;The code for this article can be found in &lt;a href=&quot;https://github.com/melgenek/serverless-tapir&quot;&gt;the github repo&lt;/a&gt;.&lt;/p&gt;
</description>
        <pubDate>Wed, 29 Jul 2020 00:00:00 +0000</pubDate>
        <link>https://melgenek.dev/serverless-tapir</link>
        <guid isPermaLink="true">https://melgenek.dev/serverless-tapir</guid>
      </item>
    
      <item>
        <title>Building a video service using Spring Framework</title>
        <description>&lt;p&gt;Some time ago a brand new WebFlux by Spring was released introducing the non-blocking reactive programming paradigm. 
One of the domains to apply this new framework is data streaming, in particular video streaming. 
In this article I’m going to build a video streaming service and describe the threading model that is being used.&lt;/p&gt;

&lt;nav&gt;
  &lt;p&gt;&lt;span class=&quot;toc-title&quot;&gt;Table of Contents&lt;/span&gt;&lt;/p&gt;
&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#byte-range-requests&quot; id=&quot;markdown-toc-byte-range-requests&quot;&gt;Byte-range requests&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#spring-mvc&quot; id=&quot;markdown-toc-spring-mvc&quot;&gt;Spring MVC&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#mvc-drawbacks&quot; id=&quot;markdown-toc-mvc-drawbacks&quot;&gt;MVC drawbacks&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#responding-with-parts-of-data&quot; id=&quot;markdown-toc-responding-with-parts-of-data&quot;&gt;Responding with parts of data&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#spring-webflux&quot; id=&quot;markdown-toc-spring-webflux&quot;&gt;Spring WebFlux&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#conclusion&quot; id=&quot;markdown-toc-conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;/nav&gt;

&lt;h2 id=&quot;byte-range-requests&quot;&gt;Byte-range requests&lt;/h2&gt;

&lt;p&gt;To begin with, let’s investigate how the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;video&amp;gt;&lt;/code&gt; element works and what requests it sends to
a server. For example, &lt;a href=&quot;https://www.w3schools.com/html/html5_video.asp&quot;&gt;w3c has an overview&lt;/a&gt; of this html element with the one embedded. 
The very first request sent to service is as follows:&lt;/p&gt;

&lt;pre class=&quot;shiki everforest-light&quot; style=&quot;background-color:#fdf6e3;color:#5c6a72&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;GET&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; https://www.w3schools.com/html/mov_bbb.mp4&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;Range:&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; bytes=0-&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Generally speaking, it is a simple http GET request. The only additional piece of data that matters is
the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Range&lt;/code&gt; header. It comes from the &lt;a href=&quot;https://tools.ietf.org/html/rfc723&quot;&gt;Range Requests specification&lt;/a&gt; and
asks the server for a specific part of the file. The header in the previous request means that the client expects data
from position 0 in a byte representation of file till the end. 
A Range header can have a final point, e.g. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Range: bytes=50-100&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;There are two possible responses to such a kind of request:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Status: 200 OK. It indicates that the server can’t fulfil the request and is going to respond with a full
resource in one request.&lt;/li&gt;
  &lt;li&gt;Status: 206 Partial Content. In this case server confirms its ability to respond to range requests.
Here are the headers we are interested in:&lt;/li&gt;
&lt;/ul&gt;

&lt;pre class=&quot;shiki everforest-light&quot; style=&quot;background-color:#fdf6e3;color:#5c6a72&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;Status:&lt;/span&gt;&lt;span style=&quot;color:#DF69BA&quot;&gt; 206&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;Accept-ranges:&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; bytes&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;Content-Length:&lt;/span&gt;&lt;span style=&quot;color:#DF69BA&quot;&gt; 100&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;Content-Range:&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; bytes&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; 0-99/788493&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Lets have a closer look at them:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Accept-ranges: bytes&lt;/code&gt;. This one says which range unit is being  used. The most common is &lt;em&gt;bytes&lt;/em&gt;
but RFC allows any other, such as seconds. It can even be &lt;a href=&quot;http://otac0n.com/blog/2012/11/21/range-header-i-choose-you.html&quot;&gt;used for pagination&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Content-Length: 100&lt;/code&gt;. In contrast to status 200 response, which shows the full length of content,
here the stated length refers to the size of the chunk received.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Content-Range: bytes 0-99/788493&lt;/code&gt;. This header shows that we have bytes from 0 to 99 and these are the 100 bytes mentioned in Content-Length header.
The number 788493 after the slash tells us the full size of the file on the server. It is used by a video tag
to figure out when the content is loaded entirely.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Using this simple protocol we can specify any point in a movie to watch. 
Thanks to getting only chunks of data, users don’t need to wait until an entire video is loaded,
which is particularly useful for those with slow connection and per megabyte internet pricing,
as well as for creation of a splendid user experience.&lt;/p&gt;

&lt;h2 id=&quot;spring-mvc&quot;&gt;Spring MVC&lt;/h2&gt;

&lt;p&gt;The classical MVC was in use for a while and has lots and lots of different features and 
specification implementations. &lt;a href=&quot;https://jira.spring.io/browse/SPR-13834&quot;&gt;After version 4.2.4&lt;/a&gt; of Spring,
you can download dynamic files from a server with just a few lines of code. The byte-range support is included as well.
The following code is based on the &lt;strong&gt;mvc&lt;/strong&gt; branch of my &lt;a href=&quot;https://github.com/melgenek/spring-video-service/tree/mvc&quot;&gt;sample project&lt;/a&gt;
and you can find project dependencies in &lt;em&gt;build.gradle&lt;/em&gt; file.
Here is the only piece of code you need to implement your video server:&lt;/p&gt;

&lt;pre class=&quot;shiki everforest-light&quot; style=&quot;background-color:#fdf6e3;color:#5c6a72&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#3A94C5&quot;&gt;@GetMapping&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;&quot;/videos/{name}/full&quot;&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;fun&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; getFullVideo&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#3A94C5&quot;&gt;@PathVariable&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; name: &lt;/span&gt;&lt;span style=&quot;color:#3A94C5&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;): &lt;/span&gt;&lt;span style=&quot;color:#3A94C5&quot;&gt;ResponseEntity&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#3A94C5&quot;&gt;UrlResource&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;	val&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; video &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; UrlResource&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;&quot;file:&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;$videoLocation&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;$name&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;	return&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; ResponseEntity.&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;status&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(HttpStatus.PARTIAL_CONTENT)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;			.&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;contentType&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(MediaTypeFactory&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;					.&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;getMediaType&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(video)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;					.&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;orElse&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(MediaType.APPLICATION_OCTET_STREAM))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;			.&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;body&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(video)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The purpose of the controller send files to client. Let’s explore it line by line:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;@GetMapping&lt;/strong&gt; obviously means that we’re handling GET http requests&lt;/li&gt;
  &lt;li&gt;The method declaration shows that it takes a name of the file as a path parameter and returns a UrlResource which is
just any resource that can be reached by url.&lt;/li&gt;
  &lt;li&gt;Next line creates a resource from url. Resource is in essence an input stream with some additional methods.
&lt;strong&gt;&lt;em&gt;$videoLocation&lt;/em&gt;&lt;/strong&gt; variable comes from environment and is the name of a folder that holds our videos.&lt;/li&gt;
  &lt;li&gt;Then we have &lt;strong&gt;&lt;em&gt;HttpStatus&lt;/em&gt;&lt;/strong&gt;. As mentioned earlier, we need a 206 status code
response to specify that server accepts range request and answers properly.&lt;/li&gt;
  &lt;li&gt;The next three lines are setting media type. Browsers (except chrome) will refuse playing you video without 
a media type specified. &lt;strong&gt;&lt;em&gt;MediaTypeFactory&lt;/em&gt;&lt;/strong&gt; gives this type based on the file name.
For example, if the file name is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;someVideoName.mp4&lt;/code&gt;, then the MIME type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;video/mp4&lt;/code&gt; is returned.
If the MIME cannot be determined, the content type is specified as byte stream.&lt;/li&gt;
  &lt;li&gt;finally, we set video resource as a body.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The only thing left to make it a full-blown video player is a bit of html :)&lt;/p&gt;

&lt;pre class=&quot;shiki everforest-light&quot; style=&quot;background-color:#fdf6e3;color:#5c6a72&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;video&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; autoplay&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;&quot;autoplay&quot;&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; controls&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;    &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;source&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; src&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;&quot;/videos/fish.mp4/full&quot;&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; type&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;&quot;video/mp4&quot;&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;video&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This section shows how simple it is to make a file server leveraging Spring.
While I’m using UrlResource, anybody can implement their own &lt;a href=&quot;https://github.com/spring-projects/spring-framework/blob/master/spring-core/src/main/java/org/springframework/core/io/Resource.java&quot;&gt;Resource&lt;/a&gt;
to get data from anywhere, for example, database.&lt;/p&gt;

&lt;h2 id=&quot;mvc-drawbacks&quot;&gt;MVC drawbacks&lt;/h2&gt;

&lt;p&gt;It is helpful to know how the code above works from threading perspective, and what problems we could face because of that.
The &lt;a href=&quot;https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/web-reactive.html#webflux-concurrency-model&quot;&gt;threading model&lt;/a&gt;
of MVC is a classical one-per-user thread model. It can be easily observed with Java VisualVM.&lt;/p&gt;

&lt;p&gt;Let’s perform two requests to our server using curl (in separate terminal windows):&lt;/p&gt;

&lt;pre class=&quot;shiki everforest-light&quot; style=&quot;background-color:#fdf6e3;color:#5c6a72&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;curl&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; -s&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; -o&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; /dev/null&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; -H&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; &quot;Range: bytes=0-&quot;&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; -D&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; http://localhost:8080/videos/fish.mp4/full&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Everything works as expected and both loads finish. The threads view shows that for the load period 
two threads were occupied (green part of line) reading data from resource and writing to output stream (see &lt;a href=&quot;https://github.com/spring-projects/spring-framework/blob/master/spring-core/src/main/java/org/springframework/util/StreamUtils.java#L132&quot;&gt;StreamUtils.copy&lt;/a&gt;).
It is performed inside Spring’s &lt;a href=&quot;https://github.com/spring-projects/spring-framework/blob/master/spring-web/src/main/java/org/springframework/http/converter/ResourceHttpMessageConverter.java#L127&quot;&gt;ResourceHttpMessageConverter&lt;/a&gt; 
for you.&lt;/p&gt;

&lt;p style=&quot;text-align: center&quot;&gt;
    &lt;img width=&quot;100%&quot; alt=&quot;VisualVM&quot; loading=&quot;lazy&quot; srcset=&quot;        /cdn-cgi/image/width=640/images/spring-video-service/full_file_mvc.png 640w,        /cdn-cgi/image/width=768/images/spring-video-service/full_file_mvc.png 768w,        /cdn-cgi/image/width=1024/images/spring-video-service/full_file_mvc.png 1024w,        /cdn-cgi/image/width=1366/images/spring-video-service/full_file_mvc.png 1366w,        /cdn-cgi/image/width=1600/images/spring-video-service/full_file_mvc.png 1600w,        /cdn-cgi/image/width=1920/images/spring-video-service/full_file_mvc.png 1920w,      &quot; src=&quot;/images/spring-video-service/full_file_mvc.png&quot; /&gt;
&lt;/p&gt;

&lt;p&gt;For the video streaming the main shortcoming is: server will not be able to process more users 
than number of threads it has. This means if there are 10 threads then there will be no more than 10 users.
You can easily check this behaviour by setting property &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;server.tomcat.max-threads=1&lt;/code&gt; and calling curl twice.
The second request will be processed only after the first one ends. 
Use a big file for this experiment, several gigabytes, because local download is really fast.&lt;/p&gt;

&lt;p&gt;Imagine a situation when your website has exclusive rights for TV series. With an average length of episode of 1 hour,
you will be able to pass the content to only 10 customers at the same time. A website with performance like this 
will never get a wide audience.&lt;/p&gt;

&lt;h2 id=&quot;responding-with-parts-of-data&quot;&gt;Responding with parts of data&lt;/h2&gt;

&lt;p&gt;One mechanism to address the issue described in the previous section is to respond only with parts of a file. 
It is suitable only for clients which support byte range responses and html video is one of them. 
This way, threads will be used for smaller amounts of time giving opportunity to other requests to be processed.
Thanks to the &lt;a href=&quot;https://jira.spring.io/browse/SPR-14221&quot;&gt;ResourceRegion&lt;/a&gt; abstraction introduced in Spring version 4.3RC1
developer can now specify the range of bytes to be returned to the client.&lt;/p&gt;

&lt;pre class=&quot;shiki everforest-light&quot; style=&quot;background-color:#fdf6e3;color:#5c6a72&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#3A94C5&quot;&gt;@GetMapping&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;&quot;/videos/{name}&quot;&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;fun&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; getVideo&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#3A94C5&quot;&gt;@PathVariable&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; name: &lt;/span&gt;&lt;span style=&quot;color:#3A94C5&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;, &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#3A94C5&quot;&gt;	     @RequestHeader&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; headers: &lt;/span&gt;&lt;span style=&quot;color:#3A94C5&quot;&gt;HttpHeaders&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;): &lt;/span&gt;&lt;span style=&quot;color:#3A94C5&quot;&gt;ResponseEntity&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#3A94C5&quot;&gt;ResourceRegion&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;	val&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; video &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; UrlResource&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;&quot;file:&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;$videoLocation&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;$name&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;	val&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; region &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; resourceRegion&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(video, headers)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;	return&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; ResponseEntity.&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;status&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(HttpStatus.PARTIAL_CONTENT)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;			.&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;contentType&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(MediaTypeFactory&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;					.&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;getMediaType&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(video)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;					.&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;orElse&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(MediaType.APPLICATION_OCTET_STREAM))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;			.&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;body&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(region)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;private&lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt; fun&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; resourceRegion&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(video: &lt;/span&gt;&lt;span style=&quot;color:#3A94C5&quot;&gt;UrlResource&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;, headers: &lt;/span&gt;&lt;span style=&quot;color:#3A94C5&quot;&gt;HttpHeaders&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;): &lt;/span&gt;&lt;span style=&quot;color:#3A94C5&quot;&gt;ResourceRegion&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;	val&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; contentLength &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; video.&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;contentLength&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;	val&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; range &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; headers.range.&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;firstOrNull&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;	return&lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt; if&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; (range &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;!=&lt;/span&gt;&lt;span style=&quot;color:#DF69BA&quot;&gt; null&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;		val&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; start &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; range.&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;getRangeStart&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(contentLength)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;		val&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; end &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; range.&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;getRangeEnd&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(contentLength)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;		val&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; rangeLength &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; min&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#DF69BA&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#DF69BA&quot;&gt; 1024&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#DF69BA&quot;&gt; 1024&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;, end &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; start &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#DF69BA&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;		ResourceRegion&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(video, start, rangeLength)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;	} &lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt;else&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;		val&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; rangeLength &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; min&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#DF69BA&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#DF69BA&quot;&gt; 1024&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#DF69BA&quot;&gt; 1024&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;, contentLength)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;		ResourceRegion&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(video, &lt;/span&gt;&lt;span style=&quot;color:#DF69BA&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;, rangeLength)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There are several additions worth to mention:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;&lt;em&gt;HttpHeaders&lt;/em&gt;&lt;/strong&gt; are added to the controller to get the range header&lt;/li&gt;
  &lt;li&gt;the returned entity is now &lt;strong&gt;&lt;em&gt;ResourceRegion&lt;/em&gt;&lt;/strong&gt;. It specifies the position in the byte representations of the file
along with the count of bytes to respond with.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;em&gt;resourceRegion&lt;/em&gt;&lt;/strong&gt; method gets the range header to find the starting position. The size of chunk
can be either 1 MB, the one specified in the range header or the length of contents of file. The smallest number is taken.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now the server takes much less time to process requests and threads have opportunity to switch to other requests.&lt;/p&gt;

&lt;p style=&quot;text-align: center&quot;&gt;
    &lt;img width=&quot;100%&quot; alt=&quot;VisualVM&quot; loading=&quot;lazy&quot; srcset=&quot;        /cdn-cgi/image/width=640/images/spring-video-service/chunk_file_mvc.png 640w,        /cdn-cgi/image/width=768/images/spring-video-service/chunk_file_mvc.png 768w,        /cdn-cgi/image/width=1024/images/spring-video-service/chunk_file_mvc.png 1024w,        /cdn-cgi/image/width=1366/images/spring-video-service/chunk_file_mvc.png 1366w,        /cdn-cgi/image/width=1600/images/spring-video-service/chunk_file_mvc.png 1600w,        /cdn-cgi/image/width=1920/images/spring-video-service/chunk_file_mvc.png 1920w,      &quot; src=&quot;/images/spring-video-service/chunk_file_mvc.png&quot; /&gt;
&lt;/p&gt;

&lt;h2 id=&quot;spring-webflux&quot;&gt;Spring WebFlux&lt;/h2&gt;

&lt;p&gt;Spring 5 has introduced a new paradigm of the reactive web applications, as well as the implementation of such an api
called WebFlux. The main difference is an introduction of reactive streams as a core component.&lt;/p&gt;

&lt;p&gt;The response body of resource in MVC was represented as java.io.InputStream. 
Consequently, to get data from a file and write it to a user connection we need to have a buffer,
fill it with data from the file and only then write to the connection.&lt;/p&gt;

&lt;pre class=&quot;shiki everforest-light&quot; style=&quot;background-color:#fdf6e3;color:#5c6a72&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#3A94C5&quot;&gt;InputStream&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; in &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; ???&lt;/span&gt;&lt;span style=&quot;color:#939F91;font-style:italic&quot;&gt; // file stream&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#3A94C5&quot;&gt;OutputStream&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; out &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt; ???&lt;/span&gt;&lt;span style=&quot;color:#939F91;font-style:italic&quot;&gt; // socket connection stream&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#3A94C5&quot;&gt;byte&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[] buffer &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F85552&quot;&gt; new&lt;/span&gt;&lt;span style=&quot;color:#3A94C5&quot;&gt; byte&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;[BUFFER_SIZE];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#3A94C5&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; bytesRead &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; in&lt;/span&gt;&lt;span style=&quot;color:#939F91&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;read&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(buffer);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;out&lt;/span&gt;&lt;span style=&quot;color:#939F91&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;write&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(buffer, &lt;/span&gt;&lt;span style=&quot;color:#DF69BA&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;, bytesRead);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The main deficiency of this technique is read operations are blocking and hang until the buffer is fully read.&lt;/p&gt;

&lt;p&gt;Thanks to creation of NIO in java it is now possible to operate on byte buffers and not streams of bytes.
The response body in WebFlux is Publisher&amp;lt;DataBuffer&amp;gt;. DataBuffer is just an abstraction over byte buffer,
can be considered as array of bytes. &lt;a href=&quot;https://github.com/reactive-streams/reactive-streams-jvm/blob/v1.0.2/README.md#1-publisher-code&quot;&gt;Publisher&lt;/a&gt; 
comes from the reactive streams specification and represents a potentially infinite stream of any entities,
byte buffers in our case. The main idea of the Publisher is to work on demand. It does not produce elements
eagerly but responds to requests. If the user of this streams requests 3 items then no more than 3 items will be returned.
What’s more, there items are returned in an undefined point in future so you don’t need to block and wait them.
When the items arrive, a callback provided is executed.&lt;/p&gt;

&lt;p&gt;Fortunately, WebFlux api is mostly compatible with MVC and we only need to change underlying implementation
to make things work. The &lt;a href=&quot;https://github.com/melgenek/spring-video-service/tree/webflux&quot;&gt;webflux&lt;/a&gt; branch of my sample repo 
shows the dependencies needed. The code is left the same as in the MVC section of this article:&lt;/p&gt;

&lt;pre class=&quot;shiki everforest-light&quot; style=&quot;background-color:#fdf6e3;color:#5c6a72&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#3A94C5&quot;&gt;@GetMapping&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;&quot;/videos/{name}/full&quot;&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;fun&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; getFullVideo&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#3A94C5&quot;&gt;@PathVariable&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; name: &lt;/span&gt;&lt;span style=&quot;color:#3A94C5&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;): &lt;/span&gt;&lt;span style=&quot;color:#3A94C5&quot;&gt;ResponseEntity&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#3A94C5&quot;&gt;UrlResource&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;	val&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; video &lt;/span&gt;&lt;span style=&quot;color:#F57D26&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; UrlResource&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;&quot;file:&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;$videoLocation&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;$name&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F85552&quot;&gt;	return&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt; ResponseEntity.&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;status&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(HttpStatus.PARTIAL_CONTENT)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;			.&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;contentType&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(MediaTypeFactory&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;					.&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;getMediaType&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(video)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;					.&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;orElse&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(MediaType.APPLICATION_OCTET_STREAM))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;			.&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;body&lt;/span&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;(video)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#5C6A72&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now we’re ready to repeat the experiment with only one thread available.
Set the property &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reactor.ipc.netty.workerCount=1&lt;/code&gt; and call curl twice:&lt;/p&gt;

&lt;pre class=&quot;shiki everforest-light&quot; style=&quot;background-color:#fdf6e3;color:#5c6a72&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#8DA101&quot;&gt;curl&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; -s&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; -o&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; /dev/null&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; -H&lt;/span&gt;&lt;span style=&quot;color:#8DA101&quot;&gt; &quot;Range: bytes=0-&quot;&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; -D&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#DFA000&quot;&gt; http://localhost:8080/videos/fish.mp4/full&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This time both files are loaded at the same time without the need to wait in a queue.
I’d like to give you some intuition into how this works internally.&lt;/p&gt;

&lt;p&gt;The server has two kinds of work done: selection and actual IO operations.
By “selection” I mean the following:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;the server has several connections, called channels&lt;/li&gt;
  &lt;li&gt;each channel can produce events&lt;/li&gt;
  &lt;li&gt;there is a special thread which tries to get these events. This thread is called selector. 
It performs an infinite loop inside itself (event loop). Each cycle of the loop asks the underlying OS about events 
available for each channel.&lt;/li&gt;
  &lt;li&gt;if the selector thread gets events, it does not read or write any data. 
It just fans out these events to free workers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Our video server is mostly interested in write operations. Let’s imagine that write event pops up.
Then worker thread takes over:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;worker asks Publisher&lt;DataBuffer&gt; for the next byte buffer but not the whole file&lt;/DataBuffer&gt;&lt;/li&gt;
  &lt;li&gt;at some point in the future this buffer arrives and callback comes into play.
The buffer received is written to output stream.&lt;/li&gt;
  &lt;li&gt;only fraction of data is allowed to be written at once. Multiple write events appear during one
client-server communication.&lt;/li&gt;
&lt;/ul&gt;

&lt;p style=&quot;text-align: center&quot;&gt;
    &lt;img width=&quot;100%&quot; alt=&quot;Reactor&quot; loading=&quot;lazy&quot; srcset=&quot;        /cdn-cgi/image/width=640/images/spring-video-service/reactor-my-intuition.png 640w,        /cdn-cgi/image/width=768/images/spring-video-service/reactor-my-intuition.png 768w,        /cdn-cgi/image/width=1024/images/spring-video-service/reactor-my-intuition.png 1024w,        /cdn-cgi/image/width=1366/images/spring-video-service/reactor-my-intuition.png 1366w,        /cdn-cgi/image/width=1600/images/spring-video-service/reactor-my-intuition.png 1600w,        /cdn-cgi/image/width=1920/images/spring-video-service/reactor-my-intuition.png 1920w,      &quot; src=&quot;/images/spring-video-service/reactor-my-intuition.png&quot; /&gt;
&lt;/p&gt;

&lt;p&gt;The pattern described is called Reactor. It allows to handle multiple requests at the same time
using less threads by splitting the processing timeline into chunks. While it heavily relies on OS,
our program will work only on Linux. The WebFlux server blocks on Windows like the MVC one.&lt;/p&gt;

&lt;p&gt;The default implementation used by &lt;em&gt;spring-boot-starter-webflux&lt;/em&gt; is Reactor Netty.
If no selector threads are configured then workers do both selection and actual work functions.
So they read events and handle them right away.&lt;/p&gt;

&lt;p style=&quot;text-align: center&quot;&gt;
    &lt;img width=&quot;100%&quot; alt=&quot;Reactor thread&quot; loading=&quot;lazy&quot; srcset=&quot;        /cdn-cgi/image/width=640/images/spring-video-service/reactor-thread.png 640w,        /cdn-cgi/image/width=768/images/spring-video-service/reactor-thread.png 768w,        /cdn-cgi/image/width=1024/images/spring-video-service/reactor-thread.png 1024w,        /cdn-cgi/image/width=1366/images/spring-video-service/reactor-thread.png 1366w,        /cdn-cgi/image/width=1600/images/spring-video-service/reactor-thread.png 1600w,        /cdn-cgi/image/width=1920/images/spring-video-service/reactor-thread.png 1920w,      &quot; src=&quot;/images/spring-video-service/reactor-thread.png&quot; /&gt;
&lt;/p&gt;

&lt;p&gt;There is one additional bonus which comes with WebFlux: &lt;a href=&quot;https://www.ibm.com/developerworks/library/j-zerocopy/index.html&quot;&gt;zero-copy data transfer&lt;/a&gt;.
Byte buffers, copied from file to connection, are not loaded into application memory.
All the work is being done on OS level. This feature is available using Reactor Netty (default backend) or Undertow.&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;In this article I tried to build simple yet efficient video streaming service and give intuition into
how things work internally.
If you want to read more about WebFlux, reactivity and NIO, here are some useful links:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Dave Syer’s &lt;a href=&quot;https://spring.io/blog/2016/06/07/notes-on-reactive-programming-part-i-the-reactive-landscape&quot;&gt;notes on reactivity&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Sébastien Deleuze tells about &lt;a href=&quot;https://spring.io/blog/2016/04/19/understanding-reactive-types&quot;&gt;reactive types in spring&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.blogjava.net/xiaomage234/archive/2016/04/05/429968.html&quot;&gt;Threaded vs evented servers&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Jakob Jenkov builds his own &lt;a href=&quot;http://tutorials.jenkov.com/java-nio/non-blocking-server.html&quot;&gt;non-blocking web server&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Awesome Doug Lea’s presentation about &lt;a href=&quot;http://gee.cs.oswego.edu/dl/cpjslides/nio.pdf&quot;&gt;Scalable IO in Java&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Step by step implementation of reactor using Java NIO: &lt;a href=&quot;http://jeewanthad.blogspot.com/2013/02/reactor-pattern-explained-part-1.html&quot;&gt;part1&lt;/a&gt;, &lt;a href=&quot;http://jeewanthad.blogspot.com/2013/03/reacter-pattern-explained-part-2.html&quot;&gt;part2&lt;/a&gt;, &lt;a href=&quot;http://jeewanthad.blogspot.com/2013/03/reacter-pattern-explained-part-3.html&quot;&gt;part3&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;And a couple &lt;a href=&quot;https://tianpan.co/blog/2015-01-13-understanding-reactor-pattern-for-highly-scalable-i-o-bound-web-server&quot;&gt;more&lt;/a&gt; 
&lt;a href=&quot;http://rox-xmlrpc.sourceforge.net/niotut/&quot;&gt;articles&lt;/a&gt; &lt;a href=&quot;https://www.usenix.org/legacy/events/hotos03/tech/full_papers/vonbehren/vonbehren_html/index.html&quot;&gt;you&lt;/a&gt; can find useful&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Sun, 20 May 2018 00:00:00 +0000</pubDate>
        <link>https://melgenek.dev/spring-video-service</link>
        <guid isPermaLink="true">https://melgenek.dev/spring-video-service</guid>
      </item>
    
  </channel>
</rss>
