<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type="text/xsl" href="https://blog.taleedevops.today/rss.xsl"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <atom:link href="https://blog.taleedevops.today/rss.xml" rel="self" type="application/rss+xml"/>
    <title>Talee Blog</title>
    <link>https://blog.taleedevops.today/</link>
    <description>Hands-on notes on DevOps and backend engineering — Docker, Kubernetes, Ansible, Spring Boot, Kafka, databases and interview preparation.</description>
    <language>en-US</language>
    <pubDate>Thu, 17 Sep 2026 01:53:13 GMT</pubDate>
    <lastBuildDate>Thu, 17 Sep 2026 01:53:13 GMT</lastBuildDate>
    <generator>@vuepress/plugin-feed</generator>
    <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
    <image>
      <title>Talee Blog</title>
      <url>https://blog.taleedevops.today/logo.png</url>
      <link>https://blog.taleedevops.today/</link>
    </image>
    <category>Devops</category>
    <category>YouTube</category>
    <category>AI</category>
    <category>AI-Driven SDLC</category>
    <category>springboot</category>
    <category>backend</category>
    <category>database</category>
    <category>devops</category>
    <category>microservice</category>
    <category>docker</category>
    <item>
      <title>Helm and Kustomize: Consume a Chart, Overlay a Base, Render Before You Apply</title>
      <link>https://blog.taleedevops.today/devops/k8s/CKA-2026/helm-and-kustomize.html</link>
      <guid>https://blog.taleedevops.today/devops/k8s/CKA-2026/helm-and-kustomize.html</guid>
      <source url="https://blog.taleedevops.today/rss.xml">Helm and Kustomize: Consume a Chart, Overlay a Base, Render Before You Apply</source>
      <description>A full Helm release cycle — install, two upgrades, a rollback that moves forward — and a Kustomize base with two overlays, rendered before anything touches the cluster.</description>
      <category>Devops</category>
      <pubDate>Tue, 15 Sep 2026 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[
<p><small>Part 8 of the <a href="/devops/k8s/CKA-2026/" target="_blank">CKA roadmap</a> · Phase 2 — Cluster Architecture · 25%</small></p>
<p>The 2025 curriculum added the objective <em>"Use Helm and Kustomize to install cluster components"</em>.
The verb is <strong>use</strong>. Nothing in it asks you to author a chart. What it asks, in practice:</p>
<ul>
<li>install a chart someone else wrote, at the version you are told</li>
<li>change its values, and know what your change did to the values that were already there</li>
<li>undo a bad upgrade</li>
<li>adapt one set of plain YAML to two environments without copying it</li>
<li>see what any of this will produce <strong>before</strong> it reaches the cluster</li>
</ul>
<p>This post does all of that on the two-node cluster from <a href="/devops/k8s/CKA-2026/build-kubeadm-cluster-gcp.html" target="_blank">part 1</a>.</p>
<h2>Two tools, two ideas</h2>
<p>They get mentioned together, but they solve the problem from opposite ends.</p>
<p>| | Helm | Kustomize |
|</p>
]]></content:encoded>
      <enclosure url="https://blog.taleedevops.today/assets/images/devops/k8s/cka-2026/phase-2-helm-kustomize.jpg" type="image/jpeg"/>
    </item>
    <item>
      <title>Ingress: Rules, Classes and the Controller That Reads Them</title>
      <link>https://blog.taleedevops.today/devops/k8s/CKA-2026/ingress.html</link>
      <guid>https://blog.taleedevops.today/devops/k8s/CKA-2026/ingress.html</guid>
      <source url="https://blog.taleedevops.today/rss.xml">Ingress: Rules, Classes and the Controller That Reads Them</source>
      <description>An Ingress with no controller is accepted and does nothing. Install one, route two paths to two Services, and find out exactly what Prefix and Exact match.</description>
      <category>Devops</category>
      <pubDate>Wed, 16 Sep 2026 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[
<p><small>Part 11 of the <a href="/devops/k8s/CKA-2026/" target="_blank">CKA roadmap</a> · Phase 3 — Services &amp; Networking · 20%</small></p>
<p>A Service routes by <strong>port</strong>. It works at layer 4 and knows nothing about HTTP. An Ingress routes
by <strong>host and path</strong>, at layer 7. That lets one entry point send <code>/app1</code> to one Service and <code>/app2</code>
to another, where you would otherwise need a load balancer per Service.</p>
<p>Gateway API is the successor, and it has its own post <a href="/devops/k8s/CKA-2026/Question-2.html" target="_blank">next in the roadmap</a>. But
Ingress is still in the curriculum, and still in most clusters you will meet. And the lesson it
teaches best carries straight over to Gateway API: a routing rule is only data until something
reads it.</p>
<h2>The one idea to hold</h2>
<p>Three objects, three jobs:</p>
<p>| Object | What it is | What it does on its own |
|</p>
]]></content:encoded>
      <enclosure url="https://blog.taleedevops.today/assets/images/devops/k8s/cka-2026/phase-3-ingress.jpg" type="image/jpeg"/>
    </item>
    <item>
      <title>Build a Two-Node kubeadm Cluster on GCP</title>
      <link>https://blog.taleedevops.today/devops/k8s/CKA-2026/build-kubeadm-cluster-gcp.html</link>
      <guid>https://blog.taleedevops.today/devops/k8s/CKA-2026/build-kubeadm-cluster-gcp.html</guid>
      <source url="https://blog.taleedevops.today/rss.xml">Build a Two-Node kubeadm Cluster on GCP</source>
      <description>Two Ubuntu VMs on GCP, Kubernetes 1.33 with kubeadm and Flannel, and the smoke test that actually proves cross-node networking — plus the two ways I broke it in two days.</description>
      <category>Devops</category>
      <pubDate>Sun, 13 Sep 2026 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[
<p><small>Part 1 of the <a href="/devops/k8s/CKA-2026/" target="_blank">CKA roadmap</a> · Phase 0 — a cluster of your own</small></p>
<p>Every troubleshooting task on the exam assumes you know what a healthy cluster looks like. The
fastest way to learn that is to build one by hand, break it, and put it back — which is why this
comes before anything else in the roadmap.</p>
<p>A browser sandbox or <code>minikube</code> gets you a working cluster in a minute, and hides exactly the
parts worth learning: which machine you are on, what kubeadm writes to disk, and why a pod
network can look fine while no packet crosses between nodes. I broke this cluster twice in two
days. Both breakages are below, because they taught me more than the build did.</p>
<h2>The task</h2>
<blockquote>
<p>Two fresh Ubuntu 24.04 VMs, <code>cp</code> and <code>worker</code>. Bring up Kubernetes 1.33 with kubeadm and a pod
network that works across both nodes. Prove it: a pod running on <code>worker</code> must reach a pod IP on
<code>cp</code>.</p>
</blockquote>
<h2>What you are building</h2>
<p>| | |
|</p>
]]></content:encoded>
      <enclosure url="https://blog.taleedevops.today/assets/images/devops/k8s/cka-2026/phase-0-cluster.jpg" type="image/jpeg"/>
    </item>
    <item>
      <title>Set Up Your Terminal for the Exam</title>
      <link>https://blog.taleedevops.today/devops/k8s/CKA-2026/exam-terminal-setup.html</link>
      <guid>https://blog.taleedevops.today/devops/k8s/CKA-2026/exam-terminal-setup.html</guid>
      <source url="https://blog.taleedevops.today/rss.xml">Set Up Your Terminal for the Exam</source>
      <description>An alias, tab completion, a dry-run shortcut, a no-wait delete and a vim config that doesn&amp;apos;t break YAML — six lines you should be able to retype from memory in under a minute.</description>
      <category>Devops</category>
      <pubDate>Sun, 13 Sep 2026 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[
<p><small>Part 2 of the <a href="/devops/k8s/CKA-2026/" target="_blank">CKA roadmap</a> · Phase 0 — a cluster of your own</small></p>
<p>This is the smallest task in the roadmap and the one that pays back fastest.</p>
<p>Over a two-hour exam you type <code>kubectl</code> something like 150 times. At roughly two seconds each for
the long form, that is five minutes spent on spelling a command name. Completion matters more
still: resource names in the exam are long and easy to mistype, and one wrong character means the
task is done against the wrong object.</p>
<p>So the goal here is double. Set up your practice environment today — and be able to retype the
whole setup <strong>from memory, in under 60 seconds</strong>, at the start of the exam.</p>
<h2>The task</h2>
<blockquote>
<p>Before reading the first question: make <code>k</code> a working alias for <code>kubectl</code> with tab completion,
add a shortcut that turns any <code>kubectl</code> command into a YAML skeleton, add one for deleting a pod
without waiting, and make vim safe for editing YAML. Then retype all of it without notes in under
a minute.</p>
</blockquote>
<h2>Check before you configure</h2>
<p>The exam environment usually has <code>alias k=kubectl</code> and completion already set up. Do not bet on
it. The first thing to type is:</p>
<div class="language-bash line-numbers-mode" data-highlighter="shiki" data-ext="bash" data-title="bash" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">k</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> version</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>If that says <code>command not found</code>, paste the setup below before you read anything.</p>
<p>Remember too that aliases live in <strong>the current shell on the current machine</strong>. The moment you
<code>ssh</code> to another node, they are gone.</p>
<h2>The solution</h2>
<h3>An alias that completes</h3>
<div class="language-bash line-numbers-mode" data-highlighter="shiki" data-ext="bash" data-title="bash" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#56B6C2">source</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> &lt;(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">kubectl</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> completion bash)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">alias</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75"> k</span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">kubectl</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">complete</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66"> -o</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> default</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66"> -F</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> __start_kubectl</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> k</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>The <code>complete</code> line is the one people leave out. Without it, <code>kubectl get po&lt;TAB&gt;</code> completes and
<code>k get po&lt;TAB&gt;</code> does not — the alias works but you have thrown away the half that matters.</p>
<p>Order matters too. <code>__start_kubectl</code> is a function defined by <code>kubectl completion bash</code>, so the
<code>source</code> line has to run <strong>before</strong> the <code>complete</code> line.</p>
<p>Completion also needs the <code>bash-completion</code> package on the machine. Check for it, and install it
if it is missing:</p>
<div class="language-bash line-numbers-mode" data-highlighter="shiki" data-ext="bash" data-title="bash" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#56B6C2">type</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> _init_completion</span><span style="--shiki-light:#D73A49;--shiki-dark:#ABB2BF"> &gt;</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">/dev/null</span><span style="--shiki-light:#D73A49;--shiki-dark:#ABB2BF"> 2&gt;&amp;1</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> &amp;&amp; </span><span style="--shiki-light:#005CC5;--shiki-dark:#56B6C2">echo</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> OK</span><span style="--shiki-light:#D73A49;--shiki-dark:#ABB2BF"> ||</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> sudo</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> apt</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> install</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66"> -y</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> bash-completion</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>Completion is worth more than the alias. It fills in <strong>resource names</strong> — <code>k get pod ngin&lt;TAB&gt;</code> —
and flag names, which is where typos actually happen.</p>
<h3><code>$do</code> — a YAML skeleton from any command</h3>
<div class="language-bash line-numbers-mode" data-highlighter="shiki" data-ext="bash" data-title="bash" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">export</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75"> do</span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">'--dry-run=client -o yaml'</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>Use it to generate manifests instead of writing them:</p>
<div class="language-bash line-numbers-mode" data-highlighter="shiki" data-ext="bash" data-title="bash" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">k</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> run</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> nginx</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66"> --image=nginx</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75"> $do</span><span style="--shiki-light:#D73A49;--shiki-dark:#ABB2BF"> &gt;</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> pod.yaml</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">k</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> create</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> deploy</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> web</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66"> --image=nginx</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66"> --replicas=3</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75"> $do</span><span style="--shiki-light:#D73A49;--shiki-dark:#ABB2BF"> &gt;</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> deploy.yaml</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">k</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> create</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> svc</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> clusterip</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> web</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66"> --tcp=80:80</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75"> $do</span><span style="--shiki-light:#D73A49;--shiki-dark:#ABB2BF"> &gt;</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> svc.yaml</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>This is how you handle any task along the lines of <em>"create a pod with …"</em> where <code>kubectl run</code>
has no flag for what is asked: generate the skeleton, edit it, then <code>k apply -f</code>.</p>
<h3><code>$now</code> — delete without waiting</h3>
<div class="language-bash line-numbers-mode" data-highlighter="shiki" data-ext="bash" data-title="bash" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">export</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75"> now</span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">'--force --grace-period=0'</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><div class="language-bash line-numbers-mode" data-highlighter="shiki" data-ext="bash" data-title="bash" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">k</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> delete</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> pod</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> nginx</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75"> $now</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>A normal pod deletion waits out <code>terminationGracePeriodSeconds</code>, which defaults to 30 seconds. In
the exam you delete and recreate things constantly — thirty seconds, ten times over, is five
minutes of watching a terminal.</p>
<h3>vim that does not break YAML</h3>
<p>YAML refuses tabs, and vim uses them by default. Paste a block into a manifest and the indentation
is wrong in a way that takes longer to fix than to retype.</p>
<div class="language-bash line-numbers-mode" data-highlighter="shiki" data-ext="bash" data-title="bash" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">cat</span><span style="--shiki-light:#D73A49;--shiki-dark:#ABB2BF"> &gt;</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> ~/.vimrc</span><span style="--shiki-light:#D73A49;--shiki-dark:#ABB2BF"> &lt;&lt;</span><span style="--shiki-light:#032F62;--shiki-dark:#ABB2BF">'VIM'</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#98C379">set expandtab</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#98C379">set tabstop=2</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#98C379">set shiftwidth=2</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#98C379">set number</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#ABB2BF">VIM</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Three keystrokes worth knowing by heart when editing long YAML:</p>
<ul>
<li><code>:set paste</code> — turns off auto-indent before you paste, so each line stops drifting further right</li>
<li><code>yyp</code> — duplicate the current line, for adding another container or env entry</li>
<li><code>dd</code> and <code>u</code> — delete a line, undo</li>
</ul>
<h3>Two more aliases worth having</h3>
<p>| Add | Why |
|</p>
]]></content:encoded>
      <enclosure url="https://blog.taleedevops.today/assets/images/devops/k8s/cka-2026/phase-0-terminal.jpg" type="image/jpeg"/>
    </item>
    <item>
      <title>Operators and CRDs: Install One, Read Its Schema, Stop Its Controller</title>
      <link>https://blog.taleedevops.today/devops/k8s/CKA-2026/operators-and-crds.html</link>
      <guid>https://blog.taleedevops.today/devops/k8s/CKA-2026/operators-and-crds.html</guid>
      <source url="https://blog.taleedevops.today/rss.xml">Operators and CRDs: Install One, Read Its Schema, Stop Its Controller</source>
      <description>Install cert-manager, find what it added, write a custom resource from kubectl explain alone, then stop its controller to see what a CR does on its own: nothing.</description>
      <category>Devops</category>
      <pubDate>Mon, 14 Sep 2026 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[
<p><small>Part 9 of the <a href="/devops/k8s/CKA-2026/" target="_blank">CKA roadmap</a> · Phase 2 — Cluster Architecture · 25%</small></p>
<p>Operators came into the CKA with the 2025 curriculum revision. The objective reads
<em>"Understand CRDs, install and configure operators"</em> — and nothing in that line asks you to write a
controller or design a CRD. What it does ask for, taken at its word:</p>
<ul>
<li>install an operator someone else wrote</li>
<li>find out what new resource types it added</li>
<li>write a custom resource for a schema you have never seen, without a template</li>
<li>work out why a custom resource you created is not doing anything</li>
</ul>
<p>This post does all four on the two-node cluster from <a href="/devops/k8s/CKA-2026/build-kubeadm-cluster-gcp.html" target="_blank">part 1</a>.</p>
<h2>The one idea to hold</h2>
<p><strong>An operator is a CRD plus a controller.</strong> Everything else in this post follows from which half
you are looking at.</p>
<p>| Piece | What it is | What it does |
|</p>
]]></content:encoded>
      <enclosure url="https://blog.taleedevops.today/assets/images/devops/k8s/cka-2026/phase-2-operators.jpg" type="image/jpeg"/>
    </item>
    <item>
      <title>Seven Upgrades to One Prompt</title>
      <link>https://blog.taleedevops.today/youtube/ai-automation/seven-prompt-upgrades.html</link>
      <guid>https://blog.taleedevops.today/youtube/ai-automation/seven-prompt-upgrades.html</guid>
      <source url="https://blog.taleedevops.today/rss.xml">Seven Upgrades to One Prompt</source>
      <description>One vague prompt, seven additive upgrades, and the full text of all eight prompts. Four of them give the model information; three change how it works — and those fail differently.</description>
      <category>YouTube</category>
      <category>AI</category>
      <pubDate>Sat, 05 Sep 2026 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[
<p>The starting prompt is the one almost everybody types:</p>
<blockquote>
<p><em>Lập cho tôi kế hoạch ra mắt khóa học trực tuyến.</em> — Make me a launch plan for an online course.</p>
</blockquote>
<p>It returns a plan. Week one, week two, week three, on to week eight, then a post-launch section.
Nothing in it is wrong, and none of it could be acted on tomorrow morning, because nothing in it
knows anything about you.</p>
<p>What follows is the same prompt, seven times, each version adding one block to the last. All eight
prompts are here in full — the seven intermediate ones and the master prompt they add up to.</p>
<p>The run itself is on one model — an Anthropic one; the name in the auto-captions is too garbled to
reproduce. The claim made alongside it is that the seven upgrades port to any of them, ChatGPT and
Gemini included. That is plausible, because none of the seven depends on a feature: they are all
things you write in the prompt box. It is still a claim, though. Nothing here was run twice on two
models to check it.</p>
<div class="hint-container info">
<p class="hint-container-title">About this write-up</p>
<p>Written from the video on the channel. The slides are the ones used in it, and the prompts are
reproduced from the source file rather than retyped, so what is on this page is what was run. They
are kept in Vietnamese: a prompt is an artifact, and translating one changes what it does. Two
transcription artifacts were normalised — a leaked LaTeX arrow escape back to <code>→</code>, and the stray
quotation marks wrapping each prompt removed.</p>
</div>
]]></content:encoded>
      <enclosure url="https://blog.taleedevops.today/assets/images/youtube/ai-automation/prompt-tips.jpg" type="image/jpeg"/>
    </item>
    <item>
      <title>Gemini 3.7 Flash: Rank 23 Was Enough</title>
      <link>https://blog.taleedevops.today/youtube/ai-automation/gemini-3-7-flash-rank-23.html</link>
      <guid>https://blog.taleedevops.today/youtube/ai-automation/gemini-3-7-flash-rank-23.html</guid>
      <source url="https://blog.taleedevops.today/rss.xml">Gemini 3.7 Flash: Rank 23 Was Enough</source>
      <description>Google&amp;apos;s own table puts Gemini 3.7 Flash near the top. An independent leaderboard puts it 23rd for code. Two builds, first try, under 10% of a quota — and rank turns out to be the wrong question.</description>
      <category>YouTube</category>
      <category>AI</category>
      <pubDate>Mon, 24 Aug 2026 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[
<p>Two scoreboards, same model, same week.</p>
<p>On Google's launch page, Gemini 3.7 Flash sits at or near the top of every category that matters
for agent work: professional code quality, long-horizon software engineering, web development,
PDF handling, enterprise automation. Occasionally a competitor edges it out. Mostly it leads.</p>
<p>On <strong>arena.ai</strong>, an independent leaderboard built from real sessions rather than a vendor's own
evaluation, the same model ranks like this:</p>
<p>| Category | Gemini 3.7 Flash |
|</p>
]]></content:encoded>
      <enclosure url="https://blog.taleedevops.today/assets/images/youtube/ai-automation/gemini-3-7-flash.jpg" type="image/jpeg"/>
    </item>
    <item>
      <title>Session 1 — From Traditional SDLC to AI-Driven SDLC: Where Are We?</title>
      <link>https://blog.taleedevops.today/ai-sdlc/session-1-traditional-to-ai-driven-sdlc.html</link>
      <guid>https://blog.taleedevops.today/ai-sdlc/session-1-traditional-to-ai-driven-sdlc.html</guid>
      <source url="https://blog.taleedevops.today/rss.xml">Session 1 — From Traditional SDLC to AI-Driven SDLC: Where Are We?</source>
      <description>Every SDLC phase now has an AI pointed at it, yet pipeline throughput has barely moved. Session 1 on why local speed-ups do not add up.</description>
      <category>AI-Driven SDLC</category>
      <pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[
<p>Every phase of the software lifecycle now has an AI assistant pointed at it. Business analysts
draft user stories with one. Architects sketch options with another. Developers generate code,
testers generate cases, reviewers get automated comments.</p>
<p>And yet, at the level of the whole delivery pipeline, throughput has barely moved.</p>
<p>That gap is the entire subject of Session 1. Not "can AI write code" — that question is settled —
but a harder one: <strong>if AI already accelerates nearly every individual activity, why isn't the
overall process meaningfully faster?</strong></p>
<div class="hint-container info">
<p class="hint-container-title">About this write-up</p>
<p>These are my notes from Day 1 of the <em>AI-Driven Software Development Life-Cycle</em> course, taught by
<strong>Dr. Bùi Thị Mai Anh</strong>, School of Information and Communication Technology (SOICT), Hanoi
University of Science and Technology, July 2026. The framing and the workshop design are hers; the
summary and wording here are mine.</p>
<p>A <a href="/vi/ai-sdlc/session-1-tu-sdlc-truyen-thong-den-sdlc-ai.html" target="_blank">Vietnamese version</a> of this article is also available.</p>
</div>
<h2>What AI is actually good at</h2>
<p>Before deciding <em>where</em> AI belongs in a process, the session grounds things in what AI contributes
across any phase. Five capability groups:</p>
<p>| Capability | What it looks like in practice |
|</p>
]]></content:encoded>
      <enclosure url="https://blog.taleedevops.today/assets/images/ai-sdlc/session-1.jpg" type="image/jpeg"/>
    </item>
    <item>
      <title>Session 2 — AI-Driven Requirement Engineering and System Design</title>
      <link>https://blog.taleedevops.today/ai-sdlc/session-2-ai-driven-requirements-and-design.html</link>
      <guid>https://blog.taleedevops.today/ai-sdlc/session-2-ai-driven-requirements-and-design.html</guid>
      <source url="https://blog.taleedevops.today/rss.xml">Session 2 — AI-Driven Requirement Engineering and System Design</source>
      <description>AI returns twenty user stories in a minute, so why do projects still rework requirements? Because its highest-value move is asking, not answering.</description>
      <category>AI-Driven SDLC</category>
      <pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[
<p>AI writes requirements fast. Give it a paragraph of business context and it returns twenty user
stories with acceptance criteria in under a minute.</p>
<p>So why do projects still rework their requirements, over and over?</p>
<p>Session 2 answers that, and the answer reframes how you use the tool: <strong>the highest-value thing AI
does in requirement engineering is not answering — it is asking.</strong></p>
<div class="hint-container info">
<p class="hint-container-title">About this write-up</p>
<p>These are my notes from Day 2 of the <em>AI-Driven Software Development Life-Cycle</em> course, taught by
<strong>Dr. Bùi Thị Mai Anh</strong>, School of Information and Communication Technology (SOICT), Hanoi
University of Science and Technology, July 2026. The framing and the workshop design are hers; the
summary and wording here are mine. The prompts reproduced below are taken from the course
workbook — they are the instructor's, not mine, and I have translated them into English.</p>
<p>This follows on from <a href="/ai-sdlc/session-1-traditional-to-ai-driven-sdlc.html" target="_blank">Session 1</a>, which established
that shared context — not model capability — is the bottleneck in an AI-assisted lifecycle. A
<a href="/vi/ai-sdlc/session-2-ky-nghe-yeu-cau-va-thiet-ke-voi-ai.html" target="_blank">Vietnamese version</a> of this article
is also available.</p>
</div>
<h2>Part 1 — Requirement engineering with AI</h2>
<h3>Make it ask, not answer</h3>
<p>The course states the reframe plainly: <em>AI that asks the right question is more useful than AI that
answers immediately.</em></p>
<p>The reason connects straight back to Session 1. Most missing requirements come from missing context.
If you ask for user stories before the context is complete, you get fluent, confident, well-formatted
stories built on unstated assumptions — and every one of those assumptions becomes rework later.</p>
<p>There is a hard boundary here that the session keeps returning to:</p>
<blockquote>
<p>AI can <strong>propose</strong> business rules. It cannot <strong>confirm</strong> them. Business rules and the final
decision belong to a person.</p>
</blockquote>
<h3>The six moves</h3>
<p>Requirement work with AI breaks into six activities, each producing an artifact that feeds the next:</p>
<ol>
<li><strong>Elicitation</strong> — AI helps mine the existing material for what is actually there</li>
<li><strong>Clarification</strong> — AI generates the questions that expose what is <em>not</em> there</li>
<li><strong>User stories</strong> — AI turns clarified requirements into structured stories; a human evaluates</li>
<li><strong>Acceptance criteria</strong> — so that AI, developer and tester share a definition of done</li>
<li><strong>Review</strong> — AI re-reads the whole package for gaps, ambiguity and contradiction</li>
<li><strong>Prioritisation</strong> — AI proposes, a person decides scope</li>
</ol>
]]></content:encoded>
      <enclosure url="https://blog.taleedevops.today/assets/images/ai-sdlc/session-2.jpg" type="image/jpeg"/>
    </item>
    <item>
      <title>Session 3 — AI-Driven Development and Quality Engineering</title>
      <link>https://blog.taleedevops.today/ai-sdlc/session-3-ai-driven-development-and-qa.html</link>
      <guid>https://blog.taleedevops.today/ai-sdlc/session-3-ai-driven-development-and-qa.html</guid>
      <source url="https://blog.taleedevops.today/rss.xml">Session 3 — AI-Driven Development and Quality Engineering</source>
      <description>One task at a time, tests that check behaviour rather than implementation, and a review where AI reports but never fixes.</description>
      <category>AI-Driven SDLC</category>
      <pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[
<p>One sentence on slide 3 carries the whole day:</p>
<blockquote>
<p><strong>AI is only strong when the specification is good enough.</strong></p>
</blockquote>
<p>Sessions 1 and 2 were an argument for building context. Session 3 is where you find out whether that
argument paid. The AI-Ready Specification Package assembled on Day 2 stops being a deliverable and
becomes an input — the <em>only</em> input — for writing code, writing tests, and deciding whether any of it
ships.</p>
<div class="hint-container info">
<p class="hint-container-title">About this write-up</p>
<p>These are my notes from Day 3 of the <em>AI-Driven Software Development Life-Cycle</em> course, taught by
<strong>Dr. Bùi Thị Mai Anh</strong>, School of Information and Communication Technology (SOICT), Hanoi
University of Science and Technology, July 2026. The framing and the workshop design are hers; the
summary and wording here are mine. The prompts reproduced below are taken from the course workbook —
they are the instructor's, not mine, and I have translated them into English.</p>
<p>It follows <a href="/ai-sdlc/session-1-traditional-to-ai-driven-sdlc.html" target="_blank">Session 1</a> and
<a href="/ai-sdlc/session-2-ai-driven-requirements-and-design.html" target="_blank">Session 2</a>. A
<a href="/vi/ai-sdlc/session-3-phat-trien-va-dam-bao-chat-luong-voi-ai.html" target="_blank">Vietnamese version</a> of this
article is also available.</p>
</div>
<h2>Where this sits</h2>
]]></content:encoded>
      <enclosure url="https://blog.taleedevops.today/assets/images/ai-sdlc/session-3.jpg" type="image/jpeg"/>
    </item>
    <item>
      <title>Session 4 — AI-Engineering Governance</title>
      <link>https://blog.taleedevops.today/ai-sdlc/session-4-ai-engineering-governance.html</link>
      <guid>https://blog.taleedevops.today/ai-sdlc/session-4-ai-engineering-governance.html</guid>
      <source url="https://blog.taleedevops.today/rss.xml">Session 4 — AI-Engineering Governance</source>
      <description>Context debt: what it costs when a team ships fast for three months and leaves no trail back. A failure taxonomy and six governance principles.</description>
      <category>AI-Driven SDLC</category>
      <pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[
<p>A team ships fast for three months. In month four the requirement changes — loan applications now need
video verification of the borrower. Two weeks of work. Not because the change is hard, but because
<strong>the main workload is understanding the code the AI wrote.</strong></p>
<p>That is the failure Session 4 is about. The team moved quickly and left no trail to come back along.</p>
<div class="hint-container info">
<p class="hint-container-title">About this write-up</p>
<p>These are my notes from Day 4 of the <em>AI-Driven Software Development Life-Cycle</em> course, taught by
<strong>Dr. Bùi Thị Mai Anh</strong>, School of Information and Communication Technology (SOICT), Hanoi
University of Science and Technology, July 2026. The framing and the workshop design are hers; the
summary and wording here are mine. The prompts reproduced below are taken from the course workbook —
they are the instructor's, not mine, and I have translated them into English.</p>
<p>It follows <a href="/ai-sdlc/session-1-traditional-to-ai-driven-sdlc.html" target="_blank">Session 1</a>,
<a href="/ai-sdlc/session-2-ai-driven-requirements-and-design.html" target="_blank">Session 2</a> and
<a href="/ai-sdlc/session-3-ai-driven-development-and-qa.html" target="_blank">Session 3</a>. A
<a href="/vi/ai-sdlc/session-4-quan-tri-ai-engineering.html" target="_blank">Vietnamese version</a> of this article is also
available.</p>
</div>
<h2>Context debt</h2>
<p>The course gives the condition a name:</p>
<blockquote>
<p><strong>Context debt</strong> is the state where technical and business knowledge is no longer held in
engineering artifacts, and survives only in people's memory or in chat history with an AI.</p>
</blockquote>
<p>Technical debt you can see in the code. Context debt is invisible until someone asks a question and
nobody can answer it.</p>
<p>Three questions that expose it:</p>
<p><strong>"Why is this premium?"</strong> — <em>"The PO said so back in March."</em> — <em>"Is it documented?"</em> — <em>"No."</em>
When business logic lives only in the heads of people who were there, or inside the code, the team
is vibe coding whether or not it thinks of itself that way.</p>
<p><strong>"What does <em>verified</em> mean?"</strong> The rule is <code>Verified = OCR AND valid ID AND face match AND blacklist check</code>. The unit tests check the implementation, not that rule. Behaviour tests protect the
business; implementation tests only protect the current shape of the code.</p>
<p><strong>"The PO changed the rule two months in."</strong> Originally: disburse only after the customer is
verified. Now: VIP customers get disbursed first and complete verification within 24 hours. With good
traceability you know exactly which use cases, criteria, tests and modules that touches. Without it,
you go looking.</p>
<h2>The failure taxonomy</h2>
<p>Failures get sorted into groups, because each group needs a different fix.</p>
<p><strong>Context loss</strong></p>
<p>| Failure | What it looks like |
|</p>
]]></content:encoded>
      <enclosure url="https://blog.taleedevops.today/assets/images/ai-sdlc/session-4.jpg" type="image/jpeg"/>
    </item>
    <item>
      <title>Session 5 — AI-Driven Workflow</title>
      <link>https://blog.taleedevops.today/ai-sdlc/session-5-ai-driven-workflow.html</link>
      <guid>https://blog.taleedevops.today/ai-sdlc/session-5-ai-driven-workflow.html</guid>
      <source url="https://blog.taleedevops.today/rss.xml">Session 5 — AI-Driven Workflow</source>
      <description>A quality gate is sufficient evidence, not a green test run — plus five review rules for code no human wrote.</description>
      <category>AI-Driven SDLC</category>
      <pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[
<p>The last slide of the course puts it in one line:</p>
<blockquote>
<p>AI helps us <strong>execute faster</strong>. Humans help us <strong>decide better.</strong></p>
</blockquote>
<p>And the first content slide sets up why the previous four days were necessary:</p>
<blockquote>
<p>The final challenge is not using AI better. It is designing an <strong>engineering system</strong> that AI can
take part in <strong>safely</strong>.</p>
</blockquote>
<div class="hint-container info">
<p class="hint-container-title">About this write-up</p>
<p>These are my notes from Day 5 — the final session — of the <em>AI-Driven Software Development
Life-Cycle</em> course, taught by <strong>Dr. Bùi Thị Mai Anh</strong>, School of Information and Communication
Technology (SOICT), Hanoi University of Science and Technology, July 2026. The framing is hers; the
summary and wording here are mine.</p>
<p>Unlike Days 2–4 this session ships <strong>no workbook</strong> — the practical half is a capstone project and
presentation, so there are no prompts to reproduce here.</p>
<p>It follows <a href="/ai-sdlc/session-1-traditional-to-ai-driven-sdlc.html" target="_blank">Session 1</a>,
<a href="/ai-sdlc/session-2-ai-driven-requirements-and-design.html" target="_blank">Session 2</a>,
<a href="/ai-sdlc/session-3-ai-driven-development-and-qa.html" target="_blank">Session 3</a> and
<a href="/ai-sdlc/session-4-ai-engineering-governance.html" target="_blank">Session 4</a>. A
<a href="/vi/ai-sdlc/session-5-quy-trinh-lam-viec-ai-driven.html" target="_blank">Vietnamese version</a> of this article is also
available.</p>
</div>
<h2>AI-assisted is a loop; AI-driven is a system</h2>
<p>The distinction the session opens with is sharper than the usual buzzword pair.</p>
<p><strong>AI-assisted activities</strong> are a loop one person runs: <em>prompt → generate → review → test → fix</em>, and
back around. It works. It just does not accumulate anything.</p>
<p><strong>An AI-driven engineering system</strong> is defined by five properties instead of five verbs:</p>
<p>| Property | What it means |
|</p>
]]></content:encoded>
      <enclosure url="https://blog.taleedevops.today/assets/images/ai-sdlc/session-5.jpg" type="image/jpeg"/>
    </item>
    <item>
      <title>What is Spring boot</title>
      <link>https://blog.taleedevops.today/backend/java/1.html</link>
      <guid>https://blog.taleedevops.today/backend/java/1.html</guid>
      <source url="https://blog.taleedevops.today/rss.xml">What is Spring boot</source>
      <description>What Spring Boot is and what it changes: auto-configuration, embedded servers, production-ready features, and why it suits microservices.</description>
      <category>springboot</category>
      <pubDate>Sun, 23 Jun 2024 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[
<p>Spring Boot is an open-source Java-based framework used to create standalone, production-grade Spring applications with minimal configuration. It is built on top of the Spring Framework and simplifies the development process by offering a convention-over-configuration approach. Spring Boot eliminates the need for extensive boilerplate code, allowing developers to quickly set up and run new Spring applications. Key features include:</p>
<p>Auto-Configuration: Automatically configures your Spring application based on the dependencies you have added.
Embedded Servers: Comes with embedded Tomcat, Jetty, or Undertow servers, eliminating the need for deploying WAR files.
Production-Ready Features: Provides metrics, health checks, and externalized configuration to help in managing the application in production environments.
Spring CLI: A command-line tool that helps in quickly developing Spring applications using Groovy scripts.
Spring Boot is widely used for microservices architecture due to its simplicity and efficiency in setting up and managing independent services.</p>
]]></content:encoded>
      <enclosure url="https://blog.taleedevops.today/assets/images/springboot/springboot_v1.jpg" type="image/jpeg"/>
    </item>
    <item>
      <title>What is Backend Developer? Roadmap to Becoming a Backend Developer</title>
      <link>https://blog.taleedevops.today/backend/java/2.html</link>
      <guid>https://blog.taleedevops.today/backend/java/2.html</guid>
      <source url="https://blog.taleedevops.today/rss.xml">What is Backend Developer? Roadmap to Becoming a Backend Developer</source>
      <description>What a backend developer actually does, and the roadmap to becoming one — languages, databases, web servers and API technologies worth learning.</description>
      <category>backend</category>
      <pubDate>Mon, 24 Jun 2024 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[
<p>Why are backend developers always in high demand? Is the learning path to becoming a backend developer easy? Let's explore interesting information about Backend Developers with my Blog!</p>
<h2>1. Introduction</h2>
<p>Many applications have a front end and a back end. The front end is the user interface—the part that users interact with. The back end runs behind the scenes on a server and is responsible for overall application functionality.</p>
<figure><img src="/assets/images/backend/backend_java_2_v2.webp" alt="" tabindex="0" loading="lazy"><figcaption></figcaption></figure>
<p>Whenever you submit form data, upload files, access databases, or run other complex operations, these commands are executed on the back-end and results are posted back to the front end.</p>
<p>In essence, back-end development is about building the core of the application. Backend engineers use various frameworks, open-source programming languages, libraries, and APIs to accomplish their tasks.</p>
<h2>2. What is a Backend Developer?</h2>
<p>A backend developer is a type of software developer who focuses on the server-side of web applications. They are responsible for creating, managing, and maintaining the technology that powers the backend of a website or web application. This includes server logic, databases, and APIs (Application Programming Interfaces) that connect the frontend (what users interact with) to the backend (the server and database).</p>
<h2>3. Popular Technologies and Languages for Backend Development</h2>
<p>Backend development involves a variety of technologies and languages. Here are some of the most popular ones:</p>
<h3>Programming Languages:</h3>
<figure><img src="/assets/images/backend/backend_java_2_v3.webp" alt="" tabindex="0" loading="lazy"><figcaption></figcaption></figure>
<ol>
<li>
<p>JavaScript (Node.js):</p>
<ul>
<li>Node.js: Allows for server-side scripting using JavaScript, making it possible to use a single programming language for both frontend and backend.</li>
</ul>
</li>
<li>
<p>Python:</p>
<ul>
<li>
<p>Django: A high-level framework that encourages rapid development and clean, pragmatic design.</p>
</li>
<li>
<p>Flask: A lightweight framework for building web applications with Python.</p>
</li>
</ul>
</li>
<li>
<p>Java:</p>
<ul>
<li>Spring: A comprehensive framework for building enterprise-grade applications.</li>
</ul>
</li>
<li>
<p>Ruby:</p>
<ul>
<li>Ruby on Rails: A robust framework that makes it easy to build database-backed web applications.</li>
</ul>
</li>
<li>
<p>PHP:</p>
<ul>
<li>
<p>Laravel: A web application framework with expressive, elegant syntax.</p>
</li>
<li>
<p>Symfony: A set of reusable PHP components and a PHP framework for web projects.</p>
</li>
</ul>
</li>
<li>
<p>C#:</p>
<ul>
<li>ASP.NET: A framework for building web applications and services with .NET and C#.</li>
</ul>
</li>
<li>
<p>Go:</p>
<ul>
<li>Known for its simplicity and performance, especially for concurrent applications.</li>
</ul>
</li>
<li>
<p>Rust:</p>
<ul>
<li>Gaining popularity for its performance and safety features.</li>
</ul>
</li>
</ol>
<h3>Database:</h3>
<figure><img src="/assets/images/backend/backend_java_2_v4.webp" alt="" tabindex="0" loading="lazy"><figcaption></figcaption></figure>
<ol>
<li>
<p>SQL Databases:</p>
<ul>
<li>
<p>MySQL: An open-source relational database management system.</p>
</li>
<li>
<p>PostgreSQL: A powerful, open-source object-relational database system.</p>
</li>
<li>
<p>SQLite: A C-language library that implements a small, fast, self-contained SQL database engine.</p>
</li>
</ul>
</li>
<li>
<p>NoSQL Databases:</p>
<ul>
<li>
<p>MongoDB: A document-oriented database that stores data in JSON-like documents.</p>
</li>
<li>
<p>Redis: An in-memory data structure store used as a database, cache, and message broker.</p>
</li>
<li>
<p>Cassandra: A distributed NoSQL database designed to handle large amounts of data across many commodity servers.</p>
</li>
</ul>
</li>
</ol>
<h3>Web Servers:</h3>
<ol>
<li>
<p>Nginx:</p>
<ul>
<li>A high-performance web server, reverse proxy, and load balancer.</li>
</ul>
</li>
<li>
<p>Apache:</p>
<ul>
<li>An open-source web server that provides a secure, efficient, and extensible server.</li>
</ul>
</li>
</ol>
<h3>API Technologies:</h3>
<ol>
<li>
<p>RESTful APIs:</p>
<ul>
<li>REST (Representational State Transfer) is an architectural style for designing networked applications.</li>
</ul>
</li>
<li>
<p>GraphQL:</p>
<ul>
<li>A query language for your API, and a server-side runtime for executing queries by using a type system you define for your data.</li>
</ul>
</li>
</ol>
<h3>DevOps and Containerization:</h3>
<ol>
<li>
<p>Docker:</p>
<ul>
<li>A platform for developing, shipping, and running applications in containers.</li>
</ul>
</li>
<li>
<p>Kubernetes:</p>
<ul>
<li>An open-source system for automating the deployment, scaling, and management of containerized applications.</li>
</ul>
</li>
<li>
<p>CI/CD Tools:</p>
<ul>
<li>Jenkins, CircleCI, Travis CI: Tools for continuous integration and continuous deployment.</li>
</ul>
</li>
</ol>
<h3>Version Control:</h3>
<figure><img src="/assets/images/backend/backend_java_2_v5.webp" alt="" tabindex="0" loading="lazy"><figcaption></figcaption></figure>
<ol>
<li>
<p>Git:</p>
<ul>
<li>A distributed version control system for tracking changes in source code during software development.</li>
</ul>
</li>
<li>
<p>GitHub, GitLab, Bitbucket:</p>
<ul>
<li>Platforms for hosting and managing Git repositories.</li>
</ul>
</li>
</ol>
<p>These technologies and languages form the backbone of backend development, providing the tools needed to build and maintain robust, scalable, and efficient web applications.</p>
<h2>4. The Role of a Backend Developer</h2>
<p>Backend developers are essential to the development of web applications, focusing on the server-side logic, databases, and integration of various services. Here’s a detailed look at their role:</p>
<h3>Key Responsibilities:</h3>
<ol>
<li>
<p>Server-Side Development:</p>
<ul>
<li>
<p>Logic Implementation: Develop and maintain the core logic that powers web applications</p>
</li>
<li>
<p>Performance Optimization: Ensure the server responds quickly and efficiently to requests.</p>
</li>
<li>
<p>Scalability: Design systems that can handle increased load by optimizing code and database queries.</p>
</li>
</ul>
</li>
<li>
<p>Database Management:</p>
<ul>
<li>
<p>Database Design: Create and manage databases that store and organize data efficiently.</p>
</li>
<li>
<p>Data Integrity: Implement measures to ensure data is accurate and consistent across the database.</p>
</li>
<li>
<p>Backup and Recovery: Develop strategies for data backup and restoration to prevent data loss.</p>
</li>
</ul>
</li>
<li>
<p>API Development and Integration:</p>
<ul>
<li>
<p>API Design: Create APIs to allow the frontend to communicate with the backend and other services.</p>
</li>
<li>
<p>Third-Party Integration: Integrate external services and APIs to enhance functionality.</p>
</li>
</ul>
</li>
<li>
<p>Security and Data Protection:</p>
<ul>
<li>
<p>Authentication and Authorization: Implement robust authentication and authorization mechanisms to protect user data.</p>
</li>
<li>
<p>Data Encryption: Ensure data is encrypted during transmission and storage to prevent unauthorized access.</p>
</li>
</ul>
</li>
<li>
<p>Collaboration and Communication:</p>
<ul>
<li>
<p>Team Collaboration: Work closely with frontend developers, designers, and project managers to align on project goals.</p>
</li>
<li>
<p>Documentation: Write clear documentation for code, APIs, and system architecture to facilitate collaboration and future maintenance.</p>
</li>
</ul>
</li>
<li>
<p>Testing and Debugging:</p>
<ul>
<li>
<p>Unit Testing: Write unit tests to ensure individual components function correctly.</p>
</li>
<li>
<p>Integration Testing: Test the interaction between different parts of the application.</p>
</li>
<li>
<p>Debugging: Identify and fix bugs that arise during development and production.</p>
</li>
</ul>
</li>
<li>
<p>Version Control and Deployment:</p>
<ul>
<li>
<p>Version Control Systems: Use tools like Git to manage code changes and collaborate with other developers.</p>
</li>
<li>
<p>Continuous Integration/Continuous Deployment (CI/CD): Set up CI/CD pipelines to automate testing and deployment processes.</p>
</li>
</ul>
</li>
</ol>
<h3>Skills Required:</h3>
<ol>
<li>
<p>Programming Languages:</p>
<ul>
<li>Proficiency in backend languages such as JavaScript (Node.js), Python, Java, Ruby, PHP, C#, and Go.</li>
</ul>
</li>
<li>
<p>Database Management:</p>
<ul>
<li>Knowledge of SQL and NoSQL databases, including MySQL, PostgreSQL, MongoDB, and Redis.</li>
</ul>
</li>
<li>
<p>API Development:</p>
<ul>
<li>Experience with RESTful and GraphQL APIs.</li>
</ul>
</li>
<li>
<p>Server Management:</p>
<ul>
<li>Understanding of server architecture and experience with tools like Docker and Kubernetes.</li>
</ul>
</li>
<li>
<p>Security:</p>
<ul>
<li>Knowledge of security best practices, including encryption, authentication, and authorization.</li>
</ul>
</li>
<li>
<p>Problem-Solving:</p>
<ul>
<li>Strong analytical skills to identify and resolve issues efficiently.</li>
</ul>
</li>
<li>
<p>Version Control:</p>
<ul>
<li>Proficiency with Git and understanding of version control principles.</li>
</ul>
</li>
</ol>
<h3>Tools and Technologies:</h3>
<ol>
<li>
<p>Frameworks and Libraries:</p>
<ul>
<li>Node.js for JavaScript, Django and Flask for Python, Spring for Java, Ruby on Rails for Ruby, Laravel and Symfony for PHP, and ASP.NET for C#.</li>
</ul>
</li>
<li>
<p>Databases:</p>
<ul>
<li>SQL databases like MySQL, PostgreSQL, SQLite, and NoSQL databases like MongoDB, Redis, Cassandra.</li>
</ul>
</li>
<li>
<p>Web Servers:</p>
<ul>
<li>Nginx and Apache.</li>
</ul>
</li>
<li>
<p>DevOps Tools:</p>
<ul>
<li>Docker for containerization, Kubernetes for orchestration, and CI/CD tools like Jenkins, CircleCI, and Travis CI.</li>
</ul>
</li>
<li>
<p>Version Control:</p>
<ul>
<li>Git and platforms like GitHub, GitLab, and Bitbucket.</li>
</ul>
</li>
</ol>
<p>Backend developers are vital to the creation and maintenance of functional, secure, and scalable web applications. Their role encompasses a wide range of responsibilities, from server-side logic and database management to API development and security implementation. Mastery of various programming languages, tools, and technologies is essential for backend developers to succeed in their roles.</p>
<h2>5. Essential Skills for a Backend Developer</h2>
<p>Backend development requires a diverse set of skills to handle the complexities of server-side logic, database management, and system integrations. Here are the essential skills every backend developer should possess:</p>
<ol>
<li>
<p>Programming Languages:</p>
<ul>
<li>
<p>Java: A robust, object-oriented language often used in enterprise-level applications with the Spring framework.</p>
</li>
<li>
<p>Go: Known for its performance and efficiency in concurrent applications.</p>
</li>
<li>
<p>Python: Widely used for its simplicity and readability, with popular frameworks like Django and Flask.</p>
</li>
</ul>
</li>
<li>
<p>Database Management:</p>
<ul>
<li>
<p>SQL Databases: Proficiency in relational databases like MySQL, PostgreSQL, and SQLite.</p>
</li>
<li>
<p>NoSQL Databases: Experience with document-oriented databases like MongoDB, in-memory data stores like Redis, and distributed databases like Cassandra.</p>
</li>
<li>
<p>Database Design: Skills in designing efficient database schemas and understanding normalization and denormalization.</p>
</li>
<li>
<p>Query Optimization: Ability to write efficient queries and understand indexing, query planning, and performance tuning.</p>
</li>
</ul>
</li>
<li>
<p>API Development and Integration:</p>
<ul>
<li>
<p>RESTful APIs: Understanding of REST principles to build scalable and maintainable APIs.</p>
</li>
<li>
<p>GraphQL: Knowledge of GraphQL for more flexible and efficient data querying.</p>
</li>
<li>
<p>API Security: Implementation of authentication and authorization methods (e.g., OAuth, JWT).</p>
</li>
</ul>
</li>
<li>
<p>Server Management:</p>
<ul>
<li>
<p>Server Architecture: Understanding of server setup, configuration, and management.</p>
</li>
<li>
<p>Web Servers: Experience with Nginx and Apache for serving web applications.</p>
</li>
<li>
<p>Containerization: Proficiency with Docker for containerizing applications.</p>
</li>
<li>
<p>Orchestration: Knowledge of Kubernetes for managing containerized applications.</p>
</li>
</ul>
</li>
<li>
<p>Security:</p>
<ul>
<li>
<p>Data Protection: Implementing encryption for data at rest and in transit.</p>
</li>
<li>
<p>Secure Coding Practices: Understanding common security vulnerabilities (e.g., SQL injection, XSS) and how to prevent them.</p>
</li>
<li>
<p>Authentication and Authorization: Implementing secure user authentication and role-based access control.</p>
</li>
</ul>
</li>
<li>
<p>Version Control:</p>
<ul>
<li>
<p>Git: Proficiency with Git for version control and collaboration.</p>
</li>
<li>
<p>Platforms: Experience with GitHub, GitLab, or Bitbucket for code repository management.</p>
</li>
</ul>
</li>
<li>
<p>Performance Optimization:</p>
<ul>
<li>
<p>Caching Strategies: Using caching mechanisms (e.g., Redis, Memcached) to improve performance.</p>
</li>
<li>
<p>Load Balancing: Implementing load balancers to distribute traffic across multiple servers.</p>
</li>
<li>
<p>Scalability: Designing applications that can scale horizontally and vertically.</p>
</li>
</ul>
</li>
<li>
<p>Testing and Debugging:</p>
<ul>
<li>
<p>Unit Testing: Writing unit tests to verify individual components.</p>
</li>
<li>
<p>Integration Testing: Testing the interaction between different parts of the application.</p>
</li>
<li>
<p>Debugging Tools: Proficiency with debugging tools and techniques to identify and fix issues.</p>
</li>
</ul>
</li>
<li>
<p>DevOps and CI/CD:</p>
<ul>
<li>
<p>CI/CD Pipelines: Setting up continuous integration and continuous deployment pipelines using tools like Jenkins, CircleCI, or Travis CI.</p>
</li>
<li>
<p>Infrastructure as Code: Using tools like Terraform or Ansible for infrastructure management.</p>
</li>
</ul>
</li>
<li>
<p>Soft Skills:</p>
<ul>
<li>
<p>Problem-Solving: Strong analytical skills to troubleshoot and resolve issues.</p>
</li>
<li>
<p>Communication: Effective communication skills to collaborate with frontend developers, designers, and stakeholders.</p>
</li>
<li>
<p>Time Management: Ability to prioritize tasks and manage time effectively.</p>
</li>
</ul>
</li>
</ol>
<p>Backend development requires a blend of technical and soft skills to manage the complexities of server-side operations, database interactions, and application security. Mastery of these essential skills enables backend developers to build robust, scalable, and efficient web applications.</p>
<h2>6. Benefits and Challenges of Being a Backend Developer</h2>
<h3>Benefits of Being a Backend Developer</h3>
<ol>
<li>
<p>High Demand and Job Security:</p>
<ul>
<li>
<p>Strong Job Market: The demand for skilled backend developers is consistently high, providing numerous job opportunities.</p>
</li>
<li>
<p>Job Stability: Given the essential role backend developers play in web and software development, they enjoy a level of job security.</p>
</li>
</ul>
</li>
<li>
<p>Competitive Salaries:</p>
<ul>
<li>Attractive Compensation: Backend developers often receive competitive salaries, reflecting their specialized skills and importance in the tech industry.</li>
</ul>
</li>
<li>
<p>Opportunities for Advancement:</p>
<ul>
<li>
<p>Career Growth: There are clear paths for career advancement, from senior backend developer roles to technical lead or engineering manager positions.</p>
</li>
<li>
<p>Skill Development: Continuous learning and skill development can lead to further opportunities in various tech domains.</p>
</li>
</ul>
</li>
</ol>
<h3>Challenges of Being a Backend Developer</h3>
<ol>
<li>
<p>Complex Problem-Solving:</p>
<ul>
<li>
<p>Technical Complexity: Backend development involves complex problem-solving and requires a deep understanding of various technologies and systems.</p>
</li>
<li>
<p>Debugging Issues: Identifying and fixing bugs, especially in large codebases, can be challenging and time-consuming.</p>
</li>
</ul>
</li>
<li>
<p>High Responsibility:</p>
<ul>
<li>
<p>System Reliability: Backend developers are responsible for the reliability and performance of applications, which can be a significant pressure.</p>
</li>
<li>
<p>Security Concerns: Ensuring data security and protecting against breaches is a critical and ongoing challenge.</p>
</li>
</ul>
</li>
<li>
<p>Keeping Up with Technology:</p>
<ul>
<li>
<p>Rapid Technological Changes: The fast pace of technological advancements requires continuous learning and adaptation.</p>
</li>
<li>
<p>Learning Curve: Mastering new tools, languages, and frameworks can be demanding</p>
</li>
</ul>
</li>
<li>
<p>Workload Management:</p>
<ul>
<li>
<p>Deadlines: Managing tight deadlines and delivering high-quality work under pressure is a common challenge.</p>
</li>
<li>
<p>Task Prioritization: Balancing multiple tasks and projects requires excellent time management and prioritization skills.</p>
</li>
</ul>
</li>
</ol>
<h2>7. Career Opportunities and Development Path</h2>
<p>Backend development offers a wide range of career opportunities and a clear development path for those interested in progressing within the field. Here’s an overview of the potential career trajectory and the opportunities available:</p>
<h3>Entry-Level Positions</h3>
<ol>
<li>
<p>Junior Backend Developer:</p>
<ul>
<li>
<p>Responsibilities: Assist in developing and maintaining backend components, write simple scripts, and handle minor bug fixes.</p>
</li>
<li>
<p>Skills Needed: Basic knowledge of programming languages (e.g., JavaScript, Python, Java), understanding of databases, and familiarity with version control systems like Git.</p>
</li>
</ul>
</li>
</ol>
<h3>Mid-Level Positions</h3>
<ol start="2">
<li>
<p>Backend Developer:</p>
<ul>
<li>
<p>Responsibilities: Develop server-side logic, manage databases, create APIs, ensure application performance, and implement security measures.</p>
</li>
<li>
<p>Skills Needed: Proficiency in backend programming languages and frameworks, experience with SQL and NoSQL databases, knowledge of RESTful and GraphQL APIs, and understanding of server management.</p>
</li>
</ul>
</li>
<li>
<p>DevOps Engineer:</p>
<ul>
<li>
<p>Responsibilities: Oversee the deployment, automation, and management of applications, work with CI/CD pipelines, and ensure infrastructure scalability and reliability.</p>
</li>
<li>
<p>Skills Needed: Knowledge of cloud platforms (AWS, Azure, GCP), containerization tools (Docker, Kubernetes), and automation scripts (Ansible, Terraform).</p>
</li>
</ul>
</li>
</ol>
<h3>Senior-Level Positions</h3>
<ol start="4">
<li>
<p>Senior Backend Developer:</p>
<ul>
<li>
<p>Responsibilities: Lead backend development projects, mentor junior developers, design complex systems, optimize application performance, and ensure robust security practices.</p>
</li>
<li>
<p>Skills Needed: Advanced knowledge of multiple backend languages and frameworks, extensive experience with databases, strong problem-solving skills, and leadership abilities.</p>
</li>
</ul>
</li>
<li>
<p>Technical Lead / Team Lead:</p>
<ul>
<li>
<p>Responsibilities: Oversee the technical direction of projects, coordinate between different development teams, ensure code quality, and guide the team in best practices.</p>
</li>
<li>
<p>Skills Needed: Strong technical expertise, excellent leadership and communication skills, ability to manage multiple projects, and experience in project management.</p>
</li>
</ul>
</li>
</ol>
<h3>Development Path</h3>
<ol>
<li>
<p>Education and Learning:</p>
<ul>
<li>
<p>Formal Education: Obtain a degree in Computer Science, Software Engineering, or a related field.</p>
</li>
<li>
<p>Online Courses and Bootcamps: Participate in coding bootcamps and online courses (e.g., Coursera, Udemy, edX) to gain practical skills.</p>
</li>
</ul>
</li>
<li>
<p>Skill Development:</p>
<ul>
<li>
<p>Programming Languages: Master backend languages such as JavaScript (Node.js), Python, Java, Ruby, PHP, C#, and Go.</p>
</li>
<li>
<p>Frameworks and Tools: Gain proficiency in frameworks (e.g., Django, Spring, Ruby on Rails) and tools (e.g., Docker, Kubernetes).</p>
</li>
</ul>
</li>
<li>
<p>Practical Experience:</p>
<ul>
<li>
<p>Projects and Internships: Work on real-world projects, contribute to open-source projects, and pursue internships to gain hands-on experience.</p>
</li>
<li>
<p>Build a Portfolio: Create a portfolio showcasing your projects, code samples, and contributions to open-source communities.</p>
</li>
</ul>
</li>
<li>
<p>Certifications:</p>
<ul>
<li>Certifications: Obtain relevant certifications (e.g., AWS Certified Solutions Architect, Microsoft Certified: Azure Developer Associate) to validate your skills and knowledge.</li>
</ul>
</li>
<li>
<p>Networking and Community Involvement:</p>
<ul>
<li>
<p>Networking: Attend industry conferences, join professional networks (e.g., LinkedIn), and participate in local tech meetups.</p>
</li>
<li>
<p>Community: Engage with online communities (e.g., Stack Overflow, GitHub), contribute to discussions, and share your knowledge.</p>
</li>
</ul>
</li>
</ol>
<h2>8. Conclusion</h2>
<p>Society is constantly changing and developing, especially with the rapid advancements in technology. Backend developers must continually enhance their professional skills and stay updated with the latest technology trends. Additionally, participating in programming communities can help you hone your skills and learn from others in the field.</p>
]]></content:encoded>
      <enclosure url="https://blog.taleedevops.today/assets/images/backend/backend_java_2_v1.jpg" type="image/jpeg"/>
    </item>
    <item>
      <title>Complete Overview of Spring Boot</title>
      <link>https://blog.taleedevops.today/backend/java/3.html</link>
      <guid>https://blog.taleedevops.today/backend/java/3.html</guid>
      <source url="https://blog.taleedevops.today/rss.xml">Complete Overview of Spring Boot</source>
      <description>Why Spring Boot exists when Spring already did: its features, core concepts, and a roadmap for learning it in a sensible order.</description>
      <category>backend</category>
      <pubDate>Sat, 29 Jun 2024 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[
<p>Spring Boot is an open-source, microservice-based framework used to create stand-alone, production-grade Spring-based applications with minimal configuration. It is a project within the larger Spring ecosystem and aims to simplify the development of new Spring applications.</p>
<h2>Why Spring Boot if There is Already Spring!</h2>
<p>Spring is widely used for creating scalable applications. In the case of web applications, Spring provides Spring MVC which is widely used to create scalable web applications. But the major drawback of spring projects is that configuration is really time-taking and can be a bit tedious for the new developers. To make the application production-ready takes some time in spring. And the solution for this is Spring Boot.</p>
<p>Spring Boot is created on the top of the spring and includes all the features of spring. And is becoming a favorite of developers these days because of its rapid production-ready environment which allows the developers to directly concentrate on the logic instead of struggling with the configuration and setup.</p>
<h2>What is Spring Boot?</h2>
<p>Spring Boot is an open-source Java framework designed to simplify the development of Java-based web applications. It is built on top of the popular Spring framework and provides a convention-over-configuration approach, which allows developers to quickly create production-ready applications with little effort.</p>
<p>The primary goal of Spring Boot is to remove boilerplate code and complex configurations that developers often encounter when building web applications with the Spring framework. It comes with a set of opinionated defaults and auto-configuration capabilities, which reduces the time and effort needed to set up a Spring web application.</p>
<p>It is very easy to create stand-alone, production-grade Spring-based Applications that you can “<strong>just run</strong>“</p>
<h2>Features of Spring Boot</h2>
<figure><img src="/assets/images/backend/java/backend_java_3_v1.webp" alt="" tabindex="0" loading="lazy"><figcaption></figcaption></figure>
<ol>
<li>
<p><strong>Auto-Configuration</strong>: Automatically configures your Spring application based on the dependencies you have added. For example, if H2 database is in the classpath, Spring Boot automatically sets up an in-memory database.</p>
</li>
<li>
<p><strong>Standalone</strong>: Spring Boot applications can run independently without needing an external application server. They can be run from the command line using java -jar.</p>
</li>
<li>
<p><strong>Embedded Servers</strong>: Spring Boot comes with embedded servers such as Tomcat, Jetty, and Undertow, which makes it easy to develop and test web applications.</p>
</li>
<li>
<p><strong>Opinionated Defaults</strong>: It provides sensible defaults out-of-the-box, reducing the need for boilerplate configuration.</p>
</li>
<li>
<p><strong>Production-Ready Features</strong>: Includes a range of non-functional features, such as metrics, health checks, and externalized configuration, essential for running applications in production.</p>
</li>
<li>
<p><strong>Spring CLI</strong>: Command-line tool that helps to bootstrap a new project with Spring Boot.</p>
</li>
<li>
<p><strong>Starter Dependencies</strong>: Spring Boot provides a wide range of "starter" dependencies. These are pre-configured dependency bundles. These starters simplify dependency management by providing a set of dependencies for specific functionalities such as data access, security, testing, etc.</p>
</li>
</ol>
<h2>Core Concepts of Spring Boot</h2>
<ol>
<li>
<p><strong>Spring Boot Starters</strong>: Starters are a set of convenient dependency descriptors you can include in your application. For example, spring-boot-starter-web includes everything to start a web application.</p>
</li>
<li>
<p><strong>Spring Boot AutoConfigurator</strong>: Auto-Configuration is a mechanism that automatically configures Spring applications based on the dependencies in the classpath.</p>
</li>
<li>
<p><strong>Spring Boot Actuator</strong>: Provides production-ready features such as monitoring, metrics, and health checks.</p>
</li>
</ol>
<h2>Why You Should Learn Spring Boot</h2>
<figure><img src="/assets/images/backend/java/backend_java_3_v2.webp" alt="" tabindex="0" loading="lazy"><figcaption></figcaption></figure>
<ol>
<li>
<p>Simplified Development</p>
<ul>
<li>
<p><strong>Auto-Configuration</strong>: Automatically configures Spring applications based on the dependencies present in the classpath, reducing the need for extensive XML configuration.</p>
</li>
<li>
<p><strong>Starter POMs</strong>: Provides a variety of starter dependencies that simplify adding necessary libraries and frameworks.</p>
</li>
</ul>
</li>
<li>
<p>Enhanced Productivity</p>
<ul>
<li>
<p><strong>Reduced Boilerplate Code</strong>: Minimizes the amount of boilerplate code developers need to write, enabling faster development cycles.</p>
</li>
<li>
<p><strong>Embedded Servers</strong>: Built-in support for embedded servers like Tomcat, Jetty, and Undertow means you can run your applications directly without needing an external server setup.</p>
</li>
</ul>
</li>
<li>
<p>Microservices Architecture</p>
<ul>
<li>
<p><strong>Modular Development</strong>: Ideal for building microservices, which are small, modular services that can be developed, deployed, and scaled independently.</p>
</li>
<li>
<p><strong>Spring Cloud Integration</strong>: Seamlessly integrates with Spring Cloud for building robust, scalable microservices architectures.</p>
</li>
</ul>
</li>
<li>
<p>Production-Ready Features</p>
<ul>
<li>
<p><strong>Spring Boot Actuator</strong>: Provides out-of-the-box monitoring and management features, including health checks, metrics, and environment information.</p>
</li>
<li>
<p><strong>Externalized Configuration</strong>: Supports externalized configuration to easily manage different environments (development, staging, production) using properties or YAML files.</p>
</li>
</ul>
</li>
<li>
<p>Strong Community Support</p>
<ul>
<li>
<p><strong>Extensive Documentation</strong>: Well-documented and supported by a vibrant community, making it easier to find resources, tutorials, and troubleshooting tips.</p>
</li>
<li>
<p><strong>Ecosystem Integration</strong>: Part of the larger Spring ecosystem, ensuring compatibility and integration with other Spring projects and third-party libraries.</p>
</li>
</ul>
</li>
<li>
<p>Learning Curve</p>
<ul>
<li>
<p><strong>Ease of Learning</strong>: Compared to other Java frameworks, Spring Boot has a gentle learning curve due to its opinionated defaults and extensive documentation.</p>
</li>
<li>
<p><strong>Educational Resources</strong>: A wealth of learning resources, including books, online courses, and community forums, are available to help you get started.</p>
</li>
</ul>
</li>
<li>
<p>Career Advancement</p>
<ul>
<li>
<p><strong>Industry Demand</strong>: Knowledge of Spring Boot is highly valued in the job market, especially for roles in backend development and enterprise application development.</p>
</li>
<li>
<p><strong>Versatile Applications</strong>: Enables you to develop a wide range of applications, from simple web applications to complex enterprise solutions.</p>
</li>
</ul>
</li>
<li>
<p>Modern Development Practices</p>
</li>
</ol>
<ul>
<li>
<p><strong>RESTful APIs</strong>: Simplifies the development of RESTful web services, a common requirement in modern web applications.</p>
</li>
<li>
<p><strong>Reactive Programming</strong>: Supports reactive programming with Spring WebFlux, allowing you to build responsive and resilient applications.</p>
</li>
</ul>
<ol start="9">
<li>
<p>DevOps and CI/CD Integration</p>
<ul>
<li>
<p><strong>Containerization</strong>: Easily containerize Spring Boot applications using Docker, facilitating smoother deployments and scaling.</p>
</li>
<li>
<p><strong>CI/CD Support</strong>: Compatible with continuous integration and continuous deployment (CI/CD) pipelines, streamlining the development workflow.</p>
</li>
</ul>
</li>
<li>
<p>Scalability and Performance</p>
</li>
</ol>
<ul>
<li>
<p><strong>Efficient Resource Management</strong>: Designed to efficiently manage resources, ensuring that applications can scale seamlessly with increasing load.</p>
</li>
<li>
<p><strong>Optimized for Performance</strong>: Fine-tuned for performance, making it suitable for high-traffic applications.</p>
</li>
</ul>
<h2>Best Way to Master Spring Boot – A Roadmap to Learn</h2>
<figure><img src="/assets/images/backend/java/backend_java_3_v3.webp" alt="" tabindex="0" loading="lazy"><figcaption></figcaption></figure>
<!-- <DarkModeImage
  dark-mode-src="/assets/images/backend/java/backend_java_3_v3.webp" 
  light-mode-src="/assets/images/backend/java/backend_java_3_v2.webp" 
  alt-text="Spring Boot Roadmap" 
/> -->
<!-- ![](/assets/images/backend/java/backend_java_3_v3.webp) -->]]></content:encoded>
      <enclosure url="https://blog.taleedevops.today/assets/images/backend/java/backend_java_3_v4.jpg" type="image/jpeg"/>
    </item>
    <item>
      <title>Spring Boot The Framework</title>
      <link>https://blog.taleedevops.today/backend/java/4.html</link>
      <guid>https://blog.taleedevops.today/backend/java/4.html</guid>
      <source url="https://blog.taleedevops.today/rss.xml">Spring Boot The Framework</source>
      <description>The four layers of the Spring Boot framework — presentation, business, persistence, database — and how a request flows through its modified MVC.</description>
      <category>backend</category>
      <pubDate>Sun, 30 Jun 2024 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[
<p>In this blog, we will explore a little about the Spring Boot framework. We will discuss the structure and architecture of the Spring Boot framework and the Spring Boot workflow architecture.</p>
<p>Spring Boot uses the hierarchical architecture where each of the layers is stacked on top of each other and communicate is also in the same fashion.</p>
<h2>Spring Boot Architecture</h2>
<p>Now let’s explore the main layers and architecture of Spring Boot to understand the inner working of the framework. The layers a divided into 4 main categories:</p>
<ul>
<li>
<p><strong>Presentation Layer</strong></p>
</li>
<li>
<p><strong>Business Layer</strong></p>
</li>
<li>
<p><strong>Persistence Layer</strong></p>
</li>
<li>
<p><strong>Database Layer</strong></p>
</li>
</ul>
<p>Nevertheless, soon you will discover that the business layer is the most important layer for a backend engineer as it is where all the logic of your application is written. Now let's explore each of these layers and learn what function they provide.</p>
<figure><img src="/assets/images/backend/java/backend_java_4_v2.webp" alt="" tabindex="0" loading="lazy"><figcaption></figcaption></figure>
<h3>Presentation Layer</h3>
<p>The presentation layer is what the user sees from the outside or what is exposed to the outside world. It can be a JSON structure that is made up of viewpoints. It can be split into the front layer which is what is seen from the outside and a back layer which is where the structure is built from viewpoints. The back layer also interprets JSON and handles authentication and HTTP requests before entering into the business layer.</p>
<h3>Business Layer</h3>
<p>The business layer houses all the logic that is specific to the application under development. It interacts with both the presentational layer and the persistence to perform its responsibilities. It is responsible for performing validations, performing authorization, and handling business logic and rules and it consists of service classes.</p>
<h3>Persistence Layer</h3>
<p>The persistence layer is responsible for all the storage logic including databases and any other form of data persistence. It is responsible for containing storage logic, Fetching objects, and translating them into database rows (and vice versa).</p>
<p>This layer is the equivalent of the Repository interface and database queries are written inside this interface. The Persistence layer is the only layer that communicates with the Business layer and the Database layer.</p>
<h3>Database Layer</h3>
<p>The database layer contains all the databases such as MySQL, MongoDB, Postgres, etc as the name suggests. It is responsible for performing database operations (mainly CRUD operations) and it is the actual database that you decide to use to build your application.</p>
<h2>Spring Boot Workflow</h2>
<p>There’s no doubt that Spring Boot relies heavily on the Spring framework, which means that it integrates almost all of the features and modules of Spring such as Spring MVC, Spring Core, etc.</p>
<p>Therefore, the Spring Boot framework is structured using the popular MVC (Model, View, Controller) pattern that is slightly modified.</p>
<figure><img src="/assets/images/backend/java/backend_java_4_v3.webp" alt="" tabindex="0" loading="lazy"><figcaption></figcaption></figure>
<p>Here is a theoretical example of the workflow of Spring Boot from Request to Response:</p>
<ul>
<li>
<p>First, the Client makes an HTTP request using GET, PUT, POST, etc.</p>
</li>
<li>
<p>The Controller class receives the HTTP request.</p>
</li>
<li>
<p>The Controller understands what type of request will process, and then it deals with it.</p>
</li>
<li>
<p>If it is needed, it calls the Service class.</p>
</li>
<li>
<p>The Service Class is going to handle the business logic. It does this on the data from the database.</p>
</li>
<li>
<p>If everything goes well, it returns a response as a JSP page.</p>
</li>
</ul>
<h2>Modified MVC Architecture</h2>
<p>When you are building a Spring Boot Web API project, typically, you will want your code to be maintainable, modular, and have a separation of concerns. Therefore, the 4 main layers above are further broken down into different smaller components which make up the modified MVC pattern used in Spring Boot.</p>
<p>Below are some of the components that make up the Spring Boot framework and you will encounter these components always as you continue to work with the framework.</p>
<ul>
<li>
<p><strong>Controllers</strong>: Controllers handle incoming HTTP requests and return the appropriate responses. It receives requests from clients, invokes validations and business logic using Services, and returns the response to the client. Controller classes are usually annotated with @RestController or @Controller annotations and also have methods that are annotated with request mapping annotations like @RequestMapping, @GetMapping, @PostMapping, and so on.</p>
</li>
<li>
<p><strong>Services</strong>: Services house the business logic of your application. This is where you write all the complex business rules, and coordinate data access, and transformation operations. They process data, perform validations, apply business rules, and invoke data access operations through repositories or DAOs(Data Access Objects). The service class is an abstraction layer between the controller and the data access layer.</p>
</li>
<li>
<p><strong>Data Access</strong>: Data Access interacts with the underlying data storage systems, such as databases or external Web APIs. It carries out CRUD (Create, Read, Update, Delete) operations on data. It consists of repositories or DAOs (Data Access Objects) that provide an abstraction for database operations. Spring Boot provides support for data access and manipulation through libraries like Spring Data JPA.</p>
</li>
<li>
<p><strong>Models</strong>: Models contain the entities or domain objects that represent the data and the relationships between them. These domain objects are mapped to database tables. Models provide a definition for the structure and behavior of the data used in the application. It may also include DTOs (Data Transfer Objects) and/or View Models for transferring data between layers or to external clients.</p>
</li>
<li>
<p><strong>Exception Handling</strong>: Exception handling deals with capturing and handling exceptions that occur during the execution of the API. It provides a mechanism to catch exceptions, transform them into meaningful error responses, and return them to the client. Spring Boot offers various exception-handling techniques, such as using @ExceptionHandler annotations or implementing custom exception handlers.</p>
</li>
<li>
<p><strong>Configurations</strong>: Configurations contain configuration files and classes required for setting up the Spring Boot web API. It contains properties files (application.properties or application.yml) which are used for configuring various aspects of the application, as well as custom configuration classes that define beans, security settings, or other application-specific configurations.</p>
</li>
</ul>
<h2>Spring Boot Architecture Patterns</h2>
<p>Spring Boot applications often follow certain architectural patterns to achieve modularity, scalability, and maintainability. Here are some common architectural patterns used in Spring Boot development:</p>
<h3>MVC (Model-View-Controller):</h3>
<ul>
<li>
<p>Spring Boot follows the MVC pattern for building web applications.</p>
</li>
<li>
<p>Model: Represents the application’s data and business logic.</p>
</li>
<li>
<p>View: Responsible for rendering the user interface.</p>
</li>
<li>
<p>Controller: Handles user requests, interacts with the model, and updates the view.</p>
</li>
</ul>
<h3>Microservices Architecture:</h3>
<ul>
<li>
<p>Spring Boot is commonly used in microservices architectures where the application is decomposed into small, independently deployable services.</p>
</li>
<li>
<p>Each microservice is responsible for a specific business capability and communicates with other services through APIs.</p>
</li>
</ul>
<h3>Restful API Design:</h3>
<ul>
<li>
<p>Spring Boot promotes the design of RESTful APIs for communication between components.</p>
</li>
<li>
<p>Controllers expose RESTful endpoints, and data is typically exchanged in JSON format.</p>
</li>
</ul>
<h3>Layered Architecture:</h3>
<ul>
<li>
<p>Organising the application into layers like presentation, service, repository, and entity helps maintain a separation of concerns.</p>
</li>
<li>
<p>This layered architecture promotes modularity and testability.</p>
</li>
</ul>
<h3>Dependency Injection (DI) / Inversion of Control (IoC):</h3>
<ul>
<li>
<p>Spring Boot relies heavily on the principle of dependency injection, where dependencies are injected into components rather than being created by the components themselves.</p>
</li>
<li>
<p>This reduces tight coupling and makes the application more maintainable.</p>
</li>
</ul>
<h3>Event-Driven Architecture:</h3>
<ul>
<li>
<p>Spring Boot supports event-driven architecture through the use of Spring Events.</p>
</li>
<li>
<p>Components can publish and subscribe to events, allowing for loosely coupled communication between different parts of the application.</p>
</li>
</ul>
<h3>CQRS (Command Query Responsibility Segregation):</h3>
<ul>
<li>
<p>CQRS separates read and write operations, allowing for independent scaling of the query (read) and command (write) sides.</p>
</li>
<li>
<p>Spring Boot can be used to implement CQRS patterns using different components for command and query responsibilities.</p>
</li>
</ul>
<h3>Saga Pattern:</h3>
<ul>
<li>
<p>In microservices architectures, the saga pattern is often used to manage distributed transactions.</p>
</li>
<li>
<p>Spring Boot applications can implement sagas by coordinating a series of transactions across multiple microservices.</p>
</li>
</ul>
<h3>Gateway Pattern:</h3>
<ul>
<li>
<p>API gateways are used to manage and route requests in microservices architectures.</p>
</li>
<li>
<p>Spring Cloud provides tools like Spring Cloud Gateway for building API gateways.</p>
</li>
</ul>
<p>These patterns can be combined and adapted based on the specific requirements of the application. The flexibility of Spring Boot allows developers to choose and implement the patterns that best suit their needs.</p>
<h2>Architecture of Spring Boot Microservices</h2>
<p>The architecture of Spring Boot microservices typically follows principles that align with the characteristics of microservices, such as modularity, independence, and distributed systems. Here’s a conceptual overview of the architecture for a Spring Boot microservices application:</p>
<h3>Microservices:</h3>
<figure><img src="/assets/images/backend/java/backend_java_4_v5.webp" alt="" tabindex="0" loading="lazy"><figcaption></figcaption></figure>
<ul>
<li>
<p>The application is decomposed into small, independent, and loosely coupled services, each focused on a specific business capability.</p>
</li>
<li>
<p>Microservices communicate with each other through well-defined APIs, often exposed as RESTful endpoints.</p>
</li>
</ul>
<h3>Service Registry and Discovery:</h3>
<figure><img src="/assets/images/backend/java/backend_java_4_v6.webp" alt="" tabindex="0" loading="lazy"><figcaption></figcaption></figure>
<ul>
<li>
<p>Services register themselves with a service registry (e.g., Spring Cloud Netflix Eureka).</p>
</li>
<li>
<p>Service discovery allows services to locate and communicate with each other dynamically.</p>
</li>
</ul>
<h3>API Gateway:</h3>
<figure><img src="/assets/images/backend/java/backend_java_4_v7.webp" alt="" tabindex="0" loading="lazy"><figcaption></figcaption></figure>
<ul>
<li>
<p>An API Gateway (e.g., Spring Cloud Gateway, Netflix Zuul) is used to manage and route external requests to the appropriate microservices.</p>
</li>
<li>
<p>It can handle authentication, load balancing, and routing.</p>
</li>
</ul>
<h3>Configuration Management:</h3>
<figure><img src="/assets/images/backend/java/backend_java_4_v8.webp" alt="" tabindex="0" loading="lazy"><figcaption></figcaption></figure>
<ul>
<li>
<p>Centralised configuration management (e.g., Spring Cloud Config) allows microservices to retrieve configuration properties dynamically.</p>
</li>
<li>
<p>Configuration can be stored in a version-controlled repository and updated without redeploying services.</p>
</li>
</ul>
<h3>Distributed Data Management:</h3>
<figure><img src="/assets/images/backend/java/backend_java_4_v9.webp" alt="" tabindex="0" loading="lazy"><figcaption></figcaption></figure>
<ul>
<li>
<p>Microservices often have their own databases, and the choice of database depends on the specific requirements of each service.</p>
</li>
<li>
<p>Eventual consistency and distributed data management strategies may be employed.</p>
</li>
</ul>
<h3>Event-Driven Architecture:</h3>
<figure><img src="/assets/images/backend/java/backend_java_4_v10.webp" alt="" tabindex="0" loading="lazy"><figcaption></figcaption></figure>
<ul>
<li>
<p>Events and messaging systems (e.g., Spring Cloud Stream, Apache Kafka) are used for communication between microservices.</p>
</li>
<li>
<p>Event-driven architecture supports loose coupling and scalability.</p>
</li>
</ul>
<h3>Polyglot Architecture:</h3>
<figure><img src="/assets/images/backend/java/backend_java_4_v11.webp" alt="" tabindex="0" loading="lazy"><figcaption></figcaption></figure>
<ul>
<li>
<p>Each microservice can be implemented in a different programming language or use a different technology stack, known as a polyglot architecture.</p>
</li>
<li>
<p>The choice of technology is based on the specific requirements of each service.</p>
</li>
</ul>
<h3>Testing and Continuous Integration/Continuous Deployment (CI/CD):</h3>
<figure><img src="/assets/images/backend/java/backend_java_4_v12.webp" alt="" tabindex="0" loading="lazy"><figcaption></figcaption></figure>
<ul>
<li>
<p>Microservices are independently testable, allowing for easier unit testing and integration testing.</p>
</li>
<li>
<p>CI/CD pipelines enable automated testing and deployment of microservices.</p>
</li>
</ul>
<h3>Domain-Driven Design (DDD):</h3>
<figure><img src="/assets/images/backend/java/backend_java_4_v13.webp" alt="" tabindex="0" loading="lazy"><figcaption></figcaption></figure>
<ul>
<li>Microservices are often designed based on domain-driven design principles, emphasising a clear understanding of the business domain and its interactions.</li>
</ul>
<p>This architecture allows for flexibility, scalability, and easy maintenance of a microservices-based system. Spring Cloud provides a set of tools and libraries to implement many of these patterns and streamline the development of microservices in a Spring Boot environment.</p>
]]></content:encoded>
      <enclosure url="https://blog.taleedevops.today/assets/images/backend/java/backend_java_4_v4.jpg" type="image/jpeg"/>
    </item>
    <item>
      <title>Building A Web App with Spring Boot</title>
      <link>https://blog.taleedevops.today/backend/java/building-web-with-spring-boot.html</link>
      <guid>https://blog.taleedevops.today/backend/java/building-web-with-spring-boot.html</guid>
      <source url="https://blog.taleedevops.today/rss.xml">Building A Web App with Spring Boot</source>
      <description>Build a Spring Boot REST API end to end: JDK and IDE setup, Spring Initializr, the entity-repository-service-controller layers, and Postman tests.</description>
      <category>backend</category>
      <pubDate>Mon, 01 Jul 2024 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[
<p>What better way to learn than to understand the theoretical and practical parts of a technical topic? Here are the steps you should take to create a Spring Boot web API.</p>
<h2>1. General introduction</h2>
<p>In this article, we will create a simple Spring Boot API application for managing a club. Through the implementation of this application, we will explore the basic components necessary to build an API application.</p>
<h2>2. Set Up Your Development Environment</h2>
<ul>
<li>
<p>Java Development Kit (JDK): Spring Boot requires JDK 8, 11, or later.</p>
</li>
<li>
<p>Integrated Development Environment (IDE): IntelliJ IDEA, Eclipse, or VS Code are popular choices.</p>
</li>
<li>
<p>Build Tool: Maven or Gradle.</p>
</li>
</ul>
<h3>2.1 <strong>Install JDK</strong></h3>
<ul>
<li>Windows/Mac/Linux: Download and install the JDK from the <a href="https://www.oracle.com/java/technologies/javase-downloads.html" target="_blank" rel="noopener noreferrer">Oracle website</a> or use <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/install/install_overview.html" target="_blank" rel="noopener noreferrer">OpenJDK</a>.</li>
</ul>
<p>Verify the installation by running:</p>
<div class="language-sh line-numbers-mode" data-highlighter="shiki" data-ext="sh" data-title="sh" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">java</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66"> -version</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">javac</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66"> -version</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><h3>2.2 <strong>Install an IDE</strong></h3>
<ul>
<li>
<p>IntelliJ IDEA: Download and install from <a href="https://www.jetbrains.com/idea/download/" target="_blank" rel="noopener noreferrer">JetBrains</a>.</p>
</li>
<li>
<p>Eclipse: Download and install from <a href="https://www.eclipse.org/downloads/" target="_blank" rel="noopener noreferrer">Eclipse</a>.</p>
</li>
<li>
<p>VS Code: Download and install from <a href="https://code.visualstudio.com/" target="_blank" rel="noopener noreferrer">Microsoft</a>.</p>
</li>
</ul>
<h3>2.3 <strong>Install Maven or Gradle</strong></h3>
<ul>
<li>
<p>Maven: Download and install from <a href="https://maven.apache.org/download.cgi" target="_blank" rel="noopener noreferrer">Apache Maven</a>.</p>
</li>
<li>
<p>Gradle: Download and install from <a href="https://gradle.org/install/" target="_blank" rel="noopener noreferrer">Gradle</a>.</p>
</li>
</ul>
<p>Verify the installation:</p>
<div class="language-sh line-numbers-mode" data-highlighter="shiki" data-ext="sh" data-title="sh" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">mvn</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66"> -v</span><span style="--shiki-light:#6A737D;--shiki-dark:#7F848E;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic">  # for Maven</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">gradle</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66"> -v</span><span style="--shiki-light:#6A737D;--shiki-dark:#7F848E;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic">  # for Gradle</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><h2>3. Generate a Spring Boot Project with Spring Initializr</h2>
<p>Spring Initializr is a web-based tool that helps you quickly bootstrap Spring Boot projects. Follow these steps to quickly generate one:</p>
<p>Open your web browser and go to <a href="https://start.spring.io" target="_blank" rel="noopener noreferrer">https://start.spring.io/</a>.</p>
<p>| Project        | Value                                                                                                                                                                                                                                                                                                                                                   |
|</p>
]]></content:encoded>
      <enclosure url="https://blog.taleedevops.today/assets/images/backend/java/building-web-with-spring-boot/title.jpg" type="image/jpeg"/>
    </item>
    <item>
      <title>Deploy Spring Boot Application to AWS EC2 using Docker</title>
      <link>https://blog.taleedevops.today/backend/java/deploy-spring-boot-with-docker-ec2.html</link>
      <guid>https://blog.taleedevops.today/backend/java/deploy-spring-boot-with-docker-ec2.html</guid>
      <source url="https://blog.taleedevops.today/rss.xml">Deploy Spring Boot Application to AWS EC2 using Docker</source>
      <description>Package a Spring Boot service as a Docker image, push it to Docker Hub, and run it on an EC2 instance.</description>
      <category>backend</category>
      <pubDate>Wed, 03 Jul 2024 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[
<p>Here we are going to move a step further and show you how to deploy your project.</p>
<p>Cloud Services are something that none of us can stay away from. If you are into tech then it is kind of impossible that you did not hear about the Cloud.</p>
<p>And those who are familiar to this industry, <code>AWS EC2</code> is not something new.</p>
<p>In this article, I will demonstrate step by step, how to deploy a spring boot application to the <code>AWS EC2 instance</code>.</p>
<p>Source Code — Sample application that I am going to use for this can be downloaded from here — #</p>
<h2>1. General introduction</h2>
<p>In this article, we will deploy a Spring Boot application using Docker on EC2 with the following contents:</p>
<ul>
<li>Packaging the Spring Boot application with Docker container</li>
<li>Creating and deploying a new container on EC2.</li>
</ul>
<h2>2. Set Up Your Development Environment</h2>
<ul>
<li>
<p><a href="https://aws.amazon.com/" target="_blank" rel="noopener noreferrer">AWS Account</a></p>
</li>
<li>
<p><a href="https://www.docker.com/" target="_blank" rel="noopener noreferrer">Docker</a></p>
</li>
<li>
<p><a href="https://hub.docker.com/" target="_blank" rel="noopener noreferrer">Docker HUB Account</a></p>
</li>
<li>
<p><a href="https://www.docker.com/products/docker-desktop/" target="_blank" rel="noopener noreferrer">Docker desktop</a> installed on your local machine</p>
</li>
</ul>
<h2>3. AWS Setup</h2>
<h3>3.1 Create VPC</h3>
<p>Access to <a href="https://us-east-1.console.aws.amazon.com/vpcconsole/home?region=us-east-1#Home:" target="_blank" rel="noopener noreferrer">VPC console</a> and select <strong><code>Create VPC</code></strong></p>
<p><strong>Configuration Setup:</strong></p>
<ul>
<li>
<p><em><strong>Resources to create</strong></em> : <span style="color:orange"><code>VPC only</code></span></p>
</li>
<li>
<p><em><strong>Name tag - optional</strong></em>: <span style="color:orange"><code>vpc-app-southeast-1-dev-web-app-stack</code></span></p>
</li>
<li>
<p><em><strong>IPv4 CIDR block</strong></em>: <span style="color:orange"><code>IPv4 CIDR manual input</code></span></p>
</li>
<li>
<p><em><strong>IPv4 CIDR</strong></em>: <span style="color:orange"><code>10.30.0.0/16</code></span></p>
</li>
<li>
<p><em><strong>IPv6 CIDR block</strong></em>: <span style="color:orange"><code>No IPv6 CIDR block</code></span></p>
</li>
<li>
<p><em><strong>Tenancy</strong></em>: <span style="color:orange"><code>Default</code></span></p>
</li>
</ul>
<figure><img src="/assets/images/backend/java/deploy-spring-boot-with-docker-ec2/create_vpc.webp" alt="Create VPC Snapshot" tabindex="0" loading="lazy"><figcaption>Create VPC Snapshot</figcaption></figure>
<p>The <code>VPC</code> was successfully created and has the <code>VPC ID</code>: <span style="color:orange"><code>vpc-0ce2993ccf77969a5</code></span></p>
<h3>3.2 Create a Subnet within a VPC</h3>
<p>Access to <a href="https://us-east-1.console.aws.amazon.com/vpcconsole/home?region=us-east-1#Home:" target="_blank" rel="noopener noreferrer">VPC console</a> and select tab <strong>Subnets</strong> -&gt; <strong>Create Subnet</strong></p>
<figure><img src="/assets/images/backend/java/deploy-spring-boot-with-docker-ec2/subnets_default.webp" alt="Subnets Default Snapshot" tabindex="0" loading="lazy"><figcaption>Subnets Default Snapshot</figcaption></figure>
<p>The <code>subnets</code> you are seeing are the default of <code>AWS</code>. In <code>AWS</code>, a <code>default subnet</code> is automatically created in each <code>Availability Zone (AZ)</code> within a <code>Virtual Private Cloud (VPC)</code> when the <code>VPC</code> is created. This default subnet has a route table that routes traffic to the default <code>Internet Gateway (IGW)</code>, allowing the virtual machines in the subnet to communicate with the Internet.</p>
<p>The main purpose of a default subnet is to provide a convenient way to deploy virtual machines in an <code>AWS</code> region without having to create a subnet each time you want to deploy.</p>
<p><strong>Configuration Setup:</strong></p>
<p>Here we will create <code>1 public subnets</code> (Note: In the <code>VPC ID</code> section, select the <code>VPC</code> we just created above).</p>
<ul>
<li>
<p><em><strong>VPC ID</strong></em>: <span style="color:orange"><code>vpc-0ce2993ccf77969a5(vpc-app-southeast-1-dev-web-app-stack)</code></span></p>
</li>
<li>
<p><em><strong>Name</strong></em>: <span style="color:orange"><code>app-southeast-1a-public-dev-web-app-stack</code></span></p>
</li>
<li>
<p><em><strong>Availability Zone</strong></em>: <span style="color:orange"><code>ap-southeast-1a</code></span></p>
</li>
<li>
<p><em><strong>IPv4 VPC CIDR block</strong></em>: <span style="color:orange"><code>10.30.0.0/16</code></span></p>
</li>
<li>
<p><em><strong>IPv4 subnet CIDR block</strong></em>: <span style="color:orange"><code>10.30.1.0/24</code></span></p>
</li>
</ul>
<figure><img src="/assets/images/backend/java/deploy-spring-boot-with-docker-ec2/create_subnet_public.webp" alt="Create Subnet Snapshot" tabindex="0" loading="lazy"><figcaption>Create Subnet Snapshot</figcaption></figure>
<p>After creating, we can see that</p>
<p><code>1 public subnet</code> have been successfully created.</p>
<figure><img src="/assets/images/backend/java/deploy-spring-boot-with-docker-ec2/view_subnet_public.webp" alt="Subnet Snapshot" tabindex="0" loading="lazy"><figcaption>Subnet Snapshot</figcaption></figure>
<h3>3.3 Create Internet Gateways within a VPC</h3>
<p>Access <a href="https://us-east-1.console.aws.amazon.com/vpcconsole/home?region=us-east-1#Home:" target="_blank" rel="noopener noreferrer">VPC console</a> and select tab <strong>Internet Gateways</strong> -&gt; <strong>Create internet gateway</strong></p>
<figure><img src="/assets/images/backend/java/deploy-spring-boot-with-docker-ec2/create_internet_gateways.webp" alt="Internet Gateway Snapshot" tabindex="0" loading="lazy"><figcaption>Internet Gateway Snapshot</figcaption></figure>
<p><strong>Configuration Setup:</strong></p>
<ul>
<li><strong>Name tag</strong>: <span style="color:orange"><code>web-app-stack-gw</code></span></li>
</ul>
<figure><img src="/assets/images/backend/java/deploy-spring-boot-with-docker-ec2/create_internet_gateways_v2.webp" alt="Create Internet Gateway Snapshot" tabindex="0" loading="lazy"><figcaption>Create Internet Gateway Snapshot</figcaption></figure>
<p>The <code>IGW</code> was successfully created and has the <code>IGW ID</code>: <span style="color:orange"><code>igw-0f97e3e6b347f9e1f</code></span></p>
<figure><img src="/assets/images/backend/java/deploy-spring-boot-with-docker-ec2/view_internet_gateway.webp" alt="View Internet Gateway Snapshot" tabindex="0" loading="lazy"><figcaption>View Internet Gateway Snapshot</figcaption></figure>
<p>Here we can see that the <code>State</code> of the <code>IGW</code> is <code>Detached</code> (the <code>IGW</code> is not attached to any <code>VPC</code> and cannot provide Internet connectivity to any resources in the <code>VPC</code>). Therefore, we will <code>Attach</code> this <code>IGW</code> to the <code>VPC</code> (<span style="color:orange"><code>vpc-app-southeast-1-dev-web-app-stack</code></span>) that was created earlier.</p>
<p>Select <span style="color:orange"><code>IGW(web-app-stack-gw)</code></span> created -&gt; <strong>Action</strong> -&gt; <strong>Attach to VPC</strong></p>
<figure><img src="/assets/images/backend/java/deploy-spring-boot-with-docker-ec2/attach_gw_vpc.webp" alt="Attach Internet Gateway Snapshot" tabindex="0" loading="lazy"><figcaption>Attach Internet Gateway Snapshot</figcaption></figure>
<p>Continue by selecting the <span style="color:orange"><code>VPC ID(vpc-0ce2993ccf77969a5)</code></span> created earlier -&gt; Choose <strong>Attach internet gateway</strong></p>
<figure><img src="/assets/images/backend/java/deploy-spring-boot-with-docker-ec2/attach_gw_vpc_v2.webp" alt="Attach Internet Gateway Snapshot" tabindex="0" loading="lazy"><figcaption>Attach Internet Gateway Snapshot</figcaption></figure>
<p>Successfully created and the <code>State</code> is now <code>Attached</code>.</p>
<figure><img src="/assets/images/backend/java/deploy-spring-boot-with-docker-ec2/attach_gw_vpc_v3.webp" alt="Attach Internet Gateway Snapshot" tabindex="0" loading="lazy"><figcaption>Attach Internet Gateway Snapshot</figcaption></figure>
<h3>3.4 Create Route Tables within a VPC</h3>
<p>Access <a href="https://us-east-1.console.aws.amazon.com/vpcconsole/home?region=us-east-1#Home:" target="_blank" rel="noopener noreferrer">VPC console</a> and select tab <strong>Route tables</strong> -&gt; <strong>Route route table</strong></p>
<figure><img src="/assets/images/backend/java/deploy-spring-boot-with-docker-ec2/create_route_table.webp" alt="Create Route Table Snapshot" tabindex="0" loading="lazy"><figcaption>Create Route Table Snapshot</figcaption></figure>
<p>The <code>Route Tables</code> you are seeing are the default of <code>AWS</code>. In <code>AWS</code>, when you create a <code>Virtual Private Cloud (VPC)</code> in <code>Amazon Web Services (AWS)</code>, AWS will automatically create a <code>default Route Table</code> for that <code>VPC</code>.</p>
<p><strong>Configuration Setup:</strong></p>
<ul>
<li>
<p><em><strong>Name optional</strong></em>: <span style="color:orange"><code>web-app-stack-route-table-public</code></span></p>
</li>
<li>
<p><em><strong>VPC</strong></em>: <span style="color:orange"><code>vpc-0ce2993ccf77969a5(vpc-app-southeast-1-dev-web-app-stack)</code></span></p>
</li>
</ul>
<figure><img src="/assets/images/backend/java/deploy-spring-boot-with-docker-ec2/create_route_table_v2.webp" alt="Create Route Table Snapshot" tabindex="0" loading="lazy"><figcaption>Create Route Table Snapshot</figcaption></figure>
<p>Select <strong>Create route table</strong></p>
<p><strong>Route Table</strong>  was successfully created and has the <strong>Route Table ID</strong>: <span style="color:orange"><code>rtb-0ef6d58f29c45b44a</code></span></p>
<figure><img src="/assets/images/backend/java/deploy-spring-boot-with-docker-ec2/create_route_table_v3.webp" alt="Create Route Table Snapshot" tabindex="0" loading="lazy"><figcaption>Create Route Table Snapshot</figcaption></figure>
<p>Check the <code>Subnet associations</code> tab and see that it is not currently assigned to any <code>Subnet</code>. Next, I will assign the <code>Route Table</code>: <code>web-app-stack-route-table-public</code> to the <code>Public Subnets</code>. Assigning the <code>Route Table</code> to <code>Subnets</code> has the following purposes for routing packets from resources within the <code>Subnets</code>:</p>
<ol>
<li>
<p><strong>Internet Access</strong>: <code>Public subnets</code> typically contain resources (e.g., web servers, web applications) that you want to be accessible from the Internet.</p>
</li>
<li>
<p><strong>Load Balancer</strong>: If you are using an <code>Elastic Load Balancer (ELB)</code> to distribute traffic to servers within the public subnets, you need to assign a <code>Route Table</code> containing routes to the <code>ELB</code>. This allows requests from the Internet to be routed to the <code>ELB</code> and then to the servers.</p>
</li>
<li>
<p><strong>Connecting to AWS Services</strong>: Sometimes, you may want resources in the public subnets to access <code>AWS</code> services such as <code>S3</code> or <code>DynamoDB</code> without going through the Internet.</p>
</li>
<li>
<p><strong>Security and Management</strong>: By routing requests from the Internet into public subnets through a <code>Route Table</code>, you can control and manage access to the resources in the <code>subnets</code>. This can be done using <code>Security Groups</code> or <code>Network Access Control Lists (NACLs)</code>.</p>
</li>
</ol>
<figure><img src="/assets/images/backend/java/deploy-spring-boot-with-docker-ec2/associations_route_tables_to_subnet.webp" alt="Associations Route Table Snapshot" tabindex="0" loading="lazy"><figcaption>Associations Route Table Snapshot</figcaption></figure>
<p>To assign the <code>Route Table</code>: <span style="color:orange"><code>web-app-stack-route-table-public</code></span> to the <code>Public Subnets</code>:</p>
<ol>
<li>
<p>Select the <code>Subnet associations</code> tab.</p>
</li>
<li>
<p>Click on <code>Edit subnet associations</code>.</p>
</li>
<li>
<p>Check the <code>Public subnet</code> options. Specifically, select the <code>Public subnets</code>: <span style="color:orange"><code>app-southeast-1a-public-dev-web-app-stack</code></span></p>
</li>
<li>
<p>Click on <code>Save associations</code>.</p>
</li>
</ol>
<figure><img src="/assets/images/backend/java/deploy-spring-boot-with-docker-ec2/associations_route_tables_to_subnet_v2.webp" alt="Associations Route Table Snapshot" tabindex="0" loading="lazy"><figcaption>Associations Route Table Snapshot</figcaption></figure>
<p>When successfully assigned, the screen will display the updated <code>Subnet associations tab</code>.</p>
<figure><img src="/assets/images/backend/java/deploy-spring-boot-with-docker-ec2/associations_route_tables_to_subnet_v3.webp" alt="Associations Route Table Snapshot" tabindex="0" loading="lazy"><figcaption>Associations Route Table Snapshot</figcaption></figure>
<p>The next step is to assign the <code>IGW ID</code>: <span style="color:orange"><code>igw-0f97e3e6b347f9e1f</code></span> to the <code>Route Table</code>: <span style="color:orange"><code>web-app-stack-route-table-public</code></span> to enable access <code>Internet</code>.</p>
<figure><img src="/assets/images/backend/java/deploy-spring-boot-with-docker-ec2/associations_route_tables_to_subnet_v4.webp" alt="Associations Route Table Snapshot" tabindex="0" loading="lazy"><figcaption>Associations Route Table Snapshot</figcaption></figure>
<p>When you enter the screen, you'll see a default <code>Destination</code>, which is a special route used to route packets to resources within the same <code>VPC</code>. This route targets the <code>internal IP</code> addresses of the resources within the <code>VPC</code> and is used to enable communication between resources within the <code>VPC</code> without going through the <code>Internet</code>.</p>
<p>Next, select <code>Add Route</code>.</p>
<p><strong>Configuration Setup:</strong></p>
<ul>
<li>
<p><em><strong>Destination:</strong></em> <span style="color:orange"><code>0.0.0.0/0</code></span>.</p>
</li>
<li>
<p><em><strong>Target:</strong></em> <span style="color:orange"><code>Internet Gateway(igw-0f97e3e6b347f9e1f)</code></span>.</p>
</li>
</ul>
<p>Next, select <strong>Save changes</strong>. If you want to preview the changes, you can choose <strong>Review</strong>.</p>
<figure><img src="/assets/images/backend/java/deploy-spring-boot-with-docker-ec2/associations_igw_to_rtb.webp" alt="Associations Route Table Snapshot" tabindex="0" loading="lazy"><figcaption>Associations Route Table Snapshot</figcaption></figure>
<p>When completed, it will display Status: <code>Status: Active</code>.</p>
<figure><img src="/assets/images/backend/java/deploy-spring-boot-with-docker-ec2/associations_igw_to_rtb_v2.webp" alt="Associations Route Table Snapshot" tabindex="0" loading="lazy"><figcaption>Associations Route Table Snapshot</figcaption></figure>
<h3>3.5 Create Security Group</h3>
<p>Access the <a href="https://us-east-1.console.aws.amazon.com/vpcconsole/home?region=us-east-1#Home:" target="_blank" rel="noopener noreferrer">VPC console</a> and select the <strong>Security groups</strong> -&gt; <strong>Create security group</strong>.</p>
<p>The <strong>Security Groups</strong> you are seeing are the default of <strong>AWS</strong>: a special security group automatically created for each new <strong>VPC (Virtual Private Cloud)</strong>. This security group can be customized to adjust security rules for the resources within the <strong>VPC</strong>.</p>
<figure><img src="/assets/images/backend/java/deploy-spring-boot-with-docker-ec2/create_sg.webp" alt="Create SG Snapshot" tabindex="0" loading="lazy"><figcaption>Create SG Snapshot</figcaption></figure>
<p><strong>Configuration Setup:</strong></p>
<ul>
<li>
<p><em><strong>Security group name</strong></em>: <span style="color:orange"><code>app-web-stack-sg</code></span></p>
</li>
<li>
<p><em><strong>Description</strong></em>: <span style="color:orange"><code>Allows SSH access to developers</code></span></p>
</li>
<li>
<p><em><strong>VPC</strong></em>: <span style="color:orange"><code>vpc-0ce2993ccf77969a5(vpc-app-southeast-1-dev-web-app-stack)</code></span></p>
</li>
<li>
<p><em><strong>Inbound rules</strong></em>: <span style="color:orange"><code>IPv4/All traffic/All/0.0.0.0/0</code></span></p>
</li>
<li>
<p><em><strong>Outbound rules</strong></em>: <span style="color:orange"><code>IPv4/All traffic/All/0.0.0.0/0</code></span></p>
</li>
</ul>
<p>Select <strong>Create security group</strong>.</p>
<figure><img src="/assets/images/backend/java/deploy-spring-boot-with-docker-ec2/create_sg_v2.webp" alt="Create SG Snapshot" tabindex="0" loading="lazy"><figcaption>Create SG Snapshot</figcaption></figure>
<figure><img src="/assets/images/backend/java/deploy-spring-boot-with-docker-ec2/create_sg_v3.webp" alt="Create SG Snapshot" tabindex="0" loading="lazy"><figcaption>Create SG Snapshot</figcaption></figure>
<p>The <code>Security group</code> was successfully created and has the <code>Security group ID</code>: <span style="color:orange"><code>sg-04837c0728cd79e89</code></span>.</p>
<figure><img src="/assets/images/backend/java/deploy-spring-boot-with-docker-ec2/create_sg_v4.webp" alt="Create SG Snapshot" tabindex="0" loading="lazy"><figcaption>Create SG Snapshot</figcaption></figure>
<p>In this section, we have successfully created a <code>virtual network environment (VPC)</code> on AWS, including <code>VPC</code>, <code>Subnets</code>, <code>Internet Gateway</code>, <code>Route Tables</code>, and <code>Security Groups</code>. These are the basic steps to begin deploying an application on <code>AWS</code>. In the next lesson, we will continue to deploy <code>Instances (EC2)</code> to run the application.</p>
<h3>3.6 Create EC2 Instances</h3>
<p>Access the <a href="https://ap-southeast-1.console.aws.amazon.com/ec2/home?region=ap-southeast-1#Home:" target="_blank" rel="noopener noreferrer">Amazone EC2</a>  and select <strong>Launch instance</strong></p>
<figure><img src="/assets/images/backend/java/deploy-spring-boot-with-docker-ec2/create_ec2.webp" alt="Create Ec2 Snapshot" tabindex="0" loading="lazy"><figcaption>Create Ec2 Snapshot</figcaption></figure>
<p><strong>Configuration Setup:</strong></p>
<ul>
<li>
<p><em><strong>Name</strong></em> : <span style="color:orange"><code>app-web-backend</code></span></p>
</li>
<li>
<p><em><strong>Quick Start</strong></em>: <span style="color:orange"><code>Ubuntu</code></span></p>
</li>
<li>
<p><em><strong>Amazon Machine Image (AMI)</strong></em>: <span style="color:orange"><code>Ubuntu Server 22.04 LTS</code></span></p>
</li>
<li>
<p><em><strong>Instance type</strong></em>: <span style="color:orange"><code>t2.micro</code></span></p>
</li>
<li>
<p><em><strong>Key pair name - required</strong></em>: <span style="color:orange"><code>app-web-public-keypair</code></span></p>
</li>
<li>
<p><em><strong>VPC - required</strong></em>: <span style="color:orange"><code>vpc-0ce2993ccf77969a5(vpc-app-southeast-1-dev-web-app-stack)</code></span></p>
</li>
<li>
<p><em><strong>Subnet</strong></em>: <span style="color:orange"><code>app-southeast-1a-public-dev-web-app-stack</code></span></p>
</li>
<li>
<p><em><strong>Auto-assign public IP</strong></em>: <span style="color:orange"><code>Enable</code></span></p>
</li>
<li>
<p><em><strong>Firewall (security groups)</strong></em>: <span style="color:orange"><code>Select existing security group</code></span></p>
</li>
<li>
<p><em><strong>Common security groups</strong></em>: <span style="color:orange"><code>app-web-stack-sg(sg-04837c0728cd79e89)</code></span></p>
</li>
</ul>
<figure><img src="/assets/images/backend/java/deploy-spring-boot-with-docker-ec2/create_ec2_v2.webp" alt="Create Ec2 Snapshot" tabindex="0" loading="lazy"><figcaption>Create Ec2 Snapshot</figcaption></figure>
<figure><img src="/assets/images/backend/java/deploy-spring-boot-with-docker-ec2/create_ec2_v3.webp" alt="Create Ec2 Snapshot" tabindex="0" loading="lazy"><figcaption>Create Ec2 Snapshot</figcaption></figure>
<figure><img src="/assets/images/backend/java/deploy-spring-boot-with-docker-ec2/create_ec2_v4.webp" alt="Create Ec2 Snapshot" tabindex="0" loading="lazy"><figcaption>Create Ec2 Snapshot</figcaption></figure>
<p>After creating, wait for a while until the Instance state: <code>Running</code>. Note the <code>Public IPv4 address</code> (this will be the IP address you will use to SSH into the instance).</p>
<figure><img src="/assets/images/backend/java/deploy-spring-boot-with-docker-ec2/create_ec2_v5.webp" alt="Create Ec2 Snapshot" tabindex="0" loading="lazy"><figcaption>Create Ec2 Snapshot</figcaption></figure>
<h2>4. Dockerize Spring Boot Application</h2>
<p>First, we need to dockerize the application we’ve built, hence we need to do some modifications.</p>
<p>Open src/main/resources/application.yml and add the following modification to the server section as shown below:</p>
<div class="language-yml line-numbers-mode" data-highlighter="shiki" data-ext="yml" data-title="yml" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">server</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">  port</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">: </span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">${SERVER_PORT:8018}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">spring</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">  h2</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">    console</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">      enabled</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66">true</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">  datasource</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">    url</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">: </span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">${H2_URL:jdbc:h2:mem:premier-league}</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">    driverClassName</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">: </span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">org.h2.Driver</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">  jpa</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">    database-platform</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">: </span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">org.hibernate.dialect.H2Dialect</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">    show-sql</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66">true</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">    hibernate</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">      ddl-auto</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">: </span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">create-drop</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>We’ll be passing the <code>PORT</code> and <code>url</code> via environment variables on the server, especially the <code>port</code>. If we manually enter the port for our application, there is every tendency that there going to be a port conflict.
If the <code>SERVER_PORT</code> environment variable is not set, the default value <code>8018</code> will be used. By using environment variables in this way, you can maintain a single configuration file that works across different environments (development, staging, production) without needing to hard-code values.</p>
<h3>4.1 Define Dockerfile</h3>
<p>Next, create a <code>Dockerfile</code> and add the following:</p>
<div class="language-dockerfile line-numbers-mode" data-highlighter="shiki" data-ext="dockerfile" data-title="dockerfile" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#7F848E;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic"># Define build arguments</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#61AFEF">ARG</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> MVN_VERSION=3.9.5</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#61AFEF">ARG</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> JDK_VERSION=21</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#7F848E;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic"># Build stage</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#61AFEF">FROM</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> jelastic/maven:${MVN_VERSION}-openjdk-${JDK_VERSION} </span><span style="--shiki-light:#D73A49;--shiki-dark:#61AFEF">AS</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> build</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#61AFEF">LABEL</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> maintainer=</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">"taleedevops.today"</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#61AFEF">WORKDIR</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> /app</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#7F848E;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic"># Copy the application code to the container</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#61AFEF">COPY</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> . /app</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#7F848E;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic"># Build the application</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#61AFEF">RUN</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> mvn clean install -Dmaven.test.skip=true</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#7F848E;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic"># Package stage</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#61AFEF">FROM</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> openjdk:21-jdk-slim</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#61AFEF">COPY</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> --from=build /app/target/*.jar /app/app.jar</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#61AFEF">EXPOSE</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> 8018</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#61AFEF">ENTRYPOINT</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> [</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">"java"</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">"-jar"</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">"/app/app.jar"</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">]</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><ul>
<li>
<p><code>ARG MVN_VERSION=3.9.5</code>: Defines a build argument for the Maven version, which can be overridden at build time.</p>
</li>
<li>
<p><code>ARG JDK_VERSION=21</code>: Defines a build argument for the JDK version, which can also be overridden at build time.</p>
</li>
<li>
<p><code>FROM jelastic/maven:${MVN_VERSION}-openjdk-${JDK_VERSION} AS build</code>: Starts a new build stage using a Maven image that includes the specified JDK version. This image will be used to build the application.</p>
</li>
<li>
<p><code>LABEL maintainer="taleedevops.today"</code>: Adds a label to the image with the maintainer's information.</p>
</li>
<li>
<p><code>WORKDIR /app</code>: Sets the working directory to <code>/app</code> in the container.</p>
</li>
<li>
<p><code>COPY . /app</code>: Copies the entire content of the current directory (where the Dockerfile is located) into the <code>/app</code> directory in the container.</p>
</li>
<li>
<p><code>RUN mvn clean install -Dmaven.test.skip=true</code>: Runs the Maven build command inside the container to clean and install the project dependencies and compile the project, skipping tests.</p>
</li>
<li>
<p><code>FROM openjdk:21-jdk-slim</code>: Starts a new stage for the final image using a slim OpenJDK 21 base image.</p>
</li>
<li>
<p><code>COPY --from=build /app/target/*.jar /app/app.jar</code>: Copies the JAR file built in the previous stage from the <code>/app/target</code> directory to the <code>/app</code> directory in the new image.\</p>
</li>
<li>
<p><code>EXPOSE 8018</code>: Informs Docker that the container will listen on port <code>8018</code> at runtime.</p>
</li>
<li>
<p><code>ENTRYPOINT ["java", "-jar", "/app/app.jar"]</code>: Specifies the command to run when the container starts, which is to execute the JAR file using Java.</p>
</li>
</ul>
<p><strong>Summary:</strong></p>
<ol>
<li>
<p>Build Stage:</p>
<ul>
<li>
<p>Uses a Maven image with the specified JDK to build the application.</p>
</li>
<li>
<p>Copies the source code into the container.</p>
</li>
<li>
<p>Runs Maven to build the application, skipping tests.</p>
</li>
</ul>
</li>
<li>
<p>Package Stage</p>
<ul>
<li>
<p>Uses a slim JDK image for the runtime environment.</p>
</li>
<li>
<p>Copies the built JAR file from the build stage.</p>
</li>
<li>
<p>Exposes port <code>8018</code>.</p>
</li>
<li>
<p>Defines the entry point to run the application.</p>
</li>
</ul>
</li>
</ol>
<h3>4.2 Generate Docker Image</h3>
<p>You can create a docker image with the following command:</p>
<div class="language-bash line-numbers-mode" data-highlighter="shiki" data-ext="bash" data-title="bash" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> build</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66"> -t</span><span style="--shiki-light:#D73A49;--shiki-dark:#ABB2BF"> &lt;</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">IMAGE_NAM</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">E</span><span style="--shiki-light:#D73A49;--shiki-dark:#ABB2BF">&gt;</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">:</span><span style="--shiki-light:#D73A49;--shiki-dark:#ABB2BF">&lt;</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">IMAGE_TA</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">G</span><span style="--shiki-light:#D73A49;--shiki-dark:#ABB2BF">&gt;</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66"> -f</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> Dockerfile</span><span style="--shiki-light:#D73A49;--shiki-dark:#ABB2BF"> &lt;</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">PATH_TO_Dockerfil</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">e</span><span style="--shiki-light:#D73A49;--shiki-dark:#ABB2BF">&gt;</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>Applies to projects:</p>
<div class="language-bash line-numbers-mode" data-highlighter="shiki" data-ext="bash" data-title="bash" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#7F848E;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic">#Build docker images</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> build</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66"> -t</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> tunganhle/premier-league:latest</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> .</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#7F848E;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic">#Process</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#98C379">=</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt; [internal] load build definition from Dockerfile                                                               0.1s</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt; =</span><span style="--shiki-light:#D73A49;--shiki-dark:#ABB2BF">&gt;</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> transferring</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> dockerfile:</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> 530B</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">                                                                               0.0s</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt; [internal] load .dockerignore                                                                                  0.1s</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt; =</span><span style="--shiki-light:#D73A49;--shiki-dark:#ABB2BF">&gt;</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> transferring</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> context:</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> 2B</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">                                                                                    0.0s</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt; [internal] load metadata </span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">for</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> docker.io/library/openjdk:21-jdk-slim                                             3.8s</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt; [internal] load metadata </span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">for</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> docker.io/jelastic/maven:3.9.5-openjdk-21                                         3.6s</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt; [auth] library/openjdk:pull token </span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">for</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> registry-1.docker.io                                                     0.0s</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt; [auth] jelastic/maven:pull token </span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">for</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> registry-1.docker.io                                                      0.0s</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt; [build </span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">1/4]</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> FROM</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> docker.io/jelastic/maven:3.9.5-openjdk-21@sha256:c43af75dc23700d0687ad4c8773f2ab441af5fb8792</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">  0.0s</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt; </span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">CACHED</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> [stage-1 </span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">1/2]</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> FROM</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> docker.io/library/openjdk:21-jdk-slim@sha256:7072053847a8a05d7f3a14ebc778a90b38c50c</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">  0.0s</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt; [internal] load build context                                                                                  0.1s</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt; =</span><span style="--shiki-light:#D73A49;--shiki-dark:#ABB2BF">&gt;</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> transferring</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> context:</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> 9.46kB</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">                                                                                0.0s</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt; </span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">CACHED</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> [build </span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">2/4]</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> WORKDIR</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> /app</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">                                                                                0.0s</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt; [build </span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">3/4]</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> COPY</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> .</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> /app</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">                                                                                        0.1s</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt; [build </span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">4/4]</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> RUN</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> mvn</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> clean</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> install</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66"> -Dmaven.test.skip=true</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">                                                     223.7s</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt; [stage-1 </span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">2/2]</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> COPY</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66"> --from=build</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> /app/target/</span><span style="--shiki-light:#005CC5;--shiki-dark:#E5C07B">*</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">.jar</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> /app/app.jar</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">                                                 0.2s</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt; </span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">exporting</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> to</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> image</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">                                                                                             0.3s</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt; =</span><span style="--shiki-light:#D73A49;--shiki-dark:#ABB2BF">&gt;</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> exporting</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> layers</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">                                                                                            0.3s</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt; =</span><span style="--shiki-light:#D73A49;--shiki-dark:#ABB2BF">&gt;</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> writing</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> image</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> sha256:43644c5f7e399cf6fe9a946dc77f936c6eb525db19c52f98f6df4ae98e5c7404</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">                       0.0s</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt; =</span><span style="--shiki-light:#D73A49;--shiki-dark:#ABB2BF">&gt;</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> naming</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> to</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> docker.io/tunganhle/premier-league:latest</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#7F848E;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic"> #Done</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Check the docker image with the command:</p>
<div class="language-dockerfile line-numbers-mode" data-highlighter="shiki" data-ext="dockerfile" data-title="dockerfile" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">docker images</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">REPOSITORY                                  TAG       IMAGE ID       CREATED         SIZE</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">tunganhle/premier-league                    latest    43644c5f7e39   2 minutes ago   487MB</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3>4.3 Push Docker Image to Docker HUB</h3>
<p>For this step make sure you have a docker hub account.</p>
<p>Push your the image to your account.</p>
<div class="language-bash line-numbers-mode" data-highlighter="shiki" data-ext="bash" data-title="bash" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> push</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> tunganhle/premier-league:latest</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><div class="hint-container important">
<p class="hint-container-title">Important</p>
<p>Before pushing your image to Docker Hub, ensure that it is tagged correctly. The format for tagging an image is username/repository:tag. For example:</p>
<div class="language-bash line-numbers-mode" data-highlighter="shiki" data-ext="bash" data-title="bash" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> tag</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> your-image:tag</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> tunganhle/premier-league:latest</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>Replace <code>your-image:tag</code> with the actual name and tag of your image. The latest tag is commonly used to indicate the most recent version of the image.
Here's an example of the complete workflow from tagging to pushing:</p>
<div class="language-bash line-numbers-mode" data-highlighter="shiki" data-ext="bash" data-title="bash" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#7F848E;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic"># Tag the image</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> tag</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> premier-league:1.0</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> tunganhle/premier-league:latest</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#7F848E;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic"># Log in to Docker Hub</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> login</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#7F848E;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic"># Push the image</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> push</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> tunganhle/premier-league:latest</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><ul>
<li><strong>Automated Builds</strong>: Docker Hub can automatically build your images from a linked GitHub or Bitbucket repository. This can simplify your workflow by automatically pushing updates whenever you push changes to your source code repository.</li>
<li><strong>Repository Management</strong>: You can manage your repositories, set descriptions, and configure build settings directly from the Docker Hub web interface.</li>
<li><strong>Private Repositories</strong>: If you need to keep your images private, Docker Hub offers private repositories as part of its paid plans.</li>
</ul>
</div>
<p>Once completed successfully, You will be able to see your image listed under repositories on your docker hub account.</p>
<figure><img src="/assets/images/backend/java/deploy-spring-boot-with-docker-ec2/docker_hub.webp" alt="Docker-Hub Snapshot" tabindex="0" loading="lazy"><figcaption>Docker-Hub Snapshot</figcaption></figure>
<h2>5. Launch Application in AWS EC2</h2>
<p>We are done with generating our artifacts in previous and step. Now its time to launch the docker image in the EC2 instance that we created earlier.</p>
<ul>
<li>Go to your terminal and run the following command to SSH into the instance.</li>
</ul>
<div class="language-bash line-numbers-mode" data-highlighter="shiki" data-ext="bash" data-title="bash" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#7F848E;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic"># Navigate to the key pair and modify the permissions if not done already.</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#7F848E;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic"># If the permissions is set to 644 then you will be denied to ssh into the instance.</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">chmod</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66"> 600</span><span style="--shiki-light:#D73A49;--shiki-dark:#ABB2BF"> &lt;</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">key-pair.pe</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">m</span><span style="--shiki-light:#D73A49;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#7F848E;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic"># SSH into the instance. Username changes on the basis of the image you are using. </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">ssh</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66"> -i</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> /path/keypair.pem</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> ec2-user@</span><span style="--shiki-light:#D73A49;--shiki-dark:#ABB2BF">&lt;</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">Instance-Public-I</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">P</span><span style="--shiki-light:#D73A49;--shiki-dark:#ABB2BF">&gt;</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><figure><img src="/assets/images/backend/java/deploy-spring-boot-with-docker-ec2/ssh_to_ec2.webp" alt="SSH into the instance" tabindex="0" loading="lazy"><figcaption>SSH into the instance</figcaption></figure>
<ul>
<li>RUN the following commands to update the instance.</li>
</ul>
<div class="language-bash line-numbers-mode" data-highlighter="shiki" data-ext="bash" data-title="bash" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#7F848E;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic"># Install the updates to the instance. Depending on the image being used the update instruction changes. Refer to the documentation of your image provider to get the correct information.</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">sudo</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> apt</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> update</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66"> -y</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#7F848E;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic"># This command installs Docker, an open-source platform for automating the deployment, scaling, and management of containerized applications.</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">sudo</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> apt</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> install</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> docker.io</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66"> -y</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#7F848E;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic"># Adding the user to the 'docker' group allows them to run Docker commands without needing to use 'sudo'.</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">sudo</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> usermod</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66"> -aG</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> docker</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75"> $USER</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">newgrp</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> docker</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#7F848E;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic"># Start Docker Service</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">sudo</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> service</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> docker</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> start</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><ul>
<li>Check Docker Version</li>
</ul>
<div class="language-bash line-numbers-mode" data-highlighter="shiki" data-ext="bash" data-title="bash" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">docker</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66"> --version</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><ul>
<li>Run docker container to test the application</li>
</ul>
<div class="language-bash line-numbers-mode" data-highlighter="shiki" data-ext="bash" data-title="bash" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#7F848E;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic"># Start the application on Port 80</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#7F848E;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic"># In you modified application.yml of the downloaded spring boot application and changed the port then replace the source port with the value that is specified in your application.yml file.</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> run</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66"> -d</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66"> -p</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> 8018:8018</span><span style="--shiki-light:#D73A49;--shiki-dark:#ABB2BF"> &lt;</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">your-docker-hub-user-nam</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">e</span><span style="--shiki-light:#D73A49;--shiki-dark:#ABB2BF">&gt;</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">/premier-league:latest</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> ps</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#7F848E;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic">#Copy the docker container Id</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> logs</span><span style="--shiki-light:#D73A49;--shiki-dark:#ABB2BF"> &lt;</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">containerI</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">d</span><span style="--shiki-light:#D73A49;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#7F848E;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic"># You will be able to see that your spring boot application is up and running on port 8018</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><figure><img src="/assets/images/backend/java/deploy-spring-boot-with-docker-ec2/docker-run-images.webp" alt="Docker run images" tabindex="0" loading="lazy"><figcaption>Docker run images</figcaption></figure>
<ul>
<li>
<p>Open up a REST client. I will be using POSTMAN but you can also use terminal to CURL the POST request to the server.</p>
</li>
<li>
<p>Make sure you use http instead of https.</p>
</li>
</ul>
<div class="language-bash line-numbers-mode" data-highlighter="shiki" data-ext="bash" data-title="bash" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">POST</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> http://</span><span style="--shiki-light:#D73A49;--shiki-dark:#ABB2BF">&lt;</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">your-instance-i</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">p</span><span style="--shiki-light:#D73A49;--shiki-dark:#ABB2BF">&gt;</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">:8018/api/club/</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#7F848E;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic">#Request Body</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">{</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">"name"</span><span style="--shiki-light:#005CC5;--shiki-dark:#56B6C2">:</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> "Manchester United",</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">"captain"</span><span style="--shiki-light:#005CC5;--shiki-dark:#56B6C2">:</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> "Bruno Fernandes",</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">"manager"</span><span style="--shiki-light:#005CC5;--shiki-dark:#56B6C2">:</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> "Erik ten Hag",</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">"stadium"</span><span style="--shiki-light:#005CC5;--shiki-dark:#56B6C2">:</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> "Old Trafford"</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><figure><img src="/assets/images/backend/java/deploy-spring-boot-with-docker-ec2/create_by_posman.webp" alt="POST Request" tabindex="0" loading="lazy"><figcaption>POST Request</figcaption></figure>
<ul>
<li>Similarly you can execute the GET request to test if the student was created successfully or no.</li>
</ul>
<div class="language-bash line-numbers-mode" data-highlighter="shiki" data-ext="bash" data-title="bash" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">GET</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> http://</span><span style="--shiki-light:#D73A49;--shiki-dark:#ABB2BF">&lt;</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">your-instance-i</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">p</span><span style="--shiki-light:#D73A49;--shiki-dark:#ABB2BF">&gt;</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">:8018/api/club/</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><figure><img src="/assets/images/backend/java/deploy-spring-boot-with-docker-ec2/get_by_posman.webp" alt="POST Request" tabindex="0" loading="lazy"><figcaption>POST Request</figcaption></figure>
<p>That's it. Your application is up and running on the EC2 instance in AWS.</p>
<div class="hint-container important">
<p class="hint-container-title">Important</p>
<p>In the realistic scenario, these steps will be a part of the automated template that will run as a part of the deployment pipeline to reduce the manual overhead to do this one by one.</p>
</div>
<p>I hope you really enjoyed the article. Thanks for reading. Feel free to share. 😃</p>
]]></content:encoded>
      <enclosure url="https://blog.taleedevops.today/assets/images/backend/java/deploy-spring-boot-with-docker-ec2/title.jpg" type="image/jpeg"/>
    </item>
    <item>
      <title>Follow Google&amp;apos;s Java coding style standards, use Intellij</title>
      <link>https://blog.taleedevops.today/backend/java/follow-google&amp;apos;s-java-coding-style-standards-use-intellij.html</link>
      <guid>https://blog.taleedevops.today/backend/java/follow-google&amp;apos;s-java-coding-style-standards-use-intellij.html</guid>
      <source url="https://blog.taleedevops.today/rss.xml">Follow Google&amp;apos;s Java coding style standards, use Intellij</source>
      <description>Install and wire up Google&amp;apos;s Java style guide in IntelliJ so formatting stops being a review topic and stays consistent across the codebase.</description>
      <category>backend</category>
      <pubDate>Tue, 23 Jul 2024 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[
<p><code>Consistency Across Codebases</code>: Adhering to a well-defined style guide ensures that all code within a project (or even across projects) follows the same conventions. This consistency makes it easier for developers to read, understand, and maintain code written by different authors.</p>
<p><code>Improved Readability</code>: A standardized coding style enhances the readability of the code. When code looks the same regardless of who wrote it, developers can quickly grasp the structure and logic without being distracted by varying styles.</p>
<p><code>Ease of Collaboration</code>: When multiple developers work on the same codebase, having a common style guide minimizes conflicts and misunderstandings. It streamlines the review process and facilitates smoother collaboration.</p>
<p><code>Reduced Cognitive Load</code>: Developers spend less time thinking about how to format their code and more time focusing on solving problems. A common style guide provides clear rules, reducing the mental overhead of making formatting decisions.</p>
<p><code>Better Tooling Support</code>: Many development tools, including linters and formatters, support Google's Java coding style. Using these tools helps automate code formatting, ensuring adherence to the style guide with minimal manual effort.</p>
<h2>Why should we follow Google's Java coding style standards?</h2>
<figure><img src="/assets/images/store/backend/java/follow-googles-java-coding-style-standards-use-intellij/why-use-google-format.webp" alt="" tabindex="0" loading="lazy"><figcaption></figcaption></figure>
<p>Because I desire and aspire to work in an environment like Google, but that seems far-fetched for someone with my modest skills. So, I might as well follow the standards they set. 😀</p>
<p>Google's Java Coding Standards: <a href="https://google.github.io/styleguide/javaguide.html" target="_blank" rel="noopener noreferrer">https://google.github.io/styleguide/javaguide.html</a></p>
<h2>How to Install the Necessary Tools:</h2>
<p><code>1.</code> <strong>PLUGIN CHECKSTYLE</strong></p>
<ul>
<li>You can find the plugin in: <code>Settings</code> &gt; <code>Plugins</code> &gt; <code>Marketplace</code> –&gt; enter <code>“CheckStyle”</code></li>
</ul>
<figure><img src="/assets/images/store/backend/java/follow-googles-java-coding-style-standards-use-intellij/check-style.webp" alt="" tabindex="0" loading="lazy"><figcaption></figcaption></figure>
<ul>
<li>Then install it and restart the IDE.</li>
</ul>
<p>After setting up, you need to configure:</p>
<figure><img src="/assets/images/store/backend/java/follow-googles-java-coding-style-standards-use-intellij/setting-style.webp" alt="" tabindex="0" loading="lazy"><figcaption></figcaption></figure>
<p><code>2.</code> PLUGIN: <strong>GOOGLE JAVA FORMAT</strong></p>
<ul>
<li>You can do the same as with the <code>Checkstyle plugin</code>, but this time search for <code>“google-java-format”</code>:</li>
</ul>
<figure><img src="/assets/images/store/backend/java/follow-googles-java-coding-style-standards-use-intellij/google-java-format.webp" alt="" tabindex="0" loading="lazy"><figcaption></figcaption></figure>
<p>After setting up and restarting the IDE, you need to activate the plugin:</p>
<figure><img src="/assets/images/store/backend/java/follow-googles-java-coding-style-standards-use-intellij/google-java-format-enable.webp" alt="" tabindex="0" loading="lazy"><figcaption></figcaption></figure>
<ol start="3">
<li>Import the <code>intellij-java-google-style.xml</code> into <code>IntelliJ IDEA</code></li>
</ol>
<p>Create file <a href="https://raw.githubusercontent.com/google/styleguide/gh-pages/intellij-java-google-style.xml" target="_blank" rel="noopener noreferrer">fsales-cs-formatter.xml</a> in project</p>
<figure><img src="/assets/images/store/backend/java/follow-googles-java-coding-style-standards-use-intellij/fsales-cs.webp" alt="" tabindex="0" loading="lazy"><figcaption></figcaption></figure>
<p>After import to <code>IntelliJ</code>:</p>
<figure><img src="/assets/images/store/backend/java/follow-googles-java-coding-style-standards-use-intellij/import-xml.webp" alt="" tabindex="0" loading="lazy"><figcaption></figcaption></figure>
<h2>How to use</h2>
<p>Now, your <code>IntelliJ IDEA</code> is configured to follow Google's Java coding standards, and your code will be automatically formatted accordingly.</p>
<p>You can use the <code>"Reformat Code"</code> option or the shortcut <code>Ctrl+Alt+L</code> to format your code according to the imported <code>Google Java style</code>.</p>
<div class="hint-container warning">
<p class="hint-container-title">Warning</p>
<p>The options you provided are used to add exports for internal JDK packages, allowing unnamed modules to access these packages. This is necessary for some tools and libraries that need to interact with
the internal APIs of the JDK, especially in newer Java versions where module boundaries are enforced more strictly.
To set these options in IntelliJ IDEA, you need to add them to the VM options of your project or run configuration. Here’s how you can do it:</p>
<h1>Adding VM Options to IntelliJ IDEA</h1>
<p>Navigate to Help &gt; Edit Custom VM Options.
Once the file is opened in the editor, add the following lines to the file:</p>
<div class="language- line-numbers-mode" data-highlighter="shiki" data-ext="" data-title="" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span>--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED</span></span>
<span class="line"><span>--add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED</span></span>
<span class="line"><span>--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED</span></span>
<span class="line"><span>--add-exports=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED</span></span>
<span class="line"><span>--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED</span></span>
<span class="line"><span>--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Restart IntelliJ IDEA for the changes to take effect.</p>
</div>
]]></content:encoded>
      <enclosure url="https://blog.taleedevops.today/assets/images/store/backend/java/follow-googles-java-coding-style-standards-use-intellij/title.jpg" type="image/jpeg"/>
    </item>
    <item>
      <title>Introduction to Spring Security Architecture</title>
      <link>https://blog.taleedevops.today/backend/java/introduction-spring-security-architecture.html</link>
      <guid>https://blog.taleedevops.today/backend/java/introduction-spring-security-architecture.html</guid>
      <source url="https://blog.taleedevops.today/rss.xml">Introduction to Spring Security Architecture</source>
      <description>How Spring Security actually fits together: DispatcherServlet, the security filter chain, AuthenticationManager, providers and UserDetailsService.</description>
      <category>backend</category>
      <pubDate>Mon, 29 Jul 2024 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[
<p><code>Spring Security</code> is a powerful and highly customizable security framework that provides comprehensive security solutions for <code>Java-based</code> applications. It is a part of the larger <code>Spring</code> ecosystem and seamlessly integrates with other <code>Spring</code> modules. <code>Spring Security</code> is a framework that focuses on providing both authentication and authorization to Java applications</p>
<p><code>Spring Security</code> acts as a vigilant guardian for your web applications. It oversees who can access your site, verifies user identities, and enforces rules to safeguard your data from unauthorized access.</p>
<h2>Authentication And Authorization</h2>
<ol>
<li><strong>Authentication in web applications</strong></li>
</ol>
<p><code>Authentication</code> is the process of verifying the identity of a user accessing a system or application.</p>
<ol start="2">
<li><strong>How Spring Security handles authentication</strong></li>
</ol>
<p><code>Spring Security</code> handles authentication by employing various <code>authentication providers</code>, such as <code>in-memory authentication</code>, <code>JDBC-based authentication</code>, and <code>LDAP authentication</code>. Each provider validates user credentials and establishes the user’s identity within the application.</p>
<ol start="3">
<li><strong>Concept of authorization</strong></li>
</ol>
<p><code>Authorization</code> determines what actions a user is allowed to perform within an application. It establishes rules and permissions for accessing protected resources based on the user’s identity and assigned roles.</p>
<h2>How DispatcherServlet works with Spring Security</h2>
<figure><img src="/assets/images/store/backend/java/introduction-spring-security-architecture/security-servlet.webp" alt="" tabindex="0" loading="lazy"><figcaption></figcaption></figure>
<p>In <code>Spring MVC</code>, all incoming <code>HTTP</code> requests are channeled through a single servlet known as the <code>DispatcherServlet</code>. This servlet directs these requests to your controller classes, where you define the endpoints for your application. <code>Spring Security</code> steps in at this point by introducing filter classes before the <code>HTTP</code> requests reach the <code>DispatcherServlet</code>.</p>
<p>This means that every incoming request will pass through these filter classes one by one. This approach allows us to verify authentication and authorization states before the request reaches the <code>DispatcherServlet</code> and subsequently the controllers. In essence, this is the core function of <code>Spring Security</code>.</p>
<h2>Spring Security Architecture</h2>
<figure><img src="/assets/images/store/backend/java/introduction-spring-security-architecture/architecture.webp" alt="" tabindex="0" loading="lazy"><figcaption></figcaption></figure>
<h3>Security Filter Chain</h3>
<p>The <code>Security Filter Chain</code> is the backbone of <code>Spring Security</code>. It’s a series of filters that processes incoming <code>HTTP</code> requests and communicates with the <code>Authentication Manager</code> for the validation of requests.</p>
<p>These filters work together to ensure that your web application is secure and responsible for tasks like authentication, authorization, session management and more. These filters work together to ensure that your web application is secure and responsible for tasks like authentication, authorization, session management and more</p>
<h4>List of default Filters in Security Filter Chain</h4>
<ul>
<li>
<p><strong>ChannelProcessingFilter</strong> — ensures protocol such as HTTP or HTTPS.</p>
</li>
<li>
<p><strong>SecurityContextPersistenceFilter</strong> — ensures the user’s authentication details persist during their session.</p>
</li>
<li>
<p><strong>UsernamePasswordAuthenticationFilter</strong> — checks the provided credentials and creates an <code>Authentication Object</code> if they are valid.</p>
</li>
<li>
<p><strong>ConcurrentSessionFilter</strong> — control how many sessions a user can have and handle scenarios where a user exceeds the session limit.</p>
</li>
<li>
<p><strong>LogoutFilter</strong> — intercepts logout requests and terminates the user’s session</p>
</li>
<li>
<p><strong>RememberMeAuthenticationFilter</strong> — allow user to be remembered across sessions, even after logout.</p>
</li>
<li>
<p><strong>AnonymousAuthenticationFilter</strong> — responsible for creating an anonymous user who is not authenticated but has limited access to some parts of the application.</p>
</li>
<li>
<p><strong>SessionManagementFilter</strong> — handles invalidating sessions, session fixation protection, and other session-related tasks.</p>
</li>
<li>
<p><strong>ExceptionTranslationFilter</strong> — responsible for translating the exception into a unauthenticated response.</p>
</li>
<li>
<p><strong>FilterSecurityInterceptor</strong> — ensures the user have the necessary roles and permissions to access specific resources.</p>
</li>
</ul>
<p>You can read more about filters <a href="https://docs.spring.io/spring-security/site/docs/3.0.x/reference/basic.html" target="_blank" rel="noopener noreferrer">here</a>.</p>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" data-title="java" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">@</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B">Bean</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">public</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> SecurityFilterChain</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> securityFilterChain</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">(</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">HttpSecurity</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75"> httpSecurity) {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">    httpSecurity</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">authorizeHttpRequests</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(authorize </span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">-&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">          authorize</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">requestMatchers</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">"/signup/"</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">permitAll</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">                   .</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">requestMatchers</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">"/users"</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">authenticated</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">    ).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">httpBasic</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">Customizer</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">withDefaults</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">());</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> httpSecurity</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">build</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">();</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>This code defines a custom <code>Security Filter Chain</code> with specific security rules. It permits unrestricted access to the <code>“/signup/”</code> URL while requiring authentication for the <code>“/users”</code> URL.  Additionally, it configures <code>HTTP Basic Authentication</code> as the authentication method.</p>
<h3>Authentication Manager</h3>
<p>The <code>Authentication Manager</code> is the central component that verifies user identities. It coordinates the authentication process and delegates the actual authentication to <code>Authentication Providers</code>.</p>
<p>In more complex systems, you might have multiple <code>Authentication Managers</code>. Each manager can be associated with a specific set of <code>Authentication Providers</code>, allowing you to handle different types of authentication for different parts of your application.</p>
<p>The <code>AuthenticationManager</code> is an interface which processes the <code>Authentication</code> request. It has an <code>authenticate()</code> method which takes <code>Authentication</code> object as a parameter.</p>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" data-title="java" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">Authentication</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> authenticate</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">(</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">Authentication</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75"> authentication) throws AuthenticationException</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>The implementation class of <code>AuthenticationManager</code> is the <code>ProviderManager</code> class which provides the logic for <code>authenticate()</code> method. We can provide our own implementation class of <code>AuthenticationProvider</code> or can use the default implementation.</p>
<h3>Authentication Providers</h3>
<p>The <code>Authentication Providers</code> are the workers of the <code>Authentication Manager</code>. They are responsible for actually performing the authentication. <code>AuthenticationProvider</code> is an interface that defines the contract for authenticating users. It is responsible for taking an <code>Authentication</code> object, which represents the user’s credentials, and returning an authenticated <code>Authentication</code> object if the credentials are valid. If the credentials are invalid, the <code>AuthenticationProvider</code> should throw an <code>AuthenticationException</code>.</p>
<p>The <code>AuthenticationProvider</code> interface has two methods:</p>
<ul>
<li>
<p><strong>authenticate()</strong> : This method takes an <code>Authentication</code> object as input and returns an authenticated <code>Authentication</code> object if the credentials are valid. If the credentials are invalid, the <code>AuthenticationProvide</code>r should throw an <code>AuthenticationException</code>.</p>
</li>
<li>
<p><strong>supports()</strong> : This method takes an <code>Authentication</code> object as input and returns true if the <code>AuthenticationProvider</code> can authenticate the object. If the <code>AuthenticationProvider</code> cannot authenticate the object, it should return false .</p>
</li>
</ul>
<p><code>Spring Security</code> supports various types of <code>Authentication Providers</code></p>
<ul>
<li>
<p><strong>DaoAuthenticationProvider</strong> — uses a UserDetailsService to retrieve user details from database and compare credentials.</p>
</li>
<li>
<p><strong>LdapAuthenticationProvider</strong> — used for authenticating against <code>LDAP servers</code>.</p>
</li>
<li>
<p><strong>JwtAuthenticationProvider</strong> — used for validating <code>JWT tokens</code> of the user.</p>
</li>
<li>
<p><strong>Custom Authentication Providers</strong> — handle authentication using specific logic or external systems.</p>
</li>
</ul>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" data-title="java" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">@</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B">Bean</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">public</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> DaoAuthenticationProvider</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> daoAuthenticationProvider</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">() {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">    DaoAuthenticationProvider</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75"> daoAuthenticationProvider </span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> DaoAuthenticationProvider</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">()</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">    daoAuthenticationProvider</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">setUserDetailsService</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">userDetailsService</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">());</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">    daoAuthenticationProvider</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">setPasswordEncoder</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">passwordEncoder</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">());</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75"> daoAuthenticationProvider</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><ul>
<li>In this snippet, a custom <code>DaoAuthenticationProvider</code> is defined, configured with a <code>UserDetailsService</code> and a <code>PasswordEncoder</code>.</li>
</ul>
<h3>UserDetailsService</h3>
<p>The <code>UserDetailsService</code> is an interface which retrieves user details during the authentication process. It is often used in conjunction with <code>Authentication Providers</code> to obtain user details from the database for authentication.</p>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" data-title="java" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#E5C07B"> UserDetailsServiceImpl</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> implements</span><span style="--shiki-light:#6F42C1;--shiki-dark:#E5C07B"> UserDetailsService</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">    @</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B">Autowired</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">    public</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> UserRepository</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75"> userRepository</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">    </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">    @</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B">Override</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">    public</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> UserDetails</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> loadUserByUsername</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">String</span><span style="--shiki-light:#E36209;--shiki-dark:#E06C75;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic"> username</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">)</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> throws</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> UsernameNotFoundException</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">        Optional</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&lt;</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B">User</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt; </span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">user</span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> userRepository</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">findById</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(username);</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">user</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">isEmpty</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">()) {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">            throw</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> UsernameNotFoundException</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">"user not found with this username"</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">        }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> UserDetailsImpl</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">user</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">get</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">());</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>The <code>UserDetailsServiceImpl</code> class is implemented as a custom <code>UserDetailsService</code>, and it overrides the <code>loadUserByUsername</code> method to retrieve user details from a database via a <code>UserRepository</code>.</p>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" data-title="java" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">@</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B">Bean</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">public</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> UserDetailsService</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> userDetailsService</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">() {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">    return</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> UserDetailsServiceImpl</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">()</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>In the above code, we are defining <code>UserDetailsServiceImpl</code> as custom <code>UserDetailsService</code>.</p>
<h3>Password Encoder</h3>
<p>The <code>Password Encoder</code> is used to hash and verify passwords securely as storing and comparing passwords is crucial for user authentication.</p>
<ul>
<li>
<p><strong>BCryptPasswordEncoder</strong> — this is widely recommended choice for securely hashing passwords in <code>Spring Security</code>. It handles the generation of random salts for each password.</p>
</li>
<li>
<p><strong>NoOpPasswordEncoder</strong> — this encoder does not perform any hashing or encoding of passwords and stores passwords in plain text which makes them highly vulnerable.</p>
</li>
<li>
<p><strong>StandardPasswordEncoder</strong> — this encoder uses one-way hashing algorithm which is less secure and it is not recommended.</p>
</li>
<li>
<p><strong>MessageDigestPasswordEncoder</strong> — this encoder uses a specified message digest algorithm (e.g., SHA-256) to hash passwords. While it’s more secure than plain text, it’s not as strong as <code>BCrypt</code> and is considered less secure in modern applications.</p>
</li>
<li>
<p><strong>SCryptPasswordEncoder</strong> — <code>SCrypt</code> is another secure password hashing algorithm, similar to <code>BCrypt</code>. It’s designed to be memory-intensive, making it resistant to certain types of attacks. <code>SCryptPasswordEncoder</code> is a good choice for secure password hashing.</p>
</li>
</ul>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" data-title="java" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">@</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B">Bean</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">public</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> PasswordEncoder</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> passwordEncoder</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">() {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">    return</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> BCryptPasswordEncoder</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">()</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>In the above code, a <code>BCryptPasswordEncoder</code> is defined as the custom <code>PasswordEncoder</code> .</p>
<h3>SecurityContextHolder and Principal</h3>
<p>The <code>SecurityContextHolder</code> class manages the user’s security context throughout the request-response lifecycle. It stores information about the currently authenticated user such as roles, and other security-related data.</p>
<p>Once the user is successfully authenticated, <code>Spring Security</code> creates an <code>Authentication Object</code> within the security context managed by <code>SecurityContextHolder</code>.</p>
<p>The <code>Principal</code> represents the current user’s username, authorities, and other user-specific data.</p>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" data-title="java" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">Authentication</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75"> authentication </span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> SecurityContextHolder</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">getContext</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">getAuthentication</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">();</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">String</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75"> username </span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> authentication</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">getName</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">();</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p>The above code snippet is an example of how to retrieve the current user’s username from the <code>Principal</code>.</p>
<h3>Request &amp; Response lifecycle</h3>
<p>Now, let us combine all the components we have learned so far and understand the whole flow of the architecture.</p>
<h3>Authentication and UsernamePasswordAuthenticationToken</h3>
<ol>
<li><strong>Authentication</strong></li>
</ol>
<p>It is an interface in <code>Spring Security</code> which represents token for incoming authentication request or an authenticated <code>Principal</code> (an interface which represents an entity like an individual) <code>AuthenticationManager.authenticate()</code> method.</p>
<p>Some methods provided:</p>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" data-title="java" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">Collection</span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">&lt;</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">?</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75"> extends GrantedAuthority</span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">&gt;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> getAuthorities</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">()</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> Object</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> getCredentials</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">()</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> boolean</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> isAuthenticated</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">()</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> setAuthenticated</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">boolean</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75"> isAuthenticated) throws IllegalArgumentException</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><ol start="2">
<li><strong>UsernamePasswordAuthenticationToken</strong></li>
</ol>
<p>This class extends the <code>AbstractAuthenticationToken</code> class (base class of authentication objects) and can be used with <code>Username/Password</code> authentication requests.</p>
<p>This class has two constructors:</p>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" data-title="java" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> UsernamePasswordAuthenticationToken</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">(</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">Object</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75"> principal</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> Object</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75"> credentials) {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#E5C07B">    super</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">((Collection)</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66">null</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">)</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#E5C07B">    this</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">principal</span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75"> principal</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#E5C07B">    this</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">credentials</span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75"> credentials</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#E5C07B">    this</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">setAuthenticated</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66">false</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> UsernamePasswordAuthenticationToken</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">(</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">Object</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75"> principal</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> Object</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75"> credentials</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> Collection</span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">&lt;</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">?</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75"> extends GrantedAuthority</span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">&gt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75"> authorities) {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#E5C07B">    super</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">(authorities)</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#E5C07B">    this</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">principal</span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75"> principal</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#E5C07B">    this</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">credentials</span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75"> credentials</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#E5C07B">    super</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">setAuthenticated</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66">true</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>The first constructor can be used for incoming requests to create unauthenticated <code>Authentication</code> object.</p>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" data-title="java" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">Authentication</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75"> authentication </span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> UsernamePasswordAuthenticationToken</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">(username</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">password)</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>The second constructor can be used to create a fully authenticated <code>Authentication</code> object.</p>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" data-title="java" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">Authentication</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75"> authToken </span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> UsernamePasswordAuthenticationToken</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">(username</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75"> password</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75"> userAuthorities)</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>This fully authenticated Authentication object is then returned from <code>AuthenticationProvider/AuthenticationManager</code> and represents an authenticated user. This authenticated object is then set in the <code>SecurityContext</code>. The <code>SecurityContext</code> in <code>Spring Security</code> is a representation of the security context of the current thread of execution. It contains information about the currently authenticated user, such as their username, authorities, and session information.</p>
<figure><img src="/assets/images/store/backend/java/introduction-spring-security-architecture/architecture.webp" alt="" tabindex="0" loading="lazy"><figcaption></figcaption></figure>
<ol>
<li>
<p>The request is intercepted by the <code>Security Filter Chain</code>. The <code>Security Filter Chain</code> consists of a series of filters, each with a specific security-related task.</p>
</li>
<li>
<p>If the user is not yet authenticated (i.e., not logged in), <code>Spring Security’s</code> authentication filters will trigger the <code>Authentication Manager</code>. If the credentials match, the <code>Authentication Manager</code> generates an <code>Authentication Object</code> indicating a successful authentication.</p>
</li>
<li>
<p>The <code>Authentication Manager</code> uses the configured <code>Authentication Providers</code> to verify the user’s credentials.</p>
</li>
<li>
<p><code>Authentication Providers</code> will use the <code>PasswordEncoder</code> to store and compare passwords.</p>
</li>
<li>
<p><code>Authentication Providers</code> may use the <code>UserDetailsService</code> to fetch user details. The user’s credentials are compared to the stored or provided credentials</p>
</li>
<li>
<p><code>UserDetailsService</code> will fetch the data from the database.</p>
</li>
<li>
<p>The status of the authentication process will be sent to the user as a success or unauthorized response.</p>
</li>
<li>
<p>This <code>Authentication</code> object is stored within the security context managed by <code>SecurityContextHolder</code>. The security context now represents the authenticated user.</p>
</li>
</ol>
<h2>Conclusion</h2>
<p>This article provides a brief description of authentication flow and different components which are needed to set up authentication. Anyone who wants to use Spring Security must have a clear understanding of these concepts before moving to more customizations and implementation.</p>
<p>Thank you for reading, and happy coding! 😊</p>
]]></content:encoded>
      <enclosure url="https://blog.taleedevops.today/assets/images/store/backend/java/introduction-spring-security-architecture/title.jpg" type="image/jpeg"/>
    </item>
    <item>
      <title>Spring Boot 3 + Spring Security 6: JWT Authentication &amp; Authorization</title>
      <link>https://blog.taleedevops.today/backend/java/jwt-authentication-authorization.html</link>
      <guid>https://blog.taleedevops.today/backend/java/jwt-authentication-authorization.html</guid>
      <source url="https://blog.taleedevops.today/rss.xml">Spring Boot 3 + Spring Security 6: JWT Authentication &amp; Authorization</source>
      <description>Add JWT authentication and authorization to Spring Boot 3 with Spring Security 6 — token structure, why JWT suits microservices, and the wiring.</description>
      <category>backend</category>
      <pubDate>Sat, 03 Aug 2024 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[
<p>In our previous article, we covered the fundamentals of Spring Security implementation for our Spring Boot project. Building on that foundation, this article will shift its focus towards a more advanced topic: integrating <code>JWT (JSON Web Token)</code> with Spring Security in our Spring Boot application. This will enable us to enhance our security framework by incorporating robust authentication and authorization mechanisms using <code>JWT</code>.</p>
<h2>What is JWT?</h2>
<p>JWT, or JSON Web Tokens, are like digital passes that help keep web applications secure. When someone logs into an application, the server gives them a JWT.</p>
<p>It’s like getting a badge that proves who you are every time you come back. Each time the user wants to access a secure part of the application, they show this badge, and the server knows it’s safe to let them in.</p>
<p>Here’s why JWTs are so great:</p>
<p><code>1.</code> <strong>Easy to Manage</strong>: They are simple strings of text, making them easy to handle and send between computers and devices.</p>
<p><code>2.</code> <strong>All-in-One</strong>: Everything the server needs to verify the user is packed into the JWT. This means the server doesn’t have to keep asking a database for information, speeding things up.</p>
<p><code>3.</code> <strong>Safe</strong>: They can be encrypted and signed, making it hard for unauthorized people to mess with them.</p>
<p>A JWT token typically appears as shown on the left side in the provided image below:</p>
<figure><img src="/assets/images/store/backend/java/jwt-authentication-authorization/jwt.webp" alt="" tabindex="0" loading="lazy"><figcaption></figcaption></figure>
<p>You can see more here: <a href="https://jwt.io/" target="_blank" rel="noopener noreferrer">jwt.io</a></p>
<h2>Parts of a JWT token:</h2>
<p>A JWT consists of three main parts, each separated by a dot (.). Here's an easy breakdown:</p>
<ol>
<li>
<p><strong>Header</strong></p>
<ul>
<li>
<p><strong>Purpose</strong>: The header typically tells us the type of the token, which is JWT, and the algorithm that is used for signing the token, like HMAC SHA256 or RSA.</p>
</li>
<li>
<p><strong>Example</strong>: <code>{"alg": "HS256", "typ": "JWT"}</code></p>
</li>
<li>
<p><strong>Explanation</strong>: This is a simple <code>JSON</code> object that states the JWT is using the <code>HS256</code> algorithm for encryption. It's encoded in <code>Base64Url</code> format to make it URL-safe.</p>
</li>
</ul>
</li>
<li>
<p><strong>Payload</strong></p>
<ul>
<li>
<p><strong>Purpose</strong>: The payload contains the <code>claims</code>. <code>Claims</code> are statements about an entity (typically, the user) and additional data.</p>
</li>
<li>
<p><strong>Example</strong>: <code>{"sub": "1516239022", "name": "John Doe", "admin": true} </code></p>
</li>
<li>
<p><strong>Explanation</strong>: This JSON object contains information about the user and other metadata. It says that the subject (user) of the JWT has the ID <code>1516239022</code>, the name <code>John Doe</code>, and has administrative rights.</p>
</li>
</ul>
</li>
<li>
<p><strong>Signature</strong></p>
<ul>
<li>
<p><strong>Purpose</strong>: The signature is used to verify that the sender of the JWT is who it says it is and to ensure that the message wasn't changed along the way.</p>
</li>
<li>
<p><strong>How It's Made</strong>: To create the signature, you take the encoded header, the encoded payload, a secret, the algorithm specified in the header (like HMAC <code>SHA256</code>), and sign that.</p>
</li>
<li>
<p><strong>Explanation</strong>: For example, if you are using the <code>HMAC SHA256</code> algorithm, the signature will be created by applying the <code>HMAC SHA256</code> algorithm to the combined string of <code>Base64Url</code> encoded header and payload, using a secret key.</p>
</li>
</ul>
</li>
</ol>
<p>These three parts together form the <code>JWT</code>: <span style="color:orange"><code>header.payload.signature</code></span>. When the JWT is sent, it appears as a string of three Base64Url-encoded parts, separated by dots, looking something like this: <span style="color:orange"><code>eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c</code></span></p>
<p>That's essentially what a JWT is made up of and how each part functions.</p>
<div class="hint-container note">
<p class="hint-container-title">Note</p>
<p>JWTs are encoded but not encrypted, making them readable if intercepted. Therefore,
avoid storing sensitive data like passwords directly in JWTs, as anyone with access can
decode and extract this information.</p>
</div>
<div class="hint-container note">
<p class="hint-container-title">Note</p>
<p>Instead, JWTs should contain only the necessary information required for user
identification and session management, such as user ID or username, and permissions or
roles that help with access control decisions. For securing the integrity and
authenticity of the token, it is digitally signed using a secret key known only to the
server. Even though the contents can be viewed, the signature helps ensure that the
token hasn't been altered after it was issued.</p>
</div>
<h2>Why JWT?</h2>
<p><em>One might wonder: if we can simply use a username and password to access secure endpoints in a web application, why then do we opt for using JWT with Spring Security?</em></p>
<p>Choosing <code>JWT (JSON Web Tokens)</code> with Spring Security instead of just using <code>usernames</code> and <code>passwords</code> has several benefits, especially for modern web applications:</p>
<ol>
<li>
<p><strong>No Need for Constant Check-ins</strong>: JWTs contain all the user information right inside them, so servers can verify who you are without having to ask the database every time you make a request. This is great for handling lots of users because it cuts down on database traffic.</p>
</li>
<li>
<p><strong>Extra Security</strong>: While you still use a username and password to log in, JWT provides a more secure way to keep checking who you are after you're logged in. The tokens are protected and have a built-in expiration time, which helps prevent them from being misused.</p>
</li>
<li>
<p><strong>Works Everywhere</strong>: JWTs are good at working across different systems and devices. This means that once you're logged in to one part of a system, you can use other parts too without having to log in again.</p>
</li>
<li>
<p><strong>Faster</strong>: Because your server isn't always asking the database who you are, things can run faster. With JWT, your server just needs to check the token you send with your requests, which speeds things up.</p>
</li>
<li>
<p><strong>Carries More Info</strong>: JWTs can also include extra details like what permissions you have, which helps the server know what you're allowed to do without having to look it up all the time.</p>
</li>
</ol>
<p>In simple terms, JWT makes things more secure, quicker, and easier to manage, especially when you have lots of users or need to work across different parts of a system. This makes them a strong choice for modern web applications.</p>
<h3>In the case of microservices, where there are multiple servers involved:</h3>
<div class="hint-container tip">
<p class="hint-container-title">Tips</p>
<p>JWTs (JSON Web Tokens) are extensively used in microservices architectures, where web
applications are built with multiple servers handling different services. In such
environments, retrieving usernames and passwords from a specific server every time a
user makes a request can be inefficient and slow down the system.</p>
</div>
<div class="hint-container tip">
<p class="hint-container-title">Tips</p>
<p>JWTs address this challenge by encapsulating the user's identity and authorization
details within a secure token. This token is issued once, typically after the user logs
in, and then used for subsequent requests across different services. This method
eliminates the need to continuously query a central authentication server or database,
thereby streamlining authentication processes across multiple servers and enhancing
overall system performance.</p>
</div>
<p>In a microservices setup, where multiple small services work together, JWT (JSON Web Tokens) offer some clear benefits for managing security efficiently:</p>
<ul>
<li>
<p><strong>Independent Verification</strong>: Each microservice can check who you are on its own using the information in the JWT. There’s no need to keep asking a central server to verify your identity, which cuts down on delays.</p>
</li>
<li>
<p><strong>Less Network Traffic</strong>: Because JWTs carry all needed user info right inside them, there’s no need for services to constantly talk to each other or to a central database to check user details. This reduces network traffic and speeds things up.</p>
</li>
<li>
<p><strong>Works Across Services</strong>: JWTs are great for setups that stretch over different areas or systems. Once you’re logged in and have a JWT, any service within the system can recognize and trust it.</p>
</li>
<li>
<p><strong>No Memory Needed</strong>: JWTs help keep the system simple because services don’t need to remember user sessions. Everything needed is in the JWT, which supports the stateless operation of microservices.</p>
</li>
</ul>
<p>Overall, JWT makes security smoother, quicker, and more scalable in a microservices architecture, fitting well with the need for each service to operate independently yet securely.</p>
<h2>Integrating JWT with Spring Security</h2>
<p>In the previous post, we implemented security using basic user and password authentication. In this post, we will replace it with JWT. You can refer to my <a href="#">GitHub</a> link for more details.</p>
<p>To implement JSON Web Tokens (JWT) for authorization in a Spring Boot Maven project, we need to include specific dependencies in our <code>pom.xml</code> file.</p>
<div class="language-xml line-numbers-mode" data-highlighter="shiki" data-ext="xml" data-title="xml" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">dependencies</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">    &lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">dependency</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">			&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">groupId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;io.jsonwebtoken&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">groupId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">			&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">artifactId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;jjwt-api&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">artifactId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">			&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">version</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;0.11.5&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">version</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">		&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">dependency</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">		&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">dependency</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">			&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">groupId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;io.jsonwebtoken&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">groupId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">			&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">artifactId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;jjwt-impl&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">artifactId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">			&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">version</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;0.11.5&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">version</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">		&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">dependency</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">		&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">dependency</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">			&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">groupId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;io.jsonwebtoken&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">groupId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">			&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">artifactId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;jjwt-jackson&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">artifactId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">			&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">version</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;0.11.5&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">version</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">		&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">dependency</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">dependencies</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>Explanation for the above dependencies</strong>:</p>
<p><code>1.</code> <strong>jjwt-jackson</strong></p>
<ul>
<li><strong>What it does</strong>: Integrates the Jackson library with JWT operations, optimizing how your Java application encodes and decodes JSON data within JWTs.</li>
</ul>
<p><code>2.</code> <strong>jjwt-api</strong></p>
<ul>
<li><strong>What it does</strong>: Supplies the fundamental classes and interfaces for constructing and validating JWTs, providing the building blocks for JWT functionality in Java.</li>
</ul>
<p><code>3.</code> <strong>jjwt-impl</strong></p>
<ul>
<li><strong>What it does</strong>: Provides the actual implementation for the interfaces from <code>jjwt-api</code>, enabling the generation, parsing, and management of JWTs according to your application's security protocols.</li>
</ul>
]]></content:encoded>
      <enclosure url="https://blog.taleedevops.today/assets/images/store/backend/java/jwt-authentication-authorization/title.jpg" type="image/jpeg"/>
    </item>
    <item>
      <title>Managing User Sessions in a Multi-Threaded Web Application with Redis and ThreadLocal</title>
      <link>https://blog.taleedevops.today/backend/java/multi-threaded-with-redis-and-threadLocal.html</link>
      <guid>https://blog.taleedevops.today/backend/java/multi-threaded-with-redis-and-threadLocal.html</guid>
      <source url="https://blog.taleedevops.today/rss.xml">Managing User Sessions in a Multi-Threaded Web Application with Redis and ThreadLocal</source>
      <description>Session management in a multi-threaded web app by pairing Redis for shared state with ThreadLocal for per-request storage, in an e-commerce setup.</description>
      <category>backend</category>
      <pubDate>Sat, 27 Jul 2024 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[
<p>In the dynamic world of web applications, efficient session management is crucial for maintaining user state and ensuring a smooth user experience. One effective approach combines the in-memory speed of <code>Redis</code> with the thread-specific storage capabilities of <code>ThreadLocal</code> in <code>Java</code>. This blog will walk you through the process of setting up this powerful duo for session management in a real-world e-commerce scenario.</p>
<figure><img src="/assets/images/store/backend/java/multi-threaded-with-redis-and-threadLocal/threadLocal-redis.webp" alt="" tabindex="0" loading="lazy"><figcaption></figcaption></figure>
<h2>Why Redis and ThreadLocal?</h2>
<p><code>Redis</code> is renowned for its blazing-fast performance as an in-memory data store, making it an excellent choice for session storage where speed and reliability are paramount.</p>
<p><code>ThreadLocal</code>, on the other hand, provides <code>thread-local</code> variables in <code>Java</code>, allowing each thread to maintain its own session state. This is particularly useful in multi-threaded environments like web servers where each request is handled by a separate thread.</p>
<h2>Setting Up the Environment</h2>
<p>Before diving into the code, ensure you have <code>Redis</code> installed and running on your machine. If you haven't set up <code>Redis</code> yet, you can download and install it from the official website.</p>
<p>Prerequisites</p>
<ul>
<li><strong>Spring Boot 3</strong></li>
<li><strong>JDK 21</strong></li>
<li><strong>Redis</strong></li>
</ul>
<h2>Step-by-Step Implementation</h2>
<ol>
<li>Set up Redis</li>
</ol>
<p>Ensure <code>Redis</code> is installed and running on your machine.</p>
<ol start="2">
<li>Add Dependencies</li>
</ol>
<p>Add the necessary dependencies to your <code>build.gradle</code> if you are using <code>Gradle</code>.</p>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" data-title="java" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">dependencies {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">    implementation </span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">'org.springframework.boot:spring-boot-starter-data-redis'</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">    implementation </span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">'redis.clients:jedis:4.3.1'</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">    implementation </span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">'org.springframework.boot:spring-boot-starter-web'</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>If you are using <code>Maven</code>, add these dependencies to your <code>pom.xml</code>.</p>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" data-title="java" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">&lt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">dependencies</span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">&gt;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">    &lt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">dependency</span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">&gt;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">        &lt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">groupId</span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">&gt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">org</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">springframework</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">boot</span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">&lt;/</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">groupId</span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">&gt;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">        &lt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">artifactId</span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">&gt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">spring</span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">-</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">boot</span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">-</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">starter</span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">-</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">data</span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">-</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">redis</span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">&lt;/</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">artifactId</span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">&gt;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">    &lt;/</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">dependency</span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">&gt;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">    &lt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">dependency</span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">&gt;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">        &lt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">groupId</span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">&gt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">redis</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">clients</span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">&lt;/</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">groupId</span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">&gt;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">        &lt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">artifactId</span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">&gt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">jedis</span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">&lt;/</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">artifactId</span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">&gt;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">        &lt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">version</span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">&gt;</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66">4.3</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#B31D28;--shiki-dark:#FFFFFF;--shiki-light-font-style:italic;--shiki-dark-font-style:inherit">1</span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">&lt;/</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">version</span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">&gt;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">    &lt;/</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">dependency</span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">&gt;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">    &lt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">dependency</span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">&gt;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">        &lt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">groupId</span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">&gt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">org</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">springframework</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">boot</span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">&lt;/</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">groupId</span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">&gt;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">        &lt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">artifactId</span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">&gt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">spring</span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">-</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">boot</span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">-</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">starter</span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">-</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">web</span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">&lt;/</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">artifactId</span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">&gt;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">    &lt;/</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">dependency</span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">&gt;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">&lt;/</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">dependencies</span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">&gt;</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><ol start="3">
<li>Configure Redis</li>
</ol>
<p>Create a <code>Redis configuration</code> class to set up the <code>Redis connection</code>.</p>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" data-title="java" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">package</span><span style="--shiki-light:#24292E;--shiki-dark:#C678DD"> com.example.demo.config</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> org.springframework.context.annotation.Bean</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> org.springframework.context.annotation.Configuration</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> org.springframework.data.redis.connection.RedisConnectionFactory</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> org.springframework.data.redis.connection.jedis.JedisConnectionFactory</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> org.springframework.data.redis.core.RedisTemplate</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> org.springframework.data.redis.serializer.StringRedisSerializer</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> redis.clients.jedis.JedisPoolConfig</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">@</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B">Configuration</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#E5C07B"> RedisConfig</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">    @</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B">Bean</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">    public</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> RedisConnectionFactory</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> redisConnectionFactory</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">()</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">        JedisPoolConfig</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75"> poolConfig</span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> JedisPoolConfig</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">();</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">        poolConfig</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">setMaxTotal</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66">128</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> JedisConnectionFactory</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(poolConfig);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">    @</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B">Bean</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">    public</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> RedisTemplate</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&lt;</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B">String</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B"> Object</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> redisTemplate</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">()</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">        RedisTemplate</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&lt;</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B">String</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B">Object</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt; </span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">template</span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> new</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> RedisTemplate</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&lt;&gt;();</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">        template</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">setConnectionFactory</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">redisConnectionFactory</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">());</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">        template</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">setKeySerializer</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> StringRedisSerializer</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">());</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">        template</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">setValueSerializer</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> StringRedisSerializer</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">());</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> template;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><ol start="4">
<li>Create a Session Manager Using ThreadLocal</li>
</ol>
<p>Create a <code>SessionManager</code> class that uses <code>ThreadLocal</code> to manage the <code>session ID</code>.</p>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" data-title="java" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">package</span><span style="--shiki-light:#24292E;--shiki-dark:#C678DD"> com.example.demo.session</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#E5C07B"> SessionManager</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">    private</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> static</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> final</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> ThreadLocal</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&lt;</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B">String</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75"> sessionThreadLocal </span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> new</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> ThreadLocal</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&lt;&gt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">()</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> static</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> setSessionId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">String</span><span style="--shiki-light:#E36209;--shiki-dark:#E06C75;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic"> sessionId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">)</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">        sessionThreadLocal</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">set</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(sessionId);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> static</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> String</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> getSessionId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">()</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> sessionThreadLocal</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">get</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">();</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> static</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> removeSessionId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">()</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">        sessionThreadLocal</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">remove</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">();</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><ol start="5">
<li>Create a Session Service to Interact with Redis</li>
</ol>
<p>Create a service class that interacts with Redis to manage session data.</p>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" data-title="java" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">package</span><span style="--shiki-light:#24292E;--shiki-dark:#C678DD"> com.example.demo.service</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> org.springframework.beans.factory.annotation.Autowired</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> org.springframework.data.redis.core.RedisTemplate</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> org.springframework.stereotype.Service</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">@</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B">Service</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#E5C07B"> SessionService</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">    @</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B">Autowired</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">    private</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> RedisTemplate</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&lt;</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B">String</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B"> Object</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75"> redisTemplate</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> setSessionData</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">String</span><span style="--shiki-light:#E36209;--shiki-dark:#E06C75;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic"> sessionId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">String</span><span style="--shiki-light:#E36209;--shiki-dark:#E06C75;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic"> key</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">String</span><span style="--shiki-light:#E36209;--shiki-dark:#E06C75;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic"> value</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">)</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">        redisTemplate</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">opsForHash</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">put</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(sessionId, key, value);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">    public</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> String</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> getSessionData</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">String</span><span style="--shiki-light:#E36209;--shiki-dark:#E06C75;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic"> sessionId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">String</span><span style="--shiki-light:#E36209;--shiki-dark:#E06C75;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic"> key</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">)</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> (String) </span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">redisTemplate</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">opsForHash</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">get</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(sessionId, key);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> invalidateSession</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">String</span><span style="--shiki-light:#E36209;--shiki-dark:#E06C75;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic"> sessionId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">)</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">        redisTemplate</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">delete</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(sessionId);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><ol start="6">
<li>Implement a Filter to Manage Session Lifecycle</li>
</ol>
<p>Create a <code>filter</code> that manages the session lifecycle, setting and removing the <code>session ID</code> in <code>ThreadLocal</code>.</p>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" data-title="java" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">package</span><span style="--shiki-light:#24292E;--shiki-dark:#C678DD"> com.example.demo.filter</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> com.example.demo.session.SessionManager</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> com.example.demo.service.SessionService</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> org.springframework.beans.factory.annotation.Autowired</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> org.springframework.stereotype.Component</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> javax.servlet.</span><span style="--shiki-light:#005CC5;--shiki-dark:#E5C07B">*</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> javax.servlet.http.HttpServletRequest</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> javax.servlet.http.HttpServletResponse</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> java.io.IOException</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">@</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B">Component</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#E5C07B"> SessionFilter</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> implements</span><span style="--shiki-light:#6F42C1;--shiki-dark:#E5C07B"> Filter</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">    @</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B">Autowired</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">    private</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> SessionService</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75"> sessionService</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">    @</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B">Override</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> doFilter</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">ServletRequest</span><span style="--shiki-light:#E36209;--shiki-dark:#E06C75;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic"> request</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">ServletResponse</span><span style="--shiki-light:#E36209;--shiki-dark:#E06C75;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic"> response</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">FilterChain</span><span style="--shiki-light:#E36209;--shiki-dark:#E06C75;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic"> chain</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">)</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> throws</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> IOException</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> ServletException</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">        HttpServletRequest</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75"> httpRequest</span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> (HttpServletRequest) request;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">        HttpServletResponse</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75"> httpResponse</span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> (HttpServletResponse) response;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">        String</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75"> sessionId</span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> httpRequest</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">getSession</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">getId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">();</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">        SessionManager</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">setSessionId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(sessionId);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#7F848E;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic">        // Example: Set some session data</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">        sessionService</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">setSessionData</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(sessionId, </span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">"user"</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">"JohnDoe"</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">        try</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">            chain</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">doFilter</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(request, response);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">        } </span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">finally</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">            SessionManager</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">removeSessionId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">();</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">        }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">    @</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B">Override</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> init</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">FilterConfig</span><span style="--shiki-light:#E36209;--shiki-dark:#E06C75;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic"> filterConfig</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">)</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> throws</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> ServletException</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">    @</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B">Override</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> destroy</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">()</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><ol start="7">
<li>Register the Filter</li>
</ol>
<p>Register the filter in your <code>Spring Boot</code> application.</p>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" data-title="java" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">package</span><span style="--shiki-light:#24292E;--shiki-dark:#C678DD"> com.example.demo</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> com.example.demo.filter.SessionFilter</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> org.springframework.boot.SpringApplication</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> org.springframework.boot.autoconfigure.SpringBootApplication</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> org.springframework.boot.web.servlet.FilterRegistrationBean</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> org.springframework.context.annotation.Bean</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">@</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B">SpringBootApplication</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#E5C07B"> DemoApplication</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> static</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> main</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B">String</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">[] </span><span style="--shiki-light:#E36209;--shiki-dark:#E06C75;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic">args</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">)</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">        SpringApplication</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">run</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">DemoApplication</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">class</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">, args);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">    @</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B">Bean</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">    public</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> FilterRegistrationBean</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&lt;</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B">SessionFilter</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> loggingFilter</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">()</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">        FilterRegistrationBean</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&lt;</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B">SessionFilter</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt; </span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">registrationBean</span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> new</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> FilterRegistrationBean</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&lt;&gt;();</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">        registrationBean</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">setFilter</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> SessionFilter</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">());</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">        registrationBean</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">addUrlPatterns</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">"/*"</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> registrationBean;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h1>Conclusion</h1>
<p>By leveraging <code>Redis</code> and <code>ThreadLocal</code> in a <code>Spring Boot 3</code> application, you can efficiently manage user sessions in a multi-threaded environment. <code>Redis</code> provides fast and reliable session storage, while <code>ThreadLocal</code> ensures thread-safe handling of session data. This setup enhances performance and scalability, making it ideal for modern web applications.</p>
<p>Implementing this approach in your <code>Spring Boot</code> application not only simplifies session management but also ensures a seamless user experience. Happy coding!</p>
]]></content:encoded>
      <enclosure url="https://blog.taleedevops.today/assets/images/store/backend/java/multi-threaded-with-redis-and-threadLocal/title.jpg" type="image/jpeg"/>
    </item>
    <item>
      <title>Securing Spring Boot 3 Applications with Spring Security 6</title>
      <link>https://blog.taleedevops.today/backend/java/securing-spring-boot-3-spring-security-6.html</link>
      <guid>https://blog.taleedevops.today/backend/java/securing-spring-boot-3-spring-security-6.html</guid>
      <source url="https://blog.taleedevops.today/rss.xml">Securing Spring Boot 3 Applications with Spring Security 6</source>
      <description>Secure a Spring Boot 3 app with Spring Security 6 from scratch: PostgreSQL via Spring Data JPA, the default config, then a custom one.</description>
      <category>backend</category>
      <pubDate>Fri, 02 Aug 2024 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[
<p>In this article, we will explore how to secure a web application developed with the latest version of <code>Spring Boot</code>, utilizing the most recent updates in <code>Spring Security</code>. Our journey will take us through creating a <code>Spring Boot</code> web project, its integration with a <code>PostgreSQL</code> database via <code>Spring Data JPA</code>, and the application of security measures provided by the updated <code>Spring Security</code> framework.</p>
<h2>Prerequisites</h2>
<p>You must need these tools installed on your computer to follow this tutorial.</p>
<ul>
<li>
<p><a href="https://www.oracle.com/java/technologies/downloads/#java11/" target="_blank" rel="noopener noreferrer">JDK 11 or higher</a></p>
</li>
<li>
<p><a href="https://maven.apache.org/" target="_blank" rel="noopener noreferrer">Maven 3.8 or higher</a></p>
</li>
<li>
<p><a href="https://docs.docker.com/get-docker/" target="_blank" rel="noopener noreferrer">PostgreSQL running on Docker</a></p>
</li>
<li>
<p>An HTTP client such as <code>Postman</code>, <code>Insomnia</code>, <code>cURL</code>, etc.</p>
</li>
</ul>
<h3>Set up the database</h3>
<p>We need <code>Docker</code> to run a container for <code>Postgres 16</code>; you can skip it if Postgres is installed on your computer. Run the command below to start the <code>Docker container</code> from the <code>Postgres</code> image:</p>
<div class="language-bash line-numbers-mode" data-highlighter="shiki" data-ext="bash" data-title="bash" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> run</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66"> --name</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> some-postgres</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66"> -e</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> POSTGRES_PASSWORD=mysecretpassword</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66"> -e</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> POSTGRES_DB=management-employee</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66"> -p</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> 5431:5432</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66"> -d</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> postgres:16-alpine</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h3>Set up the project</h3>
<p>We won't go into the details of building a CRUD application since the focus of this article is on securing the application. However, a basic overview is provided for better understanding.</p>
<p>We have included the following dependencies in our project:</p>
<p><code>1.</code> <strong>Spring Web</strong>: Enables building web applications with Spring, including RESTful services.</p>
<p><code>2.</code> <strong>PostgreSQL Driver</strong>: Connects your application to a <code>PostgreSQL</code> database for data storage.</p>
<p><code>3.</code> <strong>Spring Data JPA</strong>: Simplifies data access and manipulation through <code>JPA</code> repositories.</p>
<p><code>4.</code> <strong>Lombok</strong>: Reduces boilerplate code by automatically generating getters, setters, and other common methods.</p>
<p><code>5.</code> <strong>Spring Boot DevTools</strong>: Provides fast application restarts, live reload, and configuration options for a smoother development process.</p>
<p>The <code>Spring Boot</code> online project starter helps us create the project with these dependencies; go to the URL <a href="https://start.spring.io/" target="_blank" rel="noopener noreferrer">start.spring.io</a> to generate a new project.</p>
<figure><img src="/assets/images/store/backend/java/securing-spring-boot-3-spring-security-6/spring.io.webp" alt="" tabindex="0" loading="lazy"><figcaption></figcaption></figure>
<p>I chose <code>Java 21</code> and <code>Maven</code> as the dependency manager, but you can use whatever you want.</p>
<p>Click on the button <code>Generate</code> to download the project, open it in your <code>IDE</code>, and install the Maven dependencies.</p>
<h3>Developing a simple employee-based management system</h3>
<h4>Create the Employee Entity</h4>
<p>This Java class defines an <code>Employee</code> entity with attributes such as employeeId, name, email, department, and company, utilizing JPA annotations for ORM and Lombok annotations for boilerplate code like getters, setters, and constructors.</p>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" data-title="java" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">package</span><span style="--shiki-light:#24292E;--shiki-dark:#C678DD"> com.talee.employee.management.model</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> jakarta.persistence.Entity</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> jakarta.persistence.GeneratedValue</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> jakarta.persistence.GenerationType</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> jakarta.persistence.Id</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> lombok.AllArgsConstructor</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> lombok.Data</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> lombok.NoArgsConstructor</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">@</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B">Entity</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">@</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B">Data</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">@</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B">NoArgsConstructor</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">@</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B">AllArgsConstructor</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#E5C07B"> Employee</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">  @</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B">Id</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">  @</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B">GeneratedValue</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66">strategy</span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> GenerationType</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">AUTO</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">  private</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> Long</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75"> employeeId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">  private</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> String</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75"> name</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">  private</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> String</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75"> email</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">  private</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> String</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75"> nationality</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">  private</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> Integer</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75"> old</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4>Create the Employee Repository</h4>
<p>This interface defines a repository for <code>Employee entities</code>, extending <code>Spring Data JPA</code> to facilitate database operations.</p>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" data-title="java" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">package</span><span style="--shiki-light:#24292E;--shiki-dark:#C678DD"> com.talee.employee.management.repo</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> com.talee.employee.management.model.Employee</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> org.springframework.data.jpa.repository.JpaRepository</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> interface</span><span style="--shiki-light:#6F42C1;--shiki-dark:#E5C07B"> EmployeeRepository</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> extends</span><span style="--shiki-light:#6F42C1;--shiki-dark:#E5C07B"> JpaRepository</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&lt;</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B">Employee</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B"> Integer</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4>Create the Employee Service</h4>
<p>The <code>EmployeeService</code> class interact with the EmployeeRepository to perform CRUD operations on Employee entities, allowing for the creation, retrieval, updating, and deletion of employee records in the database.</p>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" data-title="java" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">package</span><span style="--shiki-light:#24292E;--shiki-dark:#C678DD"> com.talee.employee.management.service</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> com.talee.employee.management.model.Employee</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> java.util.List</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> java.util.Optional</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> org.springframework.stereotype.Service</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">@</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B">Service</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#E5C07B"> EmployeeService</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">  private</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> final</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> EmployeeRepository</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75"> repository</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">  public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> EmployeeService</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">EmployeeRepository</span><span style="--shiki-light:#E36209;--shiki-dark:#E06C75;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic"> repository</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">)</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#E5C07B">    this</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">repository</span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> repository;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">  }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">  public</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> List</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&lt;</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B">Employee</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> findAll</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">()</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> repository</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">findAll</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">();</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">  }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">  public</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> Optional</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&lt;</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B">Employee</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> findById</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">Integer</span><span style="--shiki-light:#E36209;--shiki-dark:#E06C75;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic"> id</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">)</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> repository</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">findById</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(id);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">  }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">  public</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> Employee</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> save</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">Employee</span><span style="--shiki-light:#E36209;--shiki-dark:#E06C75;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic"> employee</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">)</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> repository</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">save</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(employee);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">  }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">  public</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> deleteById</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">Integer</span><span style="--shiki-light:#E36209;--shiki-dark:#E06C75;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic"> id</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">)</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">    repository</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">deleteById</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(id);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">  }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">  public</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> Optional</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&lt;</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B">Employee</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> updateEmployee</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">Integer</span><span style="--shiki-light:#E36209;--shiki-dark:#E06C75;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic"> id</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">Employee</span><span style="--shiki-light:#E36209;--shiki-dark:#E06C75;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic"> employeeDetails</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">)</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> repository</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">findById</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(id).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">map</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(employee </span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">-&gt;</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">      employee</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">setName</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">employeeDetails</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">getName</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">());</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">      employee</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">setEmail</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">employeeDetails</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">getEmail</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">());</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">      employee</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">setNationality</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">employeeDetails</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">getNationality</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">());</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">      employee</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">setOld</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">employeeDetails</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">getOld</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">());</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">      return</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> Optional</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">of</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">repository</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">save</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(employee));</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">    }).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">orElse</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">Optional</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">empty</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">());</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">  }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4>Create the Employee Controller</h4>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" data-title="java" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">package</span><span style="--shiki-light:#24292E;--shiki-dark:#C678DD"> com.talee.employee.management.controller</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> com.talee.employee.management.model.Employee</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> com.talee.employee.management.service.EmployeeService</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> java.util.List</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> org.springframework.http.ResponseEntity</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> org.springframework.web.bind.annotation.DeleteMapping</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> org.springframework.web.bind.annotation.GetMapping</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> org.springframework.web.bind.annotation.PathVariable</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> org.springframework.web.bind.annotation.PostMapping</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> org.springframework.web.bind.annotation.PutMapping</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> org.springframework.web.bind.annotation.RequestBody</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> org.springframework.web.bind.annotation.RequestMapping</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> org.springframework.web.bind.annotation.RestController</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">@</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B">RestController</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">@</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B">RequestMapping</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">(</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">"/api/employees"</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#E5C07B"> EmployeeController</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">  private</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> final</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> EmployeeService</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75"> service</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">  public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> EmployeeController</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">EmployeeService</span><span style="--shiki-light:#E36209;--shiki-dark:#E06C75;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic"> service</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">)</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#E5C07B">    this</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">service</span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> service;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">  }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">  @</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B">GetMapping</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">  public</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> List</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&lt;</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B">Employee</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> getAllEmployees</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">()</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> service</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">findAll</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">();</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">  }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">  @</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B">GetMapping</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">(</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">"/{id}"</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">  public</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> ResponseEntity</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&lt;</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B">Employee</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> getEmployeeById</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(@</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B">PathVariable</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> Integer</span><span style="--shiki-light:#E36209;--shiki-dark:#E06C75;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic"> id</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">)</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> service</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">findById</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(id)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">        .</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">map</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(ResponseEntity</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">::</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">ok)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">        .</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">orElseGet</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">-&gt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> ResponseEntity</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">notFound</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">build</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">());</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">  }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">  @</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B">PostMapping</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">  public</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> Employee</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> createEmployee</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(@</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B">RequestBody</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> Employee</span><span style="--shiki-light:#E36209;--shiki-dark:#E06C75;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic"> employee</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">)</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> service</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">save</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(employee);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">  }</span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">  @</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B">PutMapping</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">(</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">"/{id}"</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">  public</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> ResponseEntity</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&lt;</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B">Employee</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> ulspdateEmployee</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(@</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B">PathVariable</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> Integer</span><span style="--shiki-light:#E36209;--shiki-dark:#E06C75;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic"> id</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">      @</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B">RequestBody</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> Employee</span><span style="--shiki-light:#E36209;--shiki-dark:#E06C75;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic"> employeeDetails</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">)</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> service</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">updateEmployee</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(id, employeeDetails)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">        .</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">map</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(ResponseEntity</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">::</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">ok)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">        .</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">orElseGet</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">-&gt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> ResponseEntity</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">notFound</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">build</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">());</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">  }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">  @</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B">DeleteMapping</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">(</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">"/{id}"</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">  public</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> ResponseEntity</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&lt;</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">?</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> deleteEmployee</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(@</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B">PathVariable</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> Integer</span><span style="--shiki-light:#E36209;--shiki-dark:#E06C75;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic"> id</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">)</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> service</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">findById</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(id)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">        .</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">map</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(employee </span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">-&gt;</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">          service</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">deleteById</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(id);</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">          return</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> ResponseEntity</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">ok</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">build</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">();</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">        })</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">        .</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">orElseGet</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">-&gt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> ResponseEntity</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">notFound</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">build</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">());</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">  }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4>Import data to Database</h4>
<p>Our application is configured to automatically populate the database with initial data at startup, utilizing SQL files named <code>schema.sql</code> and <code>data.sql</code>.`</p>
<p><strong>schema.sql</strong></p>
<div class="language-sql line-numbers-mode" data-highlighter="shiki" data-ext="sql" data-title="sql" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">CREATE</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> TABLE</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> IF</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> NOT</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> EXISTS</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> employee (</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">                          employee_id </span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">BIGSERIAL</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> PRIMARY KEY</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">,</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">                          name</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> VARCHAR</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66">255</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">),</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">                          email </span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">VARCHAR</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66">255</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">),</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">                          nationality </span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">VARCHAR</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66">255</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">),</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">                          old </span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">INTEGER</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">);</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>data.sql</strong></p>
<div class="language-sql line-numbers-mode" data-highlighter="shiki" data-ext="sql" data-title="sql" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">INSERT INTO</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> Employee (</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">name</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">, email, nationality, old) </span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">VALUES</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">'Eric Cantona'</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">'eric.cantona@manutd.com'</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">'French'</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66">57</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">INSERT INTO</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> Employee (</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">name</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">, email, nationality, old) </span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">VALUES</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">'Ryan Giggs'</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">'ryan.giggs@manutd.com'</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">'Welsh'</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66">50</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">INSERT INTO</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> Employee (</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">name</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">, email, nationality, old) </span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">VALUES</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">'Paul Scholes'</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">'paul.scholes@manutd.com'</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">'English'</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66">49</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">INSERT INTO</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> Employee (</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">name</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">, email, nationality, old) </span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">VALUES</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">'Roy Keane'</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">'roy.keane@manutd.com'</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">'Irish'</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66">52</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">INSERT INTO</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> Employee (</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">name</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">, email, nationality, old) </span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">VALUES</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">'David Beckham'</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">'david.beckham@manutd.com'</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">'English'</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66">48</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">);</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3>Configure the database connection</h3>
<p>Let's configure the application to connect to the database and perform database table creation (using Hibernate under the hood). Open the application configuration file src/resources/application.yml and add the code below:</p>
<div class="language-yml line-numbers-mode" data-highlighter="shiki" data-ext="yml" data-title="yml" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">spring</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">  application</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">    name</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">: </span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">employee-management</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">  datasource</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">    url</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">: </span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">jdbc:postgresql://localhost:5431/management-employee</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">    username</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">: </span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">postgres</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">    password</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">: </span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">3+0M1606Pc_4</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">  jpa</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">    hibernate</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">      ddl-auto</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">: </span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">update</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">    show-sql</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66">true</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">    properties</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">      hibernate</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">        dialect</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">: </span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">org.hibernate.dialect.PostgreSQLDialect</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">  sql</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">    init</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">      mode</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">: </span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">always</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">server</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">  port</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66">8018</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Run the application with the command mvn <code>spring-boot:run</code>; it will start at port <code>8018</code>.</p>
<p><a href=""></a></p>
<p>If we pay attention to the console when starting the application, we can see the message displaying a security password generated because Spring Security has the <code>HTTP Basic</code> authentication enabled by default.</p>
<h3>Protecting our Web Application using Default Spring Security Configuration</h3>
<div class="hint-container note">
<p class="hint-container-title">Note</p>
<p>Adding Spring Security to your Spring Boot project automatically makes it safer. This is because the creators of Spring decided they wanted every application to be secure right from the start.</p>
</div>
<h4>How It Works</h4>
<p>Once you include <code>Spring Security</code> in your project, it instantly sets up some security features for you. This means your application will have a basic level of security without you needing to do anything extra.</p>
<p>For securing our web application, we need another dependency i.e, <code>Spring Security</code>:</p>
<p><strong>Spring Security</strong>: Adds authentication and authorization features to secure your application.</p>
<p>Given that our project is built with Maven and <code>Spring Boot</code>, the dependency for Spring Security would appear in the <code>pom.xml</code> file as follows:</p>
<div class="language-xml line-numbers-mode" data-highlighter="shiki" data-ext="xml" data-title="xml" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">dependency</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">    &lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">groupId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;org.springframework.boot&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">groupId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">    &lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">artifactId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;spring-boot-starter-security&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">artifactId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">dependency</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Our final <code>pom.xml</code> file would be structured as follows to incorporate the specified dependencies:</p>
<div class="language-xml line-numbers-mode" data-highlighter="shiki" data-ext="xml" data-title="xml" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&lt;?</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">xml</span><span style="--shiki-light:#6F42C1;--shiki-dark:#D19A66"> version</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">=</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">"1.0"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#D19A66"> encoding</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">=</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">"UTF-8"</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">?&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">project</span><span style="--shiki-light:#6F42C1;--shiki-dark:#D19A66"> xmlns</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">=</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">"http://maven.apache.org/POM/4.0.0"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#D19A66"> xmlns:xsi</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">=</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">"http://www.w3.org/2001/XMLSchema-instance"</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#D19A66">	xsi:schemaLocation</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">=</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#7F848E;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic">	&lt;!-- Basic POM Information --&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">	&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">modelVersion</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;4.0.0&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">modelVersion</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#7F848E;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic">	&lt;!-- Parent Project Information --&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">	&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">parent</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">		&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">groupId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;org.springframework.boot&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">groupId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">		&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">artifactId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;spring-boot-starter-parent&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">artifactId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">		&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">version</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;3.3.2&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">version</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">		&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">relativePath</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">/&gt; </span><span style="--shiki-light:#6A737D;--shiki-dark:#7F848E;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic">&lt;!-- lookup parent from repository --&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">	&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">parent</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#7F848E;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic">	&lt;!-- Project Coordinates --&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">	&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">groupId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;com.talee&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">groupId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">	&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">artifactId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;employee.management&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">artifactId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">	&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">version</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;0.0.1-SNAPSHOT&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">version</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">	&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">name</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;employee.management&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">name</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">	&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">description</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;Implement authentication on a Web Api&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">description</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">	&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">url</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">/&gt; </span><span style="--shiki-light:#6A737D;--shiki-dark:#7F848E;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic">&lt;!-- URL for the project, can be filled as needed --&gt;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#7F848E;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic">	&lt;!-- Licensing Information --&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">	&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">licenses</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">		&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">license</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">/&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">	&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">licenses</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#7F848E;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic">	&lt;!-- Developer Information --&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">	&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">developers</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">		&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">developer</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">/&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">	&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">developers</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#7F848E;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic">	&lt;!-- Source Control Management Information --&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">	&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">scm</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">		&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">connection</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">/&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">		&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">developerConnection</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">/&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">		&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">tag</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">/&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">		&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">url</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">/&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">	&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">scm</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#7F848E;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic">	&lt;!-- Project Properties --&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">	&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">properties</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">		&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">java.version</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;21&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">java.version</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">	&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">properties</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#7F848E;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic">	&lt;!-- Project Dependencies --&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">	&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">dependencies</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#7F848E;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic">		&lt;!-- Spring Boot Starter for JPA --&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">		&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">dependency</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">			&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">groupId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;org.springframework.boot&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">groupId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">			&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">artifactId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;spring-boot-starter-data-jpa&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">artifactId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">		&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">dependency</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#7F848E;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic">		&lt;!-- Spring Boot Starter for Security --&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">		&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">dependency</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">			&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">groupId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;org.springframework.boot&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">groupId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">			&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">artifactId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;spring-boot-starter-security&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">artifactId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">		&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">dependency</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#7F848E;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic">		&lt;!-- Spring Boot Starter for Web --&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">		&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">dependency</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">			&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">groupId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;org.springframework.boot&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">groupId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">			&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">artifactId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;spring-boot-starter-web&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">artifactId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">		&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">dependency</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#7F848E;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic">		&lt;!-- Spring Boot DevTools for Development --&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">		&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">dependency</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">			&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">groupId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;org.springframework.boot&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">groupId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">			&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">artifactId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;spring-boot-devtools&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">artifactId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">			&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">scope</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;runtime&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">scope</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">			&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">optional</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;true&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">optional</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">		&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">dependency</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#7F848E;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic">		&lt;!-- PostgreSQL JDBC Driver --&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">		&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">dependency</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">			&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">groupId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;org.postgresql&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">groupId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">			&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">artifactId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;postgresql&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">artifactId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">			&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">scope</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;runtime&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">scope</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">		&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">dependency</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#7F848E;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic">		&lt;!-- Lombok for Boilerplate Code Reduction --&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">		&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">dependency</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">			&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">groupId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;org.projectlombok&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">groupId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">			&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">artifactId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;lombok&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">artifactId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">			&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">optional</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;true&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">optional</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">		&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">dependency</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#7F848E;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic">		&lt;!-- Spring Boot Starter for Testing --&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">		&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">dependency</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">			&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">groupId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;org.springframework.boot&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">groupId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">			&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">artifactId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;spring-boot-starter-test&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">artifactId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">			&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">scope</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;test&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">scope</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">		&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">dependency</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#7F848E;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic">		&lt;!-- Spring Security Test Dependency --&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">		&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">dependency</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">			&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">groupId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;org.springframework.security&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">groupId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">			&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">artifactId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;spring-security-test&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">artifactId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">			&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">scope</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;test&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">scope</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">		&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">dependency</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">	&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">dependencies</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#7F848E;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic">	&lt;!-- Build Configuration --&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">	&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">build</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">		&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">plugins</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">			&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">plugin</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">				&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">groupId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;org.springframework.boot&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">groupId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">				&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">artifactId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;spring-boot-maven-plugin&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">artifactId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">				&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">configuration</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">					&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">excludes</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">						&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">exclude</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">							&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">groupId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;org.projectlombok&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">groupId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">							&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">artifactId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;lombok&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">artifactId</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">						&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">exclude</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">					&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">excludes</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">				&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">configuration</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">			&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">plugin</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">		&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">plugins</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">	&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">build</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#E06C75">project</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">&gt;</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><div class="hint-container note">
<p class="hint-container-title">Note</p>
<p>Adding Spring Security to your Spring Boot project automatically makes it safer. This is because the creators of Spring decided they wanted every application to be secure right from the start.</p>
</div>
<p>When attempting to access any API via the browser, the default login form will be presented like the one given below:</p>
<figure><img src="/assets/images/store/backend/java/securing-spring-boot-3-spring-security-6/sign-in.webp" alt="" tabindex="0" loading="lazy"><figcaption></figcaption></figure>
<p>The default <code>username</code> provided by spring security is <span style="color:orange"><code>user</code></span>, while the <code>password</code> is <code>auto-generated</code> and can be found in the console.</p>
<p>But this <code>username</code> <code>password</code> should not be used in real-time production scenarios</p>
<figure><img src="/assets/images/store/backend/java/securing-spring-boot-3-spring-security-6/security-password.webp" alt="" tabindex="0" loading="lazy"><figcaption></figcaption></figure>
<p>Here, we are trying to access an API i.e. to get the list of all employees. Attached is a small video to get a clearer picture.</p>
]]></content:encoded>
      <enclosure url="https://blog.taleedevops.today/assets/images/store/backend/java/securing-spring-boot-3-spring-security-6/title.jpg" type="image/jpeg"/>
    </item>
    <item>
      <title>Apache Kafka: Understanding Key Concepts and Components.</title>
      <link>https://blog.taleedevops.today/backend/kafka/understanding-key-concepts-components.html</link>
      <guid>https://blog.taleedevops.today/backend/kafka/understanding-key-concepts-components.html</guid>
      <source url="https://blog.taleedevops.today/rss.xml">Apache Kafka: Understanding Key Concepts and Components.</source>
      <description>Apache Kafka from the ground up — clusters, brokers, topics, partitions, producers, consumers, Streams and Connect, and where event-driven fits.</description>
      <category>backend</category>
      <pubDate>Thu, 18 Jul 2024 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[
<p>In the world of modern distributed systems and data processing, <code>Apache Kafka</code> (commonly known as <code>Kafka</code>) has emerged as a powerful and widely adopted platform for <code>real-time</code> data streaming and event processing. Specifically, <code>Apache Kafka</code> is extensively used in microservices architectures.</p>
<p>In this article, we will delve into the components of <code>Kafka</code>, explore how <code>Kafka</code> works, and understand its advantages and disadvantages, as well as its applications in real life.</p>
<h2>What is Apache Kafka?</h2>
<figure><img src="/assets/images/store/backend/kafka/what-is-kafka.webp" alt="" tabindex="0" loading="lazy"><figcaption></figcaption></figure>
<p><code>Apache Kafka</code> is an open-source stream-processing software platform developed by <code>LinkedIn</code> and donated to the <code>Apache Software Foundation</code>, written in <code>Scala</code> and <code>Java</code>.</p>
<blockquote>
<p>“Apache Kafka is an open-source distributed event streaming platform used by thousands of companies for high-performance data pipelines, streaming analytics, data integration, and mission-critical
applications.”</p>
<blockquote>
<p>Source: <a href="https://kafka.apache.org" target="_blank" rel="noopener noreferrer">Kafka home page</a></p>
</blockquote>
</blockquote>
<p>The project aims to provide a unified, high-throughput, low-latency platform for handling real-time data feeds. Its core architectural concept is an immutable log of messages that can be organized into topics for consumption by multiple users or applications. A file system or database commit log keeps a permanent record of all messages so <code>Kafka</code> can replay them to maintain a consistent system state.</p>
<p><code>Kafka</code> stores data durably, in serialized fashion. It distributes data across <code>a cluster</code> of nodes, providing performance at scale that’s resilient to failures.</p>
<p><code>Kafka</code> is available as open <a href="https://kafka.apache.org/downloads" target="_blank" rel="noopener noreferrer">source code</a> or from vendors who offer it as a cloud managed service, including <code>AWS (MKS – Managed Kafka Service)</code>, <code>Azure</code>, <code>Google</code> and <code>Confluent (Confluent Cloud)</code>, the company founded by the creators of <code>Kafka</code>.</p>
<h2>What is Apache Kafka Used For?</h2>
<p>Kafka is flexible and widely-used, but there are several use cases for which it stands out:</p>
<ul>
<li>
<p><strong>Log/Metricsk, aggregation</strong>: <code>Kafka</code> provides log or event data as a stream of messages.  It removes any dependency on file details by gathering physical log files from servers and storing them in a central location. Kafka also supports multiple data sources and distributed data consumption.</p>
</li>
<li>
<p><strong>Stream processing</strong>: <code>Kafka</code> is valuable in scenarios in which <code>real-time</code> data is collected and processed. This includes raw data that’s consumed from <code>Kafka topics</code> and then enriched or processed into new <code>Kafka topics</code> for further consumption as part of a multi-step pipeline.</p>
</li>
<li>
<p><strong>Commit logs</strong>: Any large-scale distributed system can use <code>Kafka</code> to represent external commit logs. Replicated logs across a <code>Kafka</code> cluster help data recovery when nodes fail.</p>
</li>
<li>
<p><strong>Activity tracking</strong>: Data from user click stream activities, such as page views, searches, and so on, are <code>published</code> to central <code>topics</code>, with one topic per activity type.</p>
</li>
<li>
<p><strong>Event Sourcing</strong>: Event-driven architectures benefit from Kafka's ability to capture and store events that represent state changes, enabling the implementation of reliable and scalable event sourcing.</p>
</li>
<li>
<p><strong>Data Integration</strong>: <code>Kafka</code> acts as a bridge between different <code>systems</code>, enabling seamless data integration between <code>applications</code> and <code>databases</code>.</p>
</li>
</ul>
<figure><img src="/assets/images/store/backend/kafka/kafka-used-for.webp" alt="" tabindex="0" loading="lazy"><figcaption></figcaption></figure>
<h2>Understanding Event-driven Architecture in Apache Kafka</h2>
<p><code>Kafka</code> receives and sends data as events called messages which are organized into <code>topics</code> which are <code>“published”</code> by data producers and <code>“subscribed”</code> to by data <code>consumers</code>, which is why <code>Kafka</code> is sometimes called a <code>“pub/sub” system</code>. An event is simply a statement that something occurred in the real world. An event may also be referred to as a record or a message.</p>
<h2>What is a Kafka cluster?</h2>
<p><code>A cluster</code> is a distributed computing concept in which a group of devices works together to achieve a specific purpose. Multiple <code>Kafka brokers</code> form a <code>Kafka cluster</code>.</p>
<p>The main goal of a <code>Kafka cluster</code> is to spread workloads evenly across replicas and partitions. <code>Kafka clusters</code> can scale without interruption. They also manage the persistence and replication of data messages. If one <code>broker</code> fails, other <code>Kafka brokers</code> step in to offer similar services without data loss or degraded latency.</p>
<h2>Kafka Cluster Architecture</h2>
<figure><img src="/assets/images/store/backend/kafka/kafka-cluster-v2.webp" alt="" tabindex="0" loading="lazy"><figcaption></figcaption></figure>
<p>Multiple components comprise the core <code>Kafka cluster</code> architecture:</p>
<ul>
<li>
<p><strong>Kafka Events</strong></p>
</li>
<li>
<p><strong>Broker</strong></p>
</li>
<li>
<p><strong>Controller</strong></p>
</li>
<li>
<p><strong>Partitions</strong></p>
</li>
<li>
<p><strong>Consumer</strong></p>
</li>
<li>
<p><strong>Producer</strong></p>
</li>
<li>
<p><strong>Topic</strong></p>
</li>
<li>
<p><strong>Zookeeper (phasing out)</strong></p>
</li>
<li>
<p><strong>Schema registry</strong></p>
</li>
</ul>
<h3><strong>About the Apache Kafka Events</strong></h3>
<p><code>A Kafka</code> event records the fact that <code>"something has happened"</code> in the world or within your business. It is also known as a record or message. In many Kafka documents, the terms event, record, and message are used interchangeably.</p>
<p>Reading and writing data in Kafka are done through events. Each event contains a key, value, and metadata (if any).</p>
<p>Example of an event containing a key, value, and metadata (timestamp):</p>
<div class="language-json line-numbers-mode" data-highlighter="shiki" data-ext="json" data-title="json" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">{</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#E06C75">  "key"</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">: </span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">"user123"</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#E06C75">  "value"</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">: {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#E06C75">    "action"</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">: </span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">"login"</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#E06C75">    "status"</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">: </span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">"success"</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">  },</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#E06C75">  "metadata"</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">: {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#E06C75">    "timestamp"</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">: </span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">"2024-07-20T10:15:30Z"</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">  }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3><strong>About the Apache Kafka broker</strong></h3>
<p>A broker is a <code>single Kafka server</code>. <code>Kafka brokers</code> receive messages from <code>producers</code>, assign them offsets, and commit the messages to disk storage. An <code>offset</code> is a unique integer value that <code>Kafka</code> increments and adds to each message as it’s generated. Offsets are critical for maintaining data consistency in the event of a failure or outage, as consumers use offsets to return to the last-consumed message after a failure. <code>Brokers</code> respond to partition call requests from consumers and return messages that have been committed to disk. <code>A single broker</code> operates based on the specific hardware and its functional properties.</p>
<figure><img src="/assets/images/store/backend/kafka/kafka-broker.webp" alt="" tabindex="0" loading="lazy"><figcaption></figcaption></figure>
<h3><strong>About the Apache Controller</strong></h3>
<p><code>Kafka brokers</code> form a <code>cluster</code> by directly or indirectly sharing information.  In a <code>Kafka cluster</code>, <a href="https://jaceklaskowski.gitbooks.io/apache-kafka/content/kafka-controller-KafkaController.html" target="_blank" rel="noopener noreferrer">one broker serves as the Apache controller</a>. <code>The controller</code> is responsible for managing the states of partitions and replicas and for performing administrative tasks such as reassigning partitions and registering handlers to be notified about changes.</p>
<p>Although the <code>Controller</code> service runs on every <code>broker</code> in a <code>Kafka cluster</code>, only one <code>broker</code> can be active (elected) at any point in time. <code>The Kafka Controller</code> is created and starts up as soon as the <code>Kafka server</code> starts up.</p>
<h3><strong>About partitions in Apache Kafka</strong></h3>
<p><code>Partitioning</code> is a foundational principle in most distributed systems. In <code>Kafka</code>, a <code>topic</code> is split into multiple partitions. A <code>partition</code> is a discrete log file. <code>Kafka</code> writes records to each partition in <code>append-only</code> fashion. In other words, all of the records belonging to a particular topic are divided and stored in <code>partitions</code>.</p>
<p><code>Kafka</code> distributes the <code>partitions</code> of a particular topic across multiple <code>brokers</code>. This distributed layout improves scalability through parallelism, as you’re not limited to one specific <code>broker’s</code> I/O. <code>Kafka</code> also replicates <code>partitions</code> and spreads the replicas across the <code>cluster</code>. This provides robust fault tolerance; if one broker fails <code>other brokers</code> can take over and pick up where the failed machine left off.</p>
<p>When a new message is written to a <code>topic</code>, <code>Kafka</code> adds it to one of the <code>topic’s</code> partitions. Messages with the same key (for example, an enrollment number or customer ID) are published to the same <code>partition</code>. <code>Kafka</code> assures that any reader of a given <code>topic/partition</code> always consumes messages in their published sequence.</p>
<figure><img src="/assets/images/store/backend/kafka/kafka-partitions.webp" alt="" tabindex="0" loading="lazy"><figcaption></figcaption></figure>
<p>Each event in a <code>partition</code> is assigned a unique offset, starting from 0 for the first event in the <code>partition</code> and incrementing by one for each subsequent event. The <code>offset</code> is used to determine the position of the event within a <code>partition</code>.</p>
<p>Each <code>partition</code> has a <code>broker</code> designated as the <code>leader</code>, which owns that <code>partition</code>, while the remaining <code>brokers</code> store replicas of the <code>partition</code>, known as <code>followers</code>.</p>
<p>If the <code>leader broker</code> fails, one of the followers with updated data will be selected as the <code>new leader</code>. This process is called <code>leader failover</code>, and it ensures the availability of the data.</p>
<figure><img src="/assets/images/store/backend/kafka/kafka-partitions-v2.webp" alt="" tabindex="0" loading="lazy"><figcaption></figcaption></figure>
<h3><strong>About consumers in Apache Kafka</strong></h3>
<p><code>Consumers</code> are applications or machines that subscribe to <code>topics</code> and process published message feeds. Sometimes called <code>“subscribers”</code> or <code>“readers”</code> <code>consumers</code> read the messages in the order in which they were generated.</p>
<p><code>A consumer</code> uses the <code>offset</code> to track which messages it has already consumed. <code>A consumer</code> stores the offset of the last consumed message for each partition so that it can stop and restart without losing its place.</p>
<p><code>Consumers</code> interact with a topic as a <code>group</code> (although a group can consist of only one consumer). This enables scalable processing. The group ensures that one member only consumes each partition. if a single consumer fails, the group’s remaining members reorganize the consumed partitions to compensate for the absent member. Groups enable <code>Kafka</code> to consume topics with a massive amount of messages <code>horizontally</code>.</p>
<p><code>Consumers</code> connect to Kafka Brokers via the <a href="https://en.wikipedia.org/wiki/Transmission_Control_Protocol?ref=taleedevops.today" target="_blank" rel="noopener noreferrer">TCP</a> <code>network protocol</code>. This is a <code>bi-directional connection</code>.</p>
<p>When a <code>consumer group</code> reads events from partitions, there are three possible scenarios:</p>
<ul>
<li><strong>Scenario 1</strong>: The consumer group has fewer consumers than the number of <code>partitions</code> in a <code>topic</code>.</li>
</ul>
<p><code>Consumers 1 and 2</code> read events from <code>4 partitions</code> of <code>Topic T1</code> sequentially.</p>
<figure><img src="/assets/images/store/backend/kafka/kafka-consumers-v1.webp" alt="" tabindex="0" loading="lazy"><figcaption></figcaption></figure>
<ul>
<li><strong>Scenario 2</strong>: The consumer group has the same number of consumers as the number of partitions in a topic.</li>
</ul>
<p>If we add 2 <code>consumers</code> to Consumer Group 1, making the number of consumers equal to the number of partitions, each consumer will read events from one corresponding partition. In cases where consumers perform high-latency operations such as writing to a database or performing time-consuming computations on the data, increasing the number of consumers will distribute the load, thereby speeding up the data reading process from a topic.</p>
<figure><img src="/assets/images/store/backend/kafka/kafka-consumers-v2.webp" alt="" tabindex="0" loading="lazy"><figcaption></figcaption></figure>
<ul>
<li><strong>Scenario 3</strong>: The consumer group has more consumers than the number of partitions in a topic.</li>
</ul>
<p>We should not have more <code>consumers</code> than partitions in a topic because some consumers may become idle as all partitions are occupied, leading to events being missed or not read.</p>
<figure><img src="/assets/images/store/backend/kafka/kafka-consumers-v3.webp" alt="" tabindex="0" loading="lazy"><figcaption></figcaption></figure>
<h3><strong>About producers in Apache Kafka</strong></h3>
<p><code>Kafka Producer</code> is a <code>client application</code> that <code>publishes events</code> to a specific <code>topic</code> in <code>Kafka</code> and always writes to the <strong>leader broker</strong>. By default, <code>producers</code> do not care which partition an event is written to and will publish events evenly across all partitions of a topic. In some cases, <code>a producer</code> will send events directly to specific partitions.</p>
<p><code>Producers</code> connect to Kafka Brokers via the <a href="https://en.wikipedia.org/wiki/Transmission_Control_Protocol?ref=taleedevops.today" target="_blank" rel="noopener noreferrer">TCP</a> <code>network protocol</code>. This is a <code>bi-directional connection</code>.</p>
<p>The diagram below provides an overview of the components in <code>Kafka producers</code>.</p>
<figure><img src="/assets/images/store/backend/kafka/kafka-producers-v1.webp" alt="" tabindex="0" loading="lazy"><figcaption></figcaption></figure>
<p>The process of sending events from <code>Kafka</code> producers to <code>Kafka brokers</code> involves <code>4 steps</code>.</p>
<ul>
<li><code>Step 1</code>: <strong>Create a ProducerRecord</strong></li>
</ul>
<p><code>A producer</code> publishes an event to <code>Kafka</code> by creating a <code>ProducerRecord</code>, which must include a <code>topic</code> and <code>value</code>, and optionally a <code>partition</code> and <code>key</code>.</p>
<ul>
<li><code>Step 2</code>: <strong>Serializer</strong></li>
</ul>
<p>Before sending the <code>ProducerRecord</code> over the network, the <code>producer</code> will <code>serialize</code> the <code>key</code> and <code>value</code> into <code>ByteArrays</code> (byte arrays).</p>
<ul>
<li><code>Step 3</code>: <strong>Determine the number of partitions</strong></li>
</ul>
<p>After the <code>Serializer</code> step, the data is sent to a <code>Partitioner</code>. If a partition is specified, the <code>Partitioner</code> returns the specified partition; otherwise, the Partitioner selects a partition based on the <code>ProducerRecord key</code>.</p>
<ul>
<li><code>Step 4</code>: <strong>Brokers process the events and return results to the producers</strong></li>
</ul>
<p>Once the <code>producer</code> knows which <code>topic</code> and <code>partition</code> the event needs to be sent to, it adds the event to a batch of records. These records will then be sent together to the same topic and <code>partition</code>. An independent thread is responsible for sending these batches of records to the appropriate <code>Kafka brokers</code>.</p>
<p><code>The broker</code> sends back a response upon receiving the events. If the event is successfully written to <code>Kafka</code>, the <code>broker</code> returns an object containing <code>RecordMetadata</code>, which includes the <code>topic</code>, <code>partition</code>, and <code>offset</code> of the record within the partition. If the write is unsuccessful, the broker returns an error. When the producer receives an error, the event will be retried several times before giving up and returning an error.</p>
<h3><strong>About Apache Kafka topics</strong></h3>
<p>Topics classify messages in Kafka.  A topic is roughly analogous to a database table or folder. Topics are further subdivided into several partitions as described above</p>
<p>A single topic can be scaled horizontally across various servers to deliver performance well beyond the capabilities of a single server. <code>A Kafka cluster</code> sustains the partitioned log for each topic. Note that while a topic generally has multiple partitions, there is no assurance of message time-ordering throughout the whole topic – only within a single partition.</p>
<figure><img src="/assets/images/store/backend/kafka/kafka-topics.webp" alt="" tabindex="0" loading="lazy"><figcaption></figcaption></figure>
<h3><strong>About Apache Kafka Zookeeper</strong></h3>
<p>Zookeeper stores metadata for the <code>Kafka brokers</code>. It acts as a liaison between the broker and the consumers, enabling distributed processes to communicate with one another via a common centralized namespace of data registers called znodes.</p>
<blockquote>
<p>“ZooKeeper is a distributed, open-source coordination service for distributed applications.”</p>
<blockquote>
<p>Source: <a href="https://zookeeper.apache.org/doc/r3.9.0/zookeeperOver.html?ref=taleedevops.today" target="_blank" rel="noopener noreferrer">ZooKeeper home page</a></p>
</blockquote>
</blockquote>
<figure><img src="/assets/images/store/backend/kafka/kafka-zookeeper.webp" alt="" tabindex="0" loading="lazy"><figcaption></figcaption></figure>
<div class="hint-container note">
<p class="hint-container-title">Note</p>
<p>When it comes to production, a recommended docker image tagging method is <a href="https://semver.org/" target="_blank" rel="noopener noreferrer">semantic versioning (Semver)</a>.</p>
</div>
<p>With the introduction of <code>Apache Kafka 3.0</code>, <a href="https://cwiki.apache.org/confluence/display/KAFKA/KIP-500%3A+Replace+ZooKeeper+with+a+Self-Managed+Metadata+Quorum" target="_blank" rel="noopener noreferrer">Zookeeper is in the process of being removed</a>. Many users had complained about having to manage a separate system and the single point of failure that <code>Zookeeper</code> created.  Going forward, <code>Kafka brokers</code> will essentially assume Zookeeper’s functions, storing metadata locally in a file.  The Controller takes over registering brokers and removing failed brokers from the cluster, and upon startup the brokers just read  from the Controller what has changed, not the full state. This enables Kafka to support more partitions with less CPU consumption.</p>
<h3><strong>About queues in Apache Kafka</strong></h3>
<p>Initially Kafka was developed as a messaging queue. But it took on a life of its own, and as a result, was donated to <code>Apache</code> for further development. <code>Kafka</code> still operates like a traditional messaging queue such as <code>RabbitMQ</code>, in that it enables you to publish and subscribe to streams of messages. But comparing <a href="https://www.upsolver.com/blog/kafka-vs-jms-differences-as-message-queue-solution" target="_blank" rel="noopener noreferrer">RabbitMQ vs Kafka</a>, there are three core differences.</p>
<p><code>1.</code> Kafka operates as a modern distributed system that runs as a cluster and can scale to handle any number of applications.</p>
<p><code>2.</code> Kafka is designed to serve as a storage system and can store data as long as necessary – most message queues (like RabbitMQ) remove messages immediately after the consumer confirms receipt.</p>
<p><code>3.</code> Kafka is designed to handle stream processing, computing derived streams and datasets dynamically, rather than just in batches of messages.</p>
<h3><strong>About the Apache Kafka schema registry</strong></h3>
<p>A schema registry handles message schemas and routes them to topics. The schema registry verifies and maintains schemas implemented for <code>Kafka messages</code>. It also imposes compatibility before message addition. In this way publishers know which topics receive which forms (schemas) of events, and subscribers know how to interpret and extract information from events in a topic. The schema registry sends data serialized per schema ID so the consumer can map a schema to a message type.</p>
<p><code>Kafka</code> stores the schema’s <code>namespace</code> in the record it receives from publishers. Then the reader uses the namespace to retrieve records from the schema registry and deserialize the data.</p>
<p>The schema registry saves <code>Kafka</code> from enumerating the same schema details repeatedly into every message. <code>Producers</code> communicate with the registry and write new message schema to it.  The producer obtains the schema ID from the registry and includes that in the message.</p>
<h2>About Core Kafka Enhancements</h2>
<p>Beyond the core Kafka architecture are the following enhancements that extend the capabilities of <code>Kafka</code>. <code>Kafka Streams</code> integrates stream processing with <code>Kafka</code> and <code>Kafka Connect</code> facilitates connecting <code>Kafka</code> to external data sources and sinks.</p>
<h3><strong>What is Kafka Streams?</strong></h3>
<p><a href="https://kafka.apache.org/documentation/streams/" target="_blank" rel="noopener noreferrer">Kafka Streams</a> is an <code>API-driven</code> client library for building applications and microservices, where the input and output data are stored in <code>Kafka clusters</code>. <code>Kafka Streams jobs</code> do not execute on <code>Kafka brokers</code>; rather, they run inside your application or microservice.</p>
<p><code>Kafka Streams’</code> approach to parallel processing resembles that of <code>Kafka</code>:</p>
<ul>
<li>
<p>Each stream partition is a fully-ordered sequence of data records that maps to a <code>Kafka topic</code> partition.</p>
</li>
<li>
<p>A data record in the stream maps to a <code>Kafka</code> message from that topic.</p>
</li>
<li>
<p>The keys of data records determine the partitioning of data in both <code>Kafka</code> and <code>Kafka Streams</code> – that is, how data is routed to specific partitions within topics.</p>
</li>
</ul>
<p><code>Kafka Streams</code> processes messages in real-time (that is, not in microbatches), with millisecond latency.  It supports stateless and stateful processing and window operations.</p>
<p><code>Kafka Streams</code> includes two special processors: <code>a Source Processor</code> and a <code>Sink Processor</code>.</p>
<ul>
<li>
<p><code>The source processor</code> produces an input stream by consuming records from one or more <code>Kafka topics</code> and forwarding them to its down-stream processors.</p>
</li>
<li>
<p><code>Sink Processor</code>: A sink processor sends any received records from its up-stream processors to a specified <code>Kafka topic</code>.</p>
</li>
</ul>
<p>The processed results can either be streamed back into <code>Kafka</code> or written to an external system.</p>
<figure><img src="/assets/images/store/backend/kafka/kafka-streams.webp" alt="" tabindex="0" loading="lazy"><figcaption></figcaption></figure>
<p><code>2.</code> <strong>What are Kafka Connect and Kafka Connectors?</strong></p>
<p><code>Kafka Connect</code> provides a scalable means of moving data between Kafka and other repositories. It provides APIs and a runtime for designing and operating connector plugins, which are frameworks that <code>Kafka Connect</code> executes and are essential for data movement.</p>
<p>The connector controls:</p>
<ul>
<li>
<p>The definition and number of tasks that operate for the connector</p>
</li>
<li>
<p>How to divide the data-copying work among tasks.</p>
</li>
<li>
<p>Getting task configurations from workers and passing them on to the target.</p>
</li>
</ul>
<figure><img src="/assets/images/store/backend/kafka/kafka-connect.webp" alt="" tabindex="0" loading="lazy"><figcaption></figcaption></figure>
<p><code>3.</code> <strong>What are Kafka APIs?</strong></p>
<p><code>Kafka provides</code> five key APIs for Java, Scala, and command-line tools for management and administrative tasks. In addition, these APIs enable you to communicate with <code>Kafka</code> programmatically:</p>
<ul>
<li>
<p>The <code>Admin API</code> enables you to manage and analyze Kafka topics, brokers, Access Control Lists, and other objects.</p>
</li>
<li>
<p>The <code>Producer API</code>   enables applications to submit (write) data streams to <code>Kafka cluster</code> topics.</p>
</li>
<li>
<p>The <code>Consumer API</code> enables programs to access (read) data streams from topics in the <code>Kafka cluster</code>.</p>
</li>
<li>
<p>The <code>Streams API</code> provides stream processes that convert a data stream into an output stream.</p>
</li>
</ul>
<p>The <code>Connect API</code> creates connections that continuously draw data from a source data system into <code>Kafka</code> or push data from <code>Kafka</code> into a target data system.  (The Connect API is not often needed, as you can instead use pre-built connections without writing any code.)</p>
<h2>Advantages of Kafka</h2>
<ul>
<li>
<p><strong>Scalability</strong>: The distributed architecture of Kafka enables seamless scalability. It can handle large volumes of data and increase data throughput by adding more brokers and partitions.</p>
</li>
<li>
<p><strong>Durability</strong>: <code>Kafka</code> ensures data durability through replication. Data is replicated across multiple brokers, preventing data loss even if brokers fail. Additionally, by adhering to the Append-only commit log principle, Kafka's commit log provides data durability, fault tolerance, and efficient message processing.</p>
</li>
<li>
<p><strong>Real-time processing</strong>: <code>Kafka</code> enables real-time data transmission and processing, making it suitable for applications that require low-latency data analysis and transmission.</p>
</li>
<li>
<p><strong>Open-source</strong>: <code>Kafka</code> is open-source software, providing the freedom to modify, customize, and extend its functionality to meet specific requirements. It can be used without paying licensing fees, helping to reduce costs associated with proprietary software. <code>Kafka</code> is cross-platform and can integrate with various tools and libraries, creating a large ecosystem.</p>
</li>
<li>
<p><strong>Long polling:</strong>: Although long polling is not a built-in feature of <code>Kafka</code>, the concept can be applied to how <code>Kafka consumers</code> interact with Kafka brokers to achieve efficient data consumption.</p>
</li>
</ul>
<h2>Disadvantages of Kafka</h2>
<ul>
<li>
<p><strong>ZooKeepers dependency</strong>: In older versions of Kafka, there was a dependency on Apache ZooKeeper for cluster coordination, which added complexity and contained potential points of failure.</p>
</li>
<li>
<p><strong>Complexity</strong>: The distributed nature of <code>Kafka</code> can introduce complexity in setup, configuration, and management, requiring expertise for effective deployment and maintenance. Additionally, learning to use Kafka and its ecosystem components effectively can take time and effort, especially for users new to distributed systems.</p>
</li>
<li>
<p><strong>Resource requirement</strong>: Managing Kafka clusters requires significant hardware resources, including memory, storage capacity, and network bandwidth.</p>
</li>
</ul>
<div class="hint-container important">
<p class="hint-container-title">Important</p>
<p>Kafka Architecture: Key Takeaways</p>
<blockquote>
<ul>
<li>
<p>Apache Kafka is an open-source stream-processing software platform that helps deliver real-time data feeds to applications.</p>
</li>
<li>
<p>Kafka stores data durably, distributes it across a cluster of nodes, and replicates partitions and replicas to ensure data consistency and resilience to failures.</p>
</li>
<li>
<p>Kafka provides log aggregation, stream processing, commit logs, and clickstream tracking.</p>
</li>
<li>
<p>Kafka is comprised of brokers, controllers, partitions, consumers, producers, topics, schema registries, and Zookeeper (phasing out).</p>
</li>
<li>
<p>Consumers and producers interact with topics, and Kafka Streams provides stream processing.</p>
</li>
</ul>
</blockquote>
</div>
<h2>Conclusion</h2>
<p><code>Apache Kafka</code> has redefined how organizations handle data streaming and event processing. Its distributed architecture, fault tolerance, and scalability make Kafka a powerful tool for managing the challenges of real-time data. From collecting and analyzing user interactions to building event-driven applications, Kafka's capabilities are vast and impactful.</p>
]]></content:encoded>
      <enclosure url="https://blog.taleedevops.today/assets/images/store/backend/kafka/title.jpg" type="image/jpeg"/>
    </item>
    <item>
      <title>How to run Oracle Database in a Docker Container using Docker Compose</title>
      <link>https://blog.taleedevops.today/database/oracle/run-oracle-database-docker-container.html</link>
      <guid>https://blog.taleedevops.today/database/oracle/run-oracle-database-docker-container.html</guid>
      <source url="https://blog.taleedevops.today/rss.xml">How to run Oracle Database in a Docker Container using Docker Compose</source>
      <description>Run Oracle Database in Docker with Docker Compose — pulling from Oracle Container Registry, the prerequisites, and the compose file that works.</description>
      <category>backend</category>
      <category>database</category>
      <category>devops</category>
      <pubDate>Sun, 28 Jul 2024 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[
<p><a href="http://container-registry.oracle.com/" target="_blank" rel="noopener noreferrer">Oracle Container Registry</a> (OCR) is a private container registry provided by Oracle Corporation that allows users to store, distribute, and manage container images.<code>OCR</code> is built on the <code>Oracle Cloud Infrastructure</code> and enables users to store, manage and distribute container images in a secure, reliable and scalable way. It is designed to work with the Oracle Cloud Infrastructure Container Engine for <code>Kubernetes</code> (OKE), <code>Oracle Cloud Infrastructure Registry</code> (OCIR), and other <code>Oracle Cloud Infrastructure</code> services.</p>
<p><code>Oracle Container Registry</code> (OCR) is a fully-managed, enterprise-grade registry for storing and distributing container images on <code>Oracle</code>. Users can use <code>OCR</code> to store their own custom images, as well as pull down official images provided by <code>Oracle</code>. <code>OCR</code> supports both the <code>Docker</code> and <code>OCI</code> image formats and also provides features such as image scanning, image promotion and versioning, and image access control. Users can use the <code>Oracle Cloud Infrastructure Console</code>, <code>Oracle Cloud Infrastructure CLI</code>, or the <code>Oracle Cloud Infrastructure</code> SDK to interact with <code>OCR</code>.</p>
<h1>Why to run Oracle database in a Docker Container?</h1>
<p>There are several reasons why one might choose to run an <code>Oracle database</code> in a <code>Docker container</code>:</p>
<ul>
<li>
<p><strong>Portability</strong>: <code>Docker containers</code> can be easily moved between environments, making it easy to deploy the database in different environments such as development, testing, and production.</p>
</li>
<li>
<p><strong>Isolation</strong>: Running the database in a container can help to isolate it from the host system, reducing the risk of conflicts with other software running on the same machine.</p>
</li>
<li>
<p><strong>Consistency</strong>: By packaging the database and its dependencies in a container, it ensures that the database will always run the same way, regardless of the environment in which it is deployed.</p>
</li>
<li>
<p><strong>Scalability</strong>: Containers can be easily scaled up or down as needed, making it easy to handle changes in load.</p>
</li>
<li>
<p><strong>Cost Savings</strong>: <code>Docker containers</code> can be run on-premises or in the cloud, allowing you to take advantage of cloud-based services while avoiding the costs of virtualization.</p>
</li>
</ul>
<p>In this blog, you will see how you can use <code>Docker</code> to run Oracle Database in a <code>Docker container</code></p>
<h1>Getting Started</h1>
<h2>Pre-requisite</h2>
<ul>
<li><a href="https://www.docker.com/" target="_blank" rel="noopener noreferrer">Download and Install Docker</a></li>
</ul>
<ol>
<li>Visit <a href="https://container-registry.oracle.com" target="_blank" rel="noopener noreferrer">Container Registry Oracle</a> and create your new account</li>
</ol>
<figure><img src="/assets/images/store/database/oracle/oracle-registry.webp" alt="" tabindex="0" loading="lazy"><figcaption></figcaption></figure>
<ol start="2">
<li>Select <code>Enterprise</code></li>
</ol>
<figure><img src="/assets/images/store/database/oracle/oracle-registry-v2.webp" alt="" tabindex="0" loading="lazy"><figcaption></figcaption></figure>
<ol start="3">
<li>Click <code>Sign In</code></li>
</ol>
<figure><img src="/assets/images/store/database/oracle/oracle-registry-v3.webp" alt="" tabindex="0" loading="lazy"><figcaption></figcaption></figure>
<ol start="4">
<li>Authenticate by entering your registered <code>Email ID</code> and <code>Password</code></li>
</ol>
<figure><img src="/assets/images/store/database/oracle/oracle-registry-v4.webp" alt="" tabindex="0" loading="lazy"><figcaption></figcaption></figure>
<ol start="5">
<li>After successful authentication, navigate to the Database section and select the desired <code>Oracle Database</code> version.</li>
</ol>
<figure><img src="/assets/images/store/database/oracle/oracle-registry-v5.webp" alt="" tabindex="0" loading="lazy"><figcaption></figcaption></figure>
<ol start="6">
<li>Accept the license agreement to proceed with downloading the <code>Oracle Database</code> Docker image.</li>
</ol>
<figure><img src="/assets/images/store/database/oracle/oracle-registry-v6.webp" alt="" tabindex="0" loading="lazy"><figcaption></figcaption></figure>
<ol start="7">
<li>Accept the License and test if the docker login is working fine or not.</li>
</ol>
<div class="language-bash line-numbers-mode" data-highlighter="shiki" data-ext="bash" data-title="bash" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> login</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> container-registry.oracle.com</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">Username:</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> xxx</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">Password:</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> xxx</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">Login</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> Succeeded</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code>Oracle Database</code> can be run in a <code>Docker container</code>, using the official Oracle Database Docker image. To deploy an <code>Oracle Database</code> using Docker, you will need to:</p>
<ul>
<li>
<p>Install <code>Docker</code> on your machine.</p>
</li>
<li>
<p>Pull the <code>Oracle Database</code> Docker image using the command:</p>
</li>
</ul>
<ol start="8">
<li>Open a terminal on your local machine and execute the <code>Docker pull</code> command to download the <code>Oracle Database</code> image. For example:</li>
</ol>
<div class="language-bash line-numbers-mode" data-highlighter="shiki" data-ext="bash" data-title="bash" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> pull</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> container-registry.oracle.com/database/enterprise:21.3.0.0</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><ol start="9">
<li>Verify the image is downloaded successfully by running:</li>
</ol>
<div class="language-bash line-numbers-mode" data-highlighter="shiki" data-ext="bash" data-title="bash" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> images</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>You should see the <code>Oracle Database</code> image listed among the downloaded images.</p>
<ol start="10">
<li>Create a new container using the command:</li>
</ol>
<div class="language-bash line-numbers-mode" data-highlighter="shiki" data-ext="bash" data-title="bash" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> run</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66"> -d</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66"> --name</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> oracle-db</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66"> -p</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> 1521:1521</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> container-registry.oracle.com/database/enterprise:21.3.0.0</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>Once the container is up and running, you can connect to the Oracle Database using any SQL client, such as <code>SQL*Plus</code>, with the connection string <code>hostname:1521/orclpdb1</code></p>
<p>The above command creates a new container with the name <code>oracle-db</code> and maps the host’s port <code>1521</code> to the container’s port <code>1521</code>. The orclpdb1 is the default service name for the <code>Oracle Database</code>.</p>
<p>You can also customize the container by providing environment variables and volumes. For example, to set the <code>SYS</code> and <code>SYSTEM</code> password, you can use the following command</p>
<div class="language-bash line-numbers-mode" data-highlighter="shiki" data-ext="bash" data-title="bash" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> docker</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> run</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66"> -d</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66"> --name</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> oracle-db</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66"> -p</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> 1521:1521</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66"> -e</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> ORACLE_PWD=</span><span style="--shiki-light:#D73A49;--shiki-dark:#ABB2BF">&lt;</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">passwor</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">d</span><span style="--shiki-light:#D73A49;--shiki-dark:#ABB2BF">&gt;</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> container-registry.oracle.com/database/enterprise:21.3.0.0</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><div class="hint-container note">
<p class="hint-container-title">Note</p>
<p>The above command will start the Oracle Database with default settings and configurations. It is recommended to refer to the official Oracle Database documentation and also to Oracle’s licensing policy &gt; before deploying in production.</p>
</div>
<h2>Using Docker Compose</h2>
<p>Create a <code>docker-compose.yml</code> file to define the <code>Oracle Database</code> service. Here is an example:</p>
<div class="language-bash line-numbers-mode" data-highlighter="shiki" data-ext="bash" data-title="bash" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">version:</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> '3.8'</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">services:</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">  oracle-db:</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">    image:</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> container-registry.oracle.com/database/enterprise:21.3.0.0</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">    environment:</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">      -</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> ORACLE_SID=ORCLCDB</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">      -</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> ORACLE_PDB=ORCLPDB1</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">      -</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> ORACLE_PWD=Oracle_123</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">    ports:</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">      -</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> 1521:1521</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">    volumes:</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">      -</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> oracle-data:/opt/oracle/oradata</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">      -</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> oracle-backup:/opt/oracle/backup</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">    healthcheck:</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#56B6C2">      test</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">:</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> [</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">"CMD"</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">"sqlplus",</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> "-L",</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> "sys/Oracle_123@//localhost:1521/ORCLCDB as sysdba",</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> "@healthcheck.sql"]</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">      interval:</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> 30s</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">      timeout:</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> 10s</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">      retries:</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66"> 5</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">volumes:</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">  oracle-data:</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">  oracle-backup:</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>This <code>docker-compose.yml</code> file uses the official Oracle database image from the Oracle Container registry and sets several environment variables for the container, including the <code>ORACLE_SID</code>, <code>ORACLE_PDB</code>, and <code>ORACLE_PWD</code>.</p>
<p>It also maps port <code>1521</code> on the host to port <code>1521</code> in the container, so that the database can be accessed from outside of the container.</p>
<p>It also creates two volumes <code>oracle-data</code> and <code>oracle-backup</code> to store the data and backup files respectively.</p>
<p>It also has a health check to check for the availability of the DB.</p>
<p>Don’t forget to replace the values of <code>ORACLE_PWD</code> with your desired password. Also, you should adjust the volumes and ports to match your specific requirements. The above example uses <code>SQLPlus</code> to check the health of the database, you can customise it accordingly.</p>
<h1>Conclusion</h1>
<p>You have successfully set up and run an <code>Oracle Database</code> in a <code>Docker container</code> using <code>Docker Compose</code>. This setup allows for easy management, portability, and scalability of your <code>Oracle Database</code> instances. Remember to follow best practices for security and resource management in a production environment.</p>
]]></content:encoded>
      <enclosure url="https://blog.taleedevops.today/assets/images/store/database/oracle/title.jpg" type="image/jpeg"/>
    </item>
    <item>
      <title>Everything you should know about Microservices</title>
      <link>https://blog.taleedevops.today/backend/microservice/1.html</link>
      <guid>https://blog.taleedevops.today/backend/microservice/1.html</guid>
      <source url="https://blog.taleedevops.today/rss.xml">Everything you should know about Microservices</source>
      <description>What microservices are and how they differ from a monolith: loosely coupled services, independent failure, and the trade-offs that come with them.</description>
      <category>microservice</category>
      <pubDate>Sun, 23 Jun 2024 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[
<p>Microservices, also known as the microservice architecture, is an architectural style that structures an application as a collection of loosely coupled services. This approach allows for more flexible, scalable, and manageable applications.</p>
<p>In a monolithic architecture, all software components are interconnected and interdependent. If any component or single application’s function fails, the complete application could go down. Imagine you have a web application including functions like payment, history, and log in. If “history” function consumes more memory, the entire application would have to experience the same issue.</p>
<p>Unlike monolithic architecture, microservices break the large software projects into independent, loosely coupled, and smaller modules. In Microservices, the small programs are combined to deliver the functionalities of a large monolithic app</p>
<p>Read further to understand what exactly microservices are, its benefits and challenges associated with it and what can be done to overcome the challenges</p>
]]></content:encoded>
      <enclosure url="https://blog.taleedevops.today/assets/images/backend/microservice/backend_microservice_1_v1.jpg" type="image/jpeg"/>
    </item>
    <item>
      <title>A Step-by-Step guide to Build and Push Your Own Docker Images to DockerHub</title>
      <link>https://blog.taleedevops.today/devops/docker/guide-build-push-images-dockerhub.html</link>
      <guid>https://blog.taleedevops.today/devops/docker/guide-build-push-images-dockerhub.html</guid>
      <source url="https://blog.taleedevops.today/rss.xml">A Step-by-Step guide to Build and Push Your Own Docker Images to DockerHub</source>
      <description>Write a Dockerfile, build an image, run it as a container and push it to Docker Hub — a full NGINX example with every command and its output.</description>
      <category>docker</category>
      <pubDate>Sun, 14 Jul 2024 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[
<p>In this article, you will learn to build a <code>Docker image</code> from scratch and deploy and run your application as a <code>Docker container</code> using <code>Dockerfile</code></p>
<p>As you know <code>Docker</code> is a tool for packaging, deploying, and running applications in lightweight <a href="https://taleedevops.today/devops/docker/introduction-to-containers.html" target="_blank" rel="noopener noreferrer">containers</a>. If you want to learn about the basics of <code>Docker</code>, refer to the <a href="https://taleedevops.today/devops/docker/introduction-to-docker.html" target="_blank" rel="noopener noreferrer">Docker explained</a> blog.</p>
<p>If you don’t have <code>Docker installation</code>, check out the <a href="https://taleedevops.today/devops/docker/how-to-Install-docker.html" target="_blank" rel="noopener noreferrer">docker installation</a> guide.</p>
<h2>Dockerfile Explained</h2>
<p>A <code>Dockerfile</code> is a script that automatically creates <code>containers</code> on the <code>Docker platform</code>. A <code>Dockerfile</code> is basically a text document that contains all the commands a user could call on the command line to assemble an image.</p>
<p>The <code>Docker platform</code> runs natively on <code>Linux</code> and allows developers to build and run <code>containers</code>, self-contained applications or systems with no dependencies on the underlying infrastructure. Built upon the resource-isolation features of the <code>Linux kernel</code>, <code>Docker</code> helps developers and system administrators port applications across different systems and machines by running them inside <code>containers</code>.</p>
<p><code>Dockerfiles</code> enable greater flexibility and portability of business applications. IT organizations use <code>Dockerfiles</code> to package applications and their dependencies in a virtual container that can run on premises. In public or private clouds, or on bare metal. Such containers allow multiple applications, worker tasks and other processes to run autonomously on a single physical machine or across multiple virtual machines. <code>Kubernetes</code> is an open source system for automatically managing and orchestrating <code>containerized applications</code> created by <code>Dockerfiles</code>.</p>
<p>In a <code>Dockerfile</code> everything on the left is <code>INSTRUCTION</code>, and on the right is an <code>ARGUMENT</code> to those instructions. Remember that the file name is <code>"Dockerfile"</code> without any extension.</p>
<figure><img src="/assets/images/store/devops/docker/guide-build-push-images-dockerhub/dockerfile-node.webp" alt="Example Dockerfile" tabindex="0" loading="lazy"><figcaption>Example Dockerfile</figcaption></figure>
<p>The following table contains the important <code>Dockerfile</code> instructions and their explanation.</p>
<p>| Dockerfile Instruction | Explanation |
|</p>
]]></content:encoded>
      <enclosure url="https://blog.taleedevops.today/assets/images/store/devops/docker/guide-build-push-images-dockerhub/title.jpg" type="image/jpeg"/>
    </item>
    <item>
      <title>How to Install Docker: A Step-By-Step Guide</title>
      <link>https://blog.taleedevops.today/devops/docker/how-to-Install-docker.html</link>
      <guid>https://blog.taleedevops.today/devops/docker/how-to-Install-docker.html</guid>
      <source url="https://blog.taleedevops.today/rss.xml">How to Install Docker: A Step-By-Step Guide</source>
      <description>Install Docker on Ubuntu from the apt repository, plus a one-liner for the latest release and how to run docker commands without sudo.</description>
      <category>docker</category>
      <pubDate>Thu, 11 Jul 2024 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[
<p>In this article, we will explain how to install Docker on a Ubuntu and a one-liner command to install the latest version of Docker.</p>
<p>Before installing <code>docker</code> on <code>ubuntu</code>, if you want to learn <code>docker</code> basics, head over to this article – <a href="https://taleedevops.today/devops/docker/introduction-to-docker.html" target="_blank" rel="noopener noreferrer">What is docker</a></p>
<p><code>Docker</code> supports almost all <code>Unix</code> and <code>Linux distributions</code>. Getting started with <code>Docker</code> is very easy. There is no complicated configuration for <code>Docker</code>.</p>
<h2>Install Docker on Ubuntu</h2>
<p>We will look at two methods to install <code>Docker</code>.</p>
<ol>
<li>
<p>Install <code>Docker</code> from apt repository</p>
</li>
<li>
<p>Install <code>Docker</code> using one line command.</p>
</li>
</ol>
<h3>Install Docker From apt Repository</h3>
<p><code>Docker</code> package is available in the native apt repository. The installation package available in the repository will not be the latest version. If you want to install the latest release of <code>Docker</code>, you need to install it from the source.</p>
<p>Follow the instructions given below to install <code>docker</code> from the apt repository.</p>
<ol>
<li>Set up <code>Docker's</code> apt repository.</li>
</ol>
<div class="language-bash line-numbers-mode" data-highlighter="shiki" data-ext="bash" data-title="bash" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#7F848E;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic"># Add Docker's official GPG key:</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">sudo</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> apt-get</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> update</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">sudo</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> apt-get</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> install</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> ca-certificates</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> curl</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">sudo</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> install</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66"> -m</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66"> 0755</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66"> -d</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> /etc/apt/keyrings</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">sudo</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> curl</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66"> -fsSL</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> https://download.docker.com/linux/ubuntu/gpg</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66"> -o</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> /etc/apt/keyrings/docker.asc</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">sudo</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> chmod</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> a+r</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> /etc/apt/keyrings/docker.asc</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#7F848E;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic"># Add the repository to Apt sources:</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#56B6C2">echo</span><span style="--shiki-light:#005CC5;--shiki-dark:#56B6C2"> \</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#98C379">  "deb [arch=$(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">dpkg</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66"> --print-architecture</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu </span><span style="--shiki-light:#005CC5;--shiki-dark:#56B6C2">\</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#98C379">  $(</span><span style="--shiki-light:#005CC5;--shiki-dark:#56B6C2">.</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> /etc/os-release &amp;&amp; </span><span style="--shiki-light:#005CC5;--shiki-dark:#56B6C2">echo</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> "</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">$VERSION_CODENAME</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">") stable"</span><span style="--shiki-light:#D73A49;--shiki-dark:#ABB2BF"> |</span><span style="--shiki-light:#005CC5;--shiki-dark:#56B6C2"> \</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">  sudo</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> tee</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> /etc/apt/sources.list.d/docker.list</span><span style="--shiki-light:#D73A49;--shiki-dark:#ABB2BF"> &gt;</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> /dev/null</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">sudo</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> apt-get</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> update</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><figure><img src="/assets/images/store/devops/docker/install-docker/update-the-apt-cache.webp" alt="" tabindex="0" loading="lazy"><figcaption></figcaption></figure>
<ol start="2">
<li>Install the <code>Docker</code> packages.</li>
</ol>

<ol start="3">
<li>Verify that the <code>Docker Engine</code> installation is successful by running the <code>hello-world</code> image.</li>
</ol>
<div class="language-bash line-numbers-mode" data-highlighter="shiki" data-ext="bash" data-title="bash" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">sudo</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> docker</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> run</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> hello-world</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>This command downloads a test image and runs it in a <code>container</code>. When the <code>container</code> runs, it prints a confirmation message and exits.</p>
<div class="hint-container tip">
<p class="hint-container-title">Tips</p>
<p>Receiving errors when trying to run without <code>root</code>?
The <code>docker</code> user group exists but contains no users, which is why you’re required to use sudo to run <code>Docker</code> commands. Continue to <code>Linux</code> postinstall to allow non-privileged users to run <code>Docker</code> commands and for other optional configuration steps.</p>
</div>
<h3>Installing the latest Docker release [One Liner]</h3>
<p>If you are trying out <code>Docker</code> or using it for test purposes, you can use a <code>one-liner</code> command to install <code>Docker</code>.</p>
<p>To install the latest <code>docker</code> release just execute the following curl command.</p>
<div class="language-bash line-numbers-mode" data-highlighter="shiki" data-ext="bash" data-title="bash" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">curl</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66"> -sSL</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> https://get.docker.com/</span><span style="--shiki-light:#D73A49;--shiki-dark:#ABB2BF"> |</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> sudo</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> sh</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h3>Run Docker Commands Without Sudo</h3>
<p>If you try to run <code>Docker</code> without sudo as a normal user, you will get the following error.</p>
<div class="language-bash line-numbers-mode" data-highlighter="shiki" data-ext="bash" data-title="bash" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">Got</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> permission</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> denied</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> while</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> trying</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> to</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> connect</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> to</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> the</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> Docker</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> daemon</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> socket</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> at</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> unix:///var/run/docker.sock:</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><figure><img src="/assets/images/store/devops/docker/install-docker/docker-permission-denied.webp" alt="permission denied" tabindex="0" loading="lazy"><figcaption>permission denied</figcaption></figure>
<p>To <code>docker</code> commands without using sudo, you need to add the system user to the <code>Docker</code> group.</p>
<p>Here is the command to add the current user to the <code>docker group</code>.</p>
<div class="language-bash line-numbers-mode" data-highlighter="shiki" data-ext="bash" data-title="bash" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">sudo</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> usermod</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66"> -aG</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> docker</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75"> $USER</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">newgrp</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> docker</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p>Exit the current terminal and log in again to use the docker commands without <code>sudo</code>.</p>
<h2>Working with Docker on Ubuntu</h2>
<p>To test the docker installation on <code>Ubuntu</code>, let’s go through some of the basic <code>docker</code> operations.</p>
<h3>Pull a Docker Base Image</h3>
<p>Now we have <code>docker</code> installed on the host. Let’s try to pull the latest <code>ubuntu</code> base image from the docker hub using the following docker command.</p>
<div class="language-bash line-numbers-mode" data-highlighter="shiki" data-ext="bash" data-title="bash" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">sudo</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> docker</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> pull</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> ubuntu:latest</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><figure><img src="/assets/images/store/devops/docker/install-docker/docker-pull-ubuntu-images.webp" alt="docker pull" tabindex="0" loading="lazy"><figcaption>docker pull</figcaption></figure>
<p>Verify the downloaded image using the following <code>docker</code> command. It will list all the downloaded and created images in the local repository.</p>
<div class="language-bash line-numbers-mode" data-highlighter="shiki" data-ext="bash" data-title="bash" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">sudo</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> docker</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> images</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>To check if <code>Docker</code> is enabled on boot, execute the following command.</p>
<figure><img src="/assets/images/store/devops/docker/install-docker/docker-ps.webp" alt="docker ps" tabindex="0" loading="lazy"><figcaption>docker ps</figcaption></figure>
<div class="language-bash line-numbers-mode" data-highlighter="shiki" data-ext="bash" data-title="bash" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">sudo</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> systemctl</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> list-unit-files</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66"> --type=service</span><span style="--shiki-light:#D73A49;--shiki-dark:#ABB2BF"> |</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> grep</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> docker.service</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><figure><img src="/assets/images/store/devops/docker/install-docker/check-docker-enabled.webp" alt="docker service" tabindex="0" loading="lazy"><figcaption>docker service</figcaption></figure>
<h3>Run a Docker Container</h3>
<p>Now we have the latest ubuntu <code>docker image</code> in our host. Let’s create an interactive container named “test” from the <code>ubuntu image</code> using the following command.</p>
<div class="language-bash line-numbers-mode" data-highlighter="shiki" data-ext="bash" data-title="bash" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">sudo</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> docker</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> run</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66"> -i</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66"> -t</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66"> --name</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> test</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> ubuntu:latest</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><figure><img src="/assets/images/store/devops/docker/install-docker/docker-run.webp" alt="docker run" tabindex="0" loading="lazy"><figcaption>docker run</figcaption></figure>
<p>The above command will create an interactive <code>container</code> with a bash shell. You can try installing some packages in that <code>container</code>.</p>
<div class="hint-container note">
<p class="hint-container-title">Note</p>
<p>You can also create a container without having an image in the local repository. When you execute the “docker run” command, docker will look for the base image in the local system respository. If it
doesn’t find any, docker will automatically pull down the image from the docker hub.</p>
</div>
<p>Type <code>“exit”</code> to exit the <code>container</code>. When you exit, the container will stop. You can view all the stopped and running <code>containers</code> using the following command.</p>
<div class="language-bash line-numbers-mode" data-highlighter="shiki" data-ext="bash" data-title="bash" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">sudo</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> docker</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> ps</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66"> -a</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><figure><img src="/assets/images/store/devops/docker/install-docker/docker-ps-a.webp" alt="view container exited" tabindex="0" loading="lazy"><figcaption>view container exited</figcaption></figure>
<h2>Uninstallaing Docker from Ubuntu</h2>
<p>To uninstall <code>Docker</code>, execute the following command.</p>
<div class="language-bash line-numbers-mode" data-highlighter="shiki" data-ext="bash" data-title="bash" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">sudo</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> apt-get</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> purge</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> docker-ce</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> docker-ce-cli</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> containerd.io</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h2>Important Docker Configurations on Ubuntu</h2>
<ul>
<li>To check all the important configurations of <code>Docker</code> on host, execute the following command.</li>
</ul>
<div class="language-bash line-numbers-mode" data-highlighter="shiki" data-ext="bash" data-title="bash" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> info</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><ul>
<li>All the containers are stored in the following location</li>
</ul>
<div class="language-bash line-numbers-mode" data-highlighter="shiki" data-ext="bash" data-title="bash" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">/var/lib/docker/containers</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><ul>
<li>If you want to add <code>custom DNS servers for Docker</code>, create the following file.</li>
</ul>
<div class="language-bash line-numbers-mode" data-highlighter="shiki" data-ext="bash" data-title="bash" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">vi</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> /etc/docker/daemon.json</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>Add the <code>DNS servers</code> in the following format.</p>
<div class="language-json line-numbers-mode" data-highlighter="shiki" data-ext="json" data-title="json" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">}</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#98C379">  "dns"</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">: [</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">"8.8.8.8"</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">"8.8.4.4"</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">]</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2>Enable Docker Remote API Access</h2>
<p>By default, the docker client communicates with the <code>docker daemon</code> using the Unix socket <code>docker.sock</code>. If you want to accept connections from a remote <code>docker client</code>, you need to start the <code>docker daemon</code> on a specific port.</p>
<p>Follow the instructions given below to start the <code>docker daemon</code> on a particular port.</p>
<p>Step 1: Stop the docker service using the following command.</p>
<div class="language-bash line-numbers-mode" data-highlighter="shiki" data-ext="bash" data-title="bash" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">sudo</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> service</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> docker</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> stop</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>Step 2: Replace the following line in <code>/lib/systemd/system/docker.service</code> file to start the <code>docker daemon</code> on the port <code>5000</code> for client connections from all IP addresses. If you to establish a connection from a particular host, then you can mention that IP address instead of <code>"0.0.0.0"</code></p>
<div class="language-bash line-numbers-mode" data-highlighter="shiki" data-ext="bash" data-title="bash" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">ExecStart</span><span style="--shiki-light:#D73A49;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">/usr/bin/dockerd</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> -H</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> tcp://0.0.0.0:5000</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66"> -H</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> unix:///var/run/docker.sock</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>Step 3: Reload and restart <code>docker</code>.</p>
<div class="language-bash line-numbers-mode" data-highlighter="shiki" data-ext="bash" data-title="bash" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">sudo</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> systemctl</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> daemon-reload</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">sudo</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> service</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> docker</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> restart</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p>Now you will be able to run <code>docker</code> commands from the host as well as from a remote <code>docker client</code>. To run the docker commands from a remote client, use the following syntax.</p>
<div class="language-bash line-numbers-mode" data-highlighter="shiki" data-ext="bash" data-title="bash" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">docker</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66"> -H</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> tcp://</span><span style="--shiki-light:#D73A49;--shiki-dark:#ABB2BF">&lt;</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">ip-address-of-host-running-docker-daemo</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">n</span><span style="--shiki-light:#D73A49;--shiki-dark:#ABB2BF">&gt;</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">:5000</span><span style="--shiki-light:#D73A49;--shiki-dark:#ABB2BF"> &lt;</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">docker-comman</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">d</span><span style="--shiki-light:#D73A49;--shiki-dark:#ABB2BF">&gt;</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h2>Conclusion</h2>
<p>In this post, we have learned to install <code>docker on Ubuntu</code> and we created a basic container from a docker <code>Ubuntu image</code>.</p>
<p>Also, we learned how to set up client connections for the <code>docker daemon</code>.</p>
]]></content:encoded>
      <enclosure url="https://blog.taleedevops.today/assets/images/store/devops/docker/install-docker/install-docker.jpg" type="image/jpeg"/>
    </item>
    <item>
      <title>How To Reduce Docker Image Size</title>
      <link>https://blog.taleedevops.today/devops/docker/how-to-reduce-docker-image-size.html</link>
      <guid>https://blog.taleedevops.today/devops/docker/how-to-reduce-docker-image-size.html</guid>
      <source url="https://blog.taleedevops.today/rss.xml">How To Reduce Docker Image Size</source>
      <description>Practical ways to shrink a Docker image: minimal base images, multistage builds, fewer layers — with before-and-after sizes for each method.</description>
      <category>docker</category>
      <pubDate>Mon, 15 Jul 2024 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[
<p>This blog talks about different optimization techniques that you can quickly implement to make the smallest and <code>minimal docker image</code>. We will also look at some of the <code>best tools for Docker Image Optimization</code>.</p>
<p><a href="https://taleedevops.today/devops/docker/introduction-to-docker.html" target="_blank" rel="noopener noreferrer">Docker</a> as a container engine makes it easy to take a piece of code &amp; run it inside a container. It enables engineers to collect all the code dependencies and files into a single location which can be run anywhere, quite quickly &amp; easily.</p>
<p>The whole concept of <code>“run anywhere”</code> images starts from a simple configuration file called <code>Dockerfile</code>. First, we add all the build instructions, such as the code dependencies, commands, and base image details, in <code>Dockerfile</code>.</p>
<h2>Need for Docker Image Optimization</h2>
<figure><img src="/assets/images/store/devops/docker/how-to-reduce-docker-image-size/need-for-docker-image-optimization.webp" alt="" tabindex="0" loading="lazy"><figcaption></figcaption></figure>
<p>Even though the <code>Docker</code> build process is easy, many organizations make the mistake of building <code>bloated Docker images</code> without optimizing the container images.</p>
<p>In typical software development, each service will have multiple versions/releases, and each version requires more dependencies, commands, and configs. This introduces a challenge in <code>Docker image</code> build, as now – the same code requires more time &amp; resources to be built before it can be shipped as a container.</p>
<p>Also, by installing unwanted libraries, we increase the chance of a <code>potential security risk</code> by increasing the attack surface.</p>
<p>Therefore, your <code>Docker image</code> size matters for reasons such as:</p>
<ul>
<li>
<p>Faster deployments time to download, transfer and load into the container runtime, and improved team productivity and application performance.</p>
</li>
<li>
<p>Better storage utilization on your machine.</p>
</li>
<li>
<p>Reduced network bandwidth when transferring between <code>hosts</code> and <code>container</code> orchestration environments.</p>
</li>
<li>
<p>Reducing image size and removing unnecessary files eliminate vulnerable components that expose images to security issues.</p>
</li>
<li>
<p>Build and portability efficiency speeds up the build processes and improves resource usage.</p>
</li>
<li>
<p><strong><code>From the cloud perspective</code></strong>, smaller images can be uploaded to the cloud easily and are easy to maintain. Public cloud providers follow pay-as-you-go costing. To get the benefit one needs to minimize the image. From the <code>Kubernetes</code> perspective, The smaller the size of the image the faster the pod starts.</p>
</li>
</ul>
<h2>How to Reduce Docker Image Size?</h2>
<p>If we take a container image of a typical application, it contains a base image, <code>Dependencies/Files/Configs</code>, and <code>cruft</code> (unwanted software)</p>
<figure><img src="/assets/images/store/devops/docker/how-to-reduce-docker-image-size/dockerfile-app.webp" alt="" tabindex="0" loading="lazy"><figcaption></figcaption></figure>
<p>So it all boils down to how efficiently we can manage these resources inside the <code>container image</code>.</p>
<p>Let’s look at different <strong><code>established methods of optimizing Docker images</code></strong>. Additionally, we have given practical examples to understand <code>docker image</code> optimization in real time.</p>
<p>Either you use the examples given in the article or try the optimization techniques on existing <code>Dockerfiles</code>.</p>
<p>The following are the methods by which we can achieve docker image optimization:</p>
<p><code>1.</code> <strong>Using distroless/minimal base images</strong></p>
<p><code>2.</code> <strong>Multistage builds</strong></p>
<p><code>3.</code> <strong>Minimizing the number of layers</strong></p>
<p><code>4.</code> <strong>Understanding caching</strong></p>
<p><code>5.</code> <strong>Using Dockerignore</strong></p>
<p><code>6.</code> <strong>Keeping application data elsewhere</strong></p>
<p><code>7.</code> <strong>Do not Install Unnecessary Packages</strong></p>
<p><code>8.</code> <strong>After Installation Do The Clean-Up</strong></p>
<p><code>9.</code> <strong>Use docker --squash flag at build time</strong></p>
<p><code>10.</code> <strong>Do not Install Editors Using Dockerfile</strong></p>
<h3>Method 1: Use Minimal Base Images</h3>
<p>Your first focus should be on choosing the right base image with a minimal <code>OS</code> footprint. Selecting a smaller base image can significantly reduce the size of your final <code>Docker image</code>, which leads to faster deployment times and reduced attack surface.</p>
<p>| Registry                     | Base Images                                                                                                                                                                                                                                                |
|</p>
]]></content:encoded>
      <enclosure url="https://blog.taleedevops.today/assets/images/store/devops/docker/how-to-reduce-docker-image-size/how-to-reduce-docker-image-size.jpg" type="image/jpeg"/>
    </item>
    <item>
      <title>Introduction To Containers</title>
      <link>https://blog.taleedevops.today/devops/docker/introduction-to-containers.html</link>
      <guid>https://blog.taleedevops.today/devops/docker/introduction-to-containers.html</guid>
      <source url="https://blog.taleedevops.today/rss.xml">Introduction To Containers</source>
      <description>Containers versus virtual machines, explained from what each one actually virtualises — and why that makes containers lightweight.</description>
      <category>docker</category>
      <pubDate>Sun, 07 Jul 2024 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[
<p>If you’re a programmer or techie, chances are you’ve at least heard of <code>Docker</code>: a helpful tool for packing, shipping, and running applications within <code>“containers.”</code>. It’d be hard not to, with all the attention it’s getting these days — from developers and system admins alike. Even the big dogs like <code>Google</code>, <code>VMware</code> and <code>Amazon</code> are building services to support it. Regardless of whether or not you have an immediate use-case in mind for <code>Docker</code>, I still think it’s important to understand some of the fundamental concepts around what a <code>“container”</code> is and how it compares to a <code>Virtual Machine (VM)</code>.</p>
<p>Let’s start by understanding what <code>VMs</code> and <code>containers</code> even are.</p>
<h2>What are “containers” and “VMs”?</h2>
<figure><img src="/assets/images/devops/docker/introduction_to_containers/containers_vms.webp" alt="" tabindex="0" loading="lazy"><figcaption></figcaption></figure>
<p><code>Containers</code> and <code>VMs</code> are similar in their goals: to isolate an application and its dependencies into a self-contained unit that can run anywhere.</p>
<p>Moreover, <code>containers</code> and <code>VMs</code> remove the need for physical hardware, allowing for more efficient use of computing resources, both in terms of energy consumption and cost effectiveness.</p>
<p>The main difference between <code>containers</code> and <code>VMs</code> is in their architectural approach. Let’s take a closer look.</p>
<h2>Virtual Machines</h2>
<p><code>A VM</code> is essentially an emulation of a real computer that executes programs like a real computer. <code>VMs</code> run on top of a physical machine using a <code>“hypervisor”</code>. <code>A hypervisor</code>, in turn, runs on either a host machine or on <code>“bare-metal”</code>.</p>
<p><code>A Hypervisor</code> is a piece of software, firmware, or hardware that <code>VMs</code> run on top of. The <code>hypervisors</code> themselves run on physical computers, referred to as the <code>“host machine”</code>. The <code>host machine</code> provides the <code>VMs</code> with resources, including RAM and CPU. These resources are divided between <code>VMs</code> and can be distributed as you see fit. So if one <code>VM</code> is running a more resource heavy application, you might allocate more resources to that one than the other VMs running on the same <code>host machine</code>.</p>
<p><code>The VM</code> that is running on the host machine (again, using a hypervisor) is also often called a <code>“guest machine.”</code>. This <code>guest machine</code> contains both the application and whatever it needs to run that application (e.g. system binaries and libraries).  It also carries an entire virtualized hardware stack of its own, including virtualized network adapters, storage, and CPU — which means it also has its own full-fledged guest operating system. From the inside, the guest machine behaves as its own unit with its own dedicated resources. From the outside, we know that it’s a VM — sharing resources provided by the host machine.</p>
<p>As mentioned above, a guest machine can run on either a <code>hosted hypervisor</code> or a <code>bare-metal hypervisor</code>. There are some important differences between them.</p>
<p>First off, <code>a hosted virtualization hypervisor</code> runs on the operating system of the host machine. For example, a computer running OSX can have a VM (e.g. VirtualBox or VMware Workstation 8) installed on top of that OS. The VM doesn’t have direct access to hardware, so it has to go through the host operating system (in our case, the Mac’s OSX).</p>
<p>The benefit of <code>a hosted hypervisor</code> is that the underlying hardware is less important. The host’s operating system is responsible for the hardware drivers instead of the hypervisor itself, and is therefore considered to have more “hardware compatibility.” On the other hand, this additional layer in between the hardware and the hypervisor creates more resource overhead, which lowers the performance of the <code>VM</code>.</p>
<p><code>A bare metal hypervisor</code> environment tackles the performance issue by installing on and running from the host machine’s hardware. Because it interfaces directly with the underlying hardware, it doesn’t need a host operating system to run on. In this case, the first thing installed on a host machine’s server as the operating system will be the hypervisor. Unlike the hosted hypervisor, <code>a bare-metal</code> hypervisor has its own device drivers and interacts with each component directly for any I/O, processing, or OS-specific tasks. This results in better performance, scalability, and stability. The tradeoff here is that hardware compatibility is limited because the hypervisor can only have so many device drivers built into it.</p>
<p>Well, since the <code>VM</code> has a virtual operating system of its own, the hypervisor plays an essential role in providing the VMs with a platform to manage and execute this guest operating system. It allows for host computers to share their resources amongst the virtual machines that are running as guests on top of them.</p>
<p>As you can see in the diagram, VMs package up the virtual hardware, a kernel (i.e. OS) and user space for each new VM.</p>
<figure><img src="/assets/images/devops/docker/introduction_to_containers/vms.webp" alt="Virtual Machine Diagram" tabindex="0" loading="lazy"><figcaption>Virtual Machine Diagram</figcaption></figure>
<p>As you can see in the diagram, <code>VMs</code> package up the virtual hardware, a kernel (i.e. OS) and user space for each new <code>VM</code>.</p>
<h2>Container</h2>
<p>The first thing that comes to our mind when we hear <code>Containers</code> is the <code>Docker Container</code>. The <code>Docker container</code> has become an industry standard for containerization. However, <code>LXC (Linux Container)</code> was the first implementation of containerization technology. It leveraged the <code>Linux</code> cgroups and namespace isolation to create light-weight containers.In fact, the initial version of <code>Docker</code> was directly built on top of <code>LXC</code>. Similar to <code>docker</code>, there are other containers such as <code>rocket</code> &amp; <code>containerd</code>.</p>
<p><code>Containers</code> overcome all the shortcomings of <code>Virtual Machines</code>. <code>Containers</code> don't require the installation of a separate guest operating system. They directly run and use the host operating system. <code>Containers</code> only need the dependent file system and binaries for their functioning. For eg:- A java app while running inside a container will need Java Runtime Environment (JRE). As a result, containers are lightweight as compared to <code>Virtual Machines</code>.</p>
<figure><img src="/assets/images/devops/docker/introduction_to_containers/containers.webp" alt="Working of Containers" tabindex="0" loading="lazy"><figcaption>Working of Containers</figcaption></figure>
<p>Let's assume that you are running a ticket booking system. And it's currently running on a <code>virtual machine</code>. In case there is a spike in user requests, you will have to scale your system. Hence, you would need to launch multiple <code>VM instances</code>. Launching a <code>VM</code> is an expensive &amp; time taking operation. You may notice latency spikes while scaling <code>virtual machines</code>.</p>
<p>We can avoid the above latency spike using <code>containers</code>. <code>Containers</code> are light-weight, cheap, and can be easily launched. Thus, you can scale your systems easily &amp; improve responsiveness and performance.</p>
<h2>Containers vs Virtual Machine</h2>
<figure><img src="/assets/images/devops/docker/introduction_to_containers/containers_vms_v2.webp" alt="Containers vs VM &amp; Virtual Machines" tabindex="0" loading="lazy"><figcaption>Containers vs VM &amp; Virtual Machines</figcaption></figure>
<p><code>Containers</code> and <code>virtual machines</code> are both technologies used to isolate applications and their dependencies, but they have some key differences:</p>
<ol>
<li>
<p><strong>Resource Utilization</strong>: <code>Containers</code> share the host operating system kernel, making them lighter and faster than <code>VMs</code>. <code>VMs</code> have a full-fledged <code>OS</code> and hypervisor, making them more resource-intensive.</p>
</li>
<li>
<p><strong>Portability</strong>: <code>Containers</code> are designed to be portable and can run on any system with a compatible host operating system. <code>VMs</code> are less portable as they need a compatible hypervisor to run.</p>
</li>
<li>
<p><strong>Security</strong>: <code>VMs</code> provide a higher level of security as each <code>VM</code> has its own operating system and can be isolated from the host and other <code>VMs</code>. Containers provide less isolation, as they share the host operating system.</p>
</li>
<li>
<p><strong>Management</strong>: Managing containers is typically easier than managing <code>VMs</code>, as containers are designed to be lightweight and fast-moving.</p>
</li>
</ol>
<h2>Why are containers useful?</h2>
<ol>
<li>
<p><strong>Portability</strong> – the isolated environment that containers provide effectively means the container is decoupled from the environment in which they run. Basically, they don’t care much about the environment in which they run, which means they can be run in many different environments with different operating systems and hardware platforms.</p>
</li>
<li>
<p><strong>Consistency</strong> – since the containers are decoupled from the environment in which they run, you can be sure that they operate the same, regardless of where they are deployed. The isolated environment that they provide is the same across different deployment environments.</p>
</li>
<li>
<p><strong>Speed to deploy</strong> – for the same reasons as above. There is no need for considerations around how the application will operate in a production environment. If it runs in a <code>container</code> in one environment (say, your local machine), then it can be made to run in a <code>container</code> in another environment (say, in a cloud provider) very quickly</p>
</li>
</ol>
<h2>Why are containers light weight ?</h2>
<p><code>Containers</code> are lightweight because they use a technology called containerization, which allows them to share the host operating system's kernel and libraries, while still providing isolation for the application and its dependencies. This results in a smaller footprint compared to traditional <code>virtual machines</code>, as the <code>containers</code> do not need to include a full operating system. Additionally, <code>Docker containers</code> are designed to be minimal, only including what is necessary for the application to run, further reducing their size.</p>
<p>Let's try to understand this with an example:</p>
<p>Below is the screenshot of official ubuntu base image which you can use for your <code>container</code>. It's just ~ 22 MB, isn't it very small ? on a contrary if you look at official ubuntu VM image it will be close to ~ 2.3 GB. So the container base image is almost 100 times less than <code>VM</code> image.</p>
<figure><img src="/assets/images/devops/docker/introduction_to_containers/ubuntu_images.webp" alt="Ubuntu Images" tabindex="0" loading="lazy"><figcaption>Ubuntu Images</figcaption></figure>
<p>To provide a better picture of files and folders that containers base images have and files and folders that containers use from host operating system (not 100 percent accurate -&gt; varies from base image to base image). Refer below.</p>
<p><strong>Files and Folders in containers base images</strong></p>
<div class="language-bash line-numbers-mode" data-highlighter="shiki" data-ext="bash" data-title="bash" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">/bin:</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> contains</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> binary</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> executable</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> files,</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> such</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> as</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> the</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> ls,</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> cp,</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> and</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> ps</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> commands.</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">/sbin:</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> contains</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> system</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> binary</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> executable</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> files,</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> such</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> as</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> the</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> init</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> and</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> shutdown</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> commands.</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">/etc:</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> contains</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> configuration</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> files</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> for</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> various</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> system</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> services.</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">/lib:</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> contains</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> library</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> files</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> that</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> are</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> used</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> by</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> the</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> binary</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> executables.</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">/usr:</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> contains</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> user-related</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> files</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> and</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> utilities,</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> such</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> as</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> applications,</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> libraries,</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> and</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> documentation.</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">/var:</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> contains</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> variable</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> data,</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> such</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> as</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> log</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> files,</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> spool</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> files,</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> and</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> temporary</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> files.</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">/root:</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> is</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> the</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> home</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> directory</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> of</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> the</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> root</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> user.</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>Files and Folders that containers use from host operating system</strong></p>
<div class="language-bash line-numbers-mode" data-highlighter="shiki" data-ext="bash" data-title="bash" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">The</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> host's file system: Docker containers can access the host file system using bind mounts, which allow the container to read and write files in the host file system.</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#98C379">Networking stack: The host's</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> networking</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> stack</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> is</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> used</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> to</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> provide</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> network</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> connectivity</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> to</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> the</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> container.</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> Docker</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> containers</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> can</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> be</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> connected</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> to</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> the</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> host's network directly or through a virtual network.</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#98C379">System calls: The host's</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> kernel</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> handles</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> system</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> calls</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> from</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> the</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> container,</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> which</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> is</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> how</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> the</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> container</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> accesses</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> the</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> host's resources, such as CPU, memory, and I/O.</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#98C379">Namespaces: Docker containers use Linux namespaces to create isolated environments for the container's</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> processes.</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> Namespaces</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> provide</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> isolation</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> for</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> resources</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> such</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> as</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> the</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> file</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> system,</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> process</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> ID,</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> and</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> network.</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">Control</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> groups</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> (cgroups): Docker containers use cgroups to limit and control the amount of resources, such as CPU, memory, and I/O, that a container can access.</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>It's important to note that while a container uses resources from the host operating system, it is still isolated from the host and other containers, so changes to the container do not affect the <code>host</code> or other <code>containers</code>.</p>
<p>Note: There are multiple ways to reduce your <code>VM</code> image size as well, but I am just talking about the default for easy comparision and understanding.</p>
<p>So, in a nutshell, container base images are typically smaller compared to <code>VM</code> images because they are designed to be minimalist and only contain the necessary components for running a specific application or service. <code>VMs</code>, on the other hand, emulate an entire operating system, including all its libraries, utilities, and system files, resulting in a much larger size.</p>
<p>I hope it is now very clear why containers are light weight in nature.</p>
<p>Good luck and get containerizing! Leave any questions/feedback/comments in the comment area below ❤️</p>
]]></content:encoded>
      <enclosure url="https://blog.taleedevops.today/assets/images/devops/docker/introduction_to_containers/title.jpg" type="image/jpeg"/>
    </item>
    <item>
      <title>Introduction To Docker</title>
      <link>https://blog.taleedevops.today/devops/docker/introduction-to-docker.html</link>
      <guid>https://blog.taleedevops.today/devops/docker/introduction-to-docker.html</guid>
      <source url="https://blog.taleedevops.today/rss.xml">Introduction To Docker</source>
      <description>What Docker is and why it took over: containers versus VMs, and the core architecture — Docker Engine, containerd and runc.</description>
      <category>docker</category>
      <pubDate>Tue, 09 Jul 2024 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[
<p>People and organizations have driven the demand for new applications to new heights, so the pressure is on to keep up with the demand. The task becomes easier if developers have the right tools. <code>Docker</code> is one such tool, a popular platform dedicated to the development, shipment, and running of applications.</p>
<p>Today, we will look at the best way to start using Docker. But before we get into the nuts and bolts of implementation, let’s refresh our understanding of this versatile and popular platform.</p>
<h2>What is Docker?</h2>
<figure><img src="/assets/images/devops/docker/introduction_to_docker/what_is_docker.webp" alt="What is Docker" tabindex="0" loading="lazy"><figcaption>What is Docker</figcaption></figure>
<p><code>Docker</code> is an open source software platform used to create, deploy and manage virtualized application. Open your web browser and go to <a href="https://taleedevops.today/devops/docker/introduction-to-containers.html" target="_blank" rel="noopener noreferrer">containers</a> on a common operating system <code>(OS)</code>, with an ecosystem of allied tools. The container itself is a very lightweight package with all the instructions and dependencies—such as frameworks, libraries, and bins—within it.</p>
<p><code>Docker</code> gives software developers a faster and more efficient way to build and test containerized portions of an overall software application. This lets developers in a team concurrently build multiple pieces of software. Each container contains all elements needed to build a software component and ensure it's built, tested and deployed smoothly. <code>Docker</code> enables portability for when these packaged containers are moved to different servers or environments.</p>
<p>You can use <code>Docker</code> throughout multiple stages of your <code>DevOps cycle</code>, but it is especially valuable in the deployment stage, especially since it allows developers to use rapid deployment. In addition, the environment itself is highly portable and was designed with efficiencies that will enable you to run multiple <code>Docker containers</code> in a single environment, unlike traditional virtual machine environments.</p>
<h2>Difference Between Docker Containers and Virtual Machines</h2>
<figure><img src="/assets/images/devops/docker/introduction_to_docker/docker_vms.webp" alt="Docker&amp;VMS" tabindex="0" loading="lazy"><figcaption>Docker&amp;VMS</figcaption></figure>
<ul>
<li>
<p><code>The virtual</code> environment has a <code>hypervisor layer</code>, whereas <code>Docker</code> has a <code>Docker engine</code> layer.</p>
</li>
<li>
<p>There are additional layers of libraries within the <code>virtual machine</code>, each of which compounds and creates very significant differences between a <code>Docker</code> environment and a <code>virtual machine</code> environment.</p>
</li>
<li>
<p>With a <code>virtual machine</code>, the memory usage is very high, whereas, in a <code>Docker</code> environment, memory usage is very low.</p>
</li>
<li>
<p>In terms of performance, when you start building out a <code>virtual machine</code>, particularly when you have more than one <code>virtual machine</code> on a server, the performance becomes poorer. With <code>Docker</code>, the performance is always high because of the single <code>Docker engine</code>.</p>
</li>
<li>
<p>In terms of portability, <code>virtual machines</code> just are not ideal. They’re still dependent on the host operating system, and a lot of problems can happen when you use <code>virtual machines</code> for portability. In contrast, <code>Docker</code> was designed for portability. You can actually build solutions in a <code>Docker container</code>, and the solution is guaranteed to work as you have built it no matter where it’s <code>hosted</code>.</p>
</li>
<li>
<p>The boot-up time for a <code>virtual machine</code> is fairly slow in comparison to the boot-up time for a <code>Docker</code> environment, in which boot-up is almost instantaneous.</p>
</li>
<li>
<p>One of the other challenges of using a <code>virtual machine</code> is that if you have unused memory within the environment, you cannot reallocate it. If you set up an environment that has 9 gigabytes of memory, and 6 of those gigabytes are free, you cannot do anything with that unused memory. With <code>Docker</code>, if you have free memory, you can reallocate and reuse it across other <code>containers</code> used within the <code>Docker</code> environment.</p>
</li>
<li>
<p>Another challenge of <code>virtual machines</code> is that running multiples of them in a single environment can lead to instability and performance issues. <code>Docker</code>, on the other hand, is designed to run <code>multiple containers</code> in the same environment—it actually gets better with more <code>containers</code> run in that <code>hosted</code> single <code>Docker engine</code>.</p>
</li>
<li>
<p><code>Virtual machines</code> have portability issues; the software can work on one machine, but if you move that virtual machine to another machine, suddenly some of the software won’t work, because some dependencies will not be inherited correctly. <code>Docker</code> is designed to be able to run across multiple environments and to be deployed easily across systems.</p>
</li>
<li>
<p>The boot-up time for a virtual machine is about a few minutes, in contrast to the milliseconds it takes for a <code>Docker</code> environment to boot up.</p>
</li>
</ul>
<h2>Why Docker is popular?</h2>
<p><code>Docker</code> gained its popularity due to its impact on the software development and deployment. The following are the some of the main reasons for <code>docker</code> becoming popular:</p>
<figure><img src="/assets/images/devops/docker/introduction_to_docker/why_docker_popular.webp" alt="Why Docker Popular" tabindex="0" loading="lazy"><figcaption>Why Docker Popular</figcaption></figure>
<ul>
<li>
<p><strong>Portability</strong>: <code>Docker</code> facilitates the developers in packaging their applications with all dependencies into a single lightweight <code>containers</code>. It facilities in ensuring the consistent performance across the different computing environments.</p>
</li>
<li>
<p><strong>Reproducibility</strong>: Through encapsulating the applications with their dependencies within a container it ensures in software setups remaining consistent across the development, testing and production environments.</p>
</li>
<li>
<p><strong>Efficiency</strong>: <code>Docker</code> through its container based architecture it optimizes the resource utilization. It allows the developers to run the multiple isolated applications on a single host system.</p>
</li>
<li>
<p><strong>Scalability</strong>: <code>Docker’s</code> scalability features facilitated the developers in making easier of their applications handling at time of workloads increment.</p>
</li>
</ul>
<h2>Docker Core Architecture</h2>
<p>The following sections will look at the <code>Docker architecture</code> and its associated components. We will also look at how each component works together to make <code>Docker</code> work.</p>
<p><code>Docker architecture</code> has changed a few times since its inception. When I published the first version of this article, <code>Docker</code> was built on top of <code>LXC</code>.</p>
<p>Here are some notable architectural changes that happened for the <code>Docker</code>:</p>
<ol>
<li>
<p><code>Docker</code> moved from <a href="https://linuxcontainers.org" target="_blank" rel="noopener noreferrer">LXC</a> to libcontainer in 2014</p>
</li>
<li>
<p><a href="https://github.com/opencontainers/runc" target="_blank" rel="noopener noreferrer">runc</a> – a <code>CLI</code> for spinning up containers that follow all <code>OCI</code> specifications.</p>
</li>
<li>
<p><a href="https://github.com/containerd/containerd" target="_blank" rel="noopener noreferrer">containerd</a> – <code>Docker</code> separated its container management component to <code>containerd</code> in 2016</p>
</li>
</ol>
<div class="hint-container tip">
<p class="hint-container-title">Tips</p>
<p><code>OCI</code>: <code>Open Container Initiative</code> is an open industry standard for container runtime and specifications.</p>
</div>
<p>When <code>Docker</code> was initially launched, it had a monolithic architecture. Now it is separated into the following three different components.</p>
<ol>
<li>
<p><strong>Docker Engine (dockerd)</strong></p>
</li>
<li>
<p><strong>docker-containerd (containerd)</strong></p>
</li>
<li>
<p><strong>docker-runc (runc)</strong></p>
</li>
</ol>
<p><code>Docker</code> and other big organizations contributed to a standard container runtime and management layers. Hence <code>containerd</code> and <code>runc</code> are now part of the <code>Cloud Native Foundation</code> with contributors from all the organizations.</p>
<div class="hint-container tip">
<p class="hint-container-title">Tips</p>
<p><strong>Note</strong>: When installing Docker, all these components get installed. You don’t have to install it separately. For exaplanation, we are showing it as different components.</p>
</div>
<figure><img src="/assets/images/devops/docker/introduction_to_docker/docker_core_architecture.webp" alt="Docker Architecture" tabindex="0" loading="lazy"><figcaption>Docker Architecture</figcaption></figure>
<h3>Docker Engine</h3>
<p><code>Docker engine</code> comprises the <code>docker daemon</code>, an <code>API interface</code>, and <code>Docker CLI</code>. <code>Docker daemon</code> <code>(dockerd)</code> runs continuously as <code>dockerd systemd</code> service. It is responsible for building the <code>docker images</code>.</p>
<p>To manage images and run <code>containers</code>, <code>dockerd</code> calls the <code>docker-containerd</code> APIs.</p>
<figure><img src="/assets/images/devops/docker/introduction_to_docker/docker_engine.webp" alt="Docker Engine" tabindex="0" loading="lazy"><figcaption>Docker Engine</figcaption></figure>
<h3>Docker-containerd (containerd)</h3>
<p><code>containerd</code> is another system daemon service than is responsible for downloading the docker images and running them as a container. It exposes its API to receive instructions from the <code>dockerd</code> service</p>
<h3>Docker-runc</h3>
<p><code>runc</code> is the container runtime responsible for creating the namespaces and cgroups required for a container. It then runs the container commands inside those namespaces. runc runtime is implemented as per the <code>OCI</code> specification.</p>
<figure><img src="/assets/images/devops/docker/introduction_to_docker/containerd.webp" alt="" tabindex="0" loading="lazy"><figcaption></figcaption></figure>
<h2>How Docker works</h2>
<p><code>Docker</code> works via a <code>Docker engine</code> that is composed of two key elements: <code>a server</code> and <code>a client</code> and the communication between the two is via <code>REST API</code>. The server communicates the instructions to the client. On older <code>Windows</code> and <code>Mac systems</code>, you can take advantage of the <code>Docker</code> toolbox, which allows you to control the <code>Docker engine</code> using <code>Compose</code> and <code>Kitematic</code>.</p>
<h2>Key Components of Docker</h2>
<p>The following official <code>high-level</code> <code>docker</code> architecture diagram shows the common <code>Docker</code> workflow.</p>
<figure><img src="/assets/images/devops/docker/introduction_to_docker/high_level_docker.webp" alt="High-level docker" tabindex="0" loading="lazy"><figcaption>High-level docker</figcaption></figure>
<p><code>Docker</code> ecosystem is composed of the following five components:</p>
<ol>
<li>
<p><strong>Docker Daemon (dockerd)</strong></p>
</li>
<li>
<p><strong>Docker client and server</strong></p>
</li>
<li>
<p><strong>Docker Images</strong></p>
</li>
<li>
<p><strong>Docker Registries</strong></p>
</li>
<li>
<p><strong>Docker Containers</strong></p>
</li>
</ol>
<h3>What is a Docker Daemon</h3>
<p><code>Docker</code> has a client-server architecture. <code>Docker Daemon</code> <code>(dockerd)</code> or <code>server</code> is responsible for all the actions related to <code>containers</code>.</p>
<p><code>The daemon</code> receives the commands from the <code>Docker client</code> through <code>CLI</code> or <code>REST API</code>. <code>Docker client</code> can be on the same host as a daemon or present on any other host.</p>
<p>By default, the <code>docker daemon</code> listens to the <code>docker.sock</code> <code>UNIX socket</code>. If you have any use case to access the docker API remotely, you need to expose it over a host port</p>
<p>If you want to run <code>Docker inside Docker</code>, you can use the <code>docker.sock</code> from the host machine.</p>
<h3>What is a Docker Image</h3>
<p><code>Images</code> are the basic building blocks of <code>Docker</code>. It contains the <code>OS</code> libraries, dependencies, and tools to run an application.</p>
<p>The <code>Docker image</code> is built within the <code>YAML</code> file and then hosted as a file in the <code>Docker registry</code>.</p>
<p><code>The image</code> has several key layers, and each layer depends on the layer below it.</p>
<p><code>Image layers</code> are created by executing each command in the <code>Dockerfile</code> and are in the read-only format.</p>
<p>You start with your base layer, which will typically have your base image and your base operating system, and then you will have a layer of dependencies above that.</p>
<p>These then comprise the instructions in a read-only file that would become your <code>Dockerfile</code>.</p>
<h3>What is a Docker File</h3>
<figure><img src="/assets/images/devops/docker/introduction_to_docker/docker_file.webp" alt="DockerFile" tabindex="0" loading="lazy"><figcaption>DockerFile</figcaption></figure>
<ul>
<li>
<p><strong>From</strong> command creates a layer based on <code>Ubuntu</code>, and then we add files from the <code>Docker repository</code> to the base command of that base layer.</p>
</li>
<li>
<p><strong>Pull</strong>: Adds files from your <code>Docker repository</code></p>
</li>
<li>
<p><strong>Run</strong>: Builds your <code>container</code></p>
</li>
<li>
<p><strong>CMD</strong>: Specifies which command to run within the <code>container</code></p>
</li>
</ul>
<p>In this instance, the command is to run Python. One of the things that will happen as we set up multiple <code>containers</code> is that each new container adds a new layer with new images within the <code>Docker</code> environment. Each container is completely separate from the other containers within the <code>Docker</code> environment, so you can create your own separate read-write instructions within each layer. What’s interesting is that if you delete a layer, the layer above it will also get deleted.</p>
<p>What happens when you pull in a layer but something changes in the core image? Interestingly, the main image itself cannot be modified. Once you’ve copied the image, you can modify it locally. You can never modify the actual base image.</p>
<p>The top layer of an image is writable and used by the running container. Other layers in the image are read-only.</p>
<figure><img src="/assets/images/devops/docker/introduction_to_docker/dockerfile_v2.webp" alt="DockerFile" tabindex="0" loading="lazy"><figcaption>DockerFile</figcaption></figure>
<h3>What is Docker Registry</h3>
<p>It is a <code>repository</code> (storage) for <code>Docker</code> images.</p>
<p>A registry can be public or private. For example, Docker Inc provides a hosted registry service called <code>Docker Hub</code>. It allows you to upload and download images from a central location.</p>
<div class="hint-container note">
<p class="hint-container-title">Note</p>
<p>By default, when you install docker, it looks for images from the public Docker hub unless you specify a custom registry in Docker settings.</p>
</div>
<p>Other <code>Docker hub</code> users can access all your images if your repository is public. You can also create a private registry in <code>Docker Hub</code>.</p>
<p><code>Docker hub</code> acts like git, where you can build your images locally on your laptop, commit it, and then be pushed to the <code>Docker hub</code>.</p>
<div class="hint-container tip">
<p class="hint-container-title">Tips</p>
<p>When using docker in enterprise networks/project, set up your own docker registries instead of using the public docker hub. All cloud providers have their own container registry services.</p>
</div>
<h3>What is a Docker Container</h3>
<p><code>Docker Containers</code> are created from existing images. It is a writable layer of the image.</p>
<p>If you try to relate image layers and a <code>container</code>, here is how it looks for a <code>ubuntu-based</code> image.</p>
<figure><img src="/assets/images/devops/docker/introduction_to_docker/docker_container.webp" alt="Docker Container" tabindex="0" loading="lazy"><figcaption>Docker Container</figcaption></figure>
<p>You can package your applications in a <code>container</code>, commit it, and make it a golden image to build more <code>containers</code> from it.</p>
<p><code>Containers</code> can be started, stopped, committed, and terminated. If you terminate a container without committing it, all the <code>container</code> changes will be lost.</p>
<p>Ideally, <code>containers</code> are treated as immutable objects, and it is not recommended to make changes to a running <code>container</code>. Instead, make changes to a running <code>container</code> only for testing purposes.</p>
<p>Two or more <code>containers</code> can be linked together to form tiered application architecture. However, hosting hight scalable applications with <code>Docker</code> has been made easy with the advent of <code>container orchestration tools</code> like <code>kubernetes</code>.</p>
<h2>Advanced Docker Components</h2>
<p>After going through the various components of <code>Docker</code>, the next focus of this <code>Docker</code> tutorial are the advanced components of <code>Docker</code>:</p>
<ul>
<li>
<p><strong>Docker compose</strong></p>
</li>
<li>
<p><strong>Docker swamp</strong></p>
</li>
</ul>
<h3>Docker Compose</h3>
<figure><img src="/assets/images/store/devops/docker/introduction-to-docker/docker-compose.webp" alt="Docker Compose" tabindex="0" loading="lazy"><figcaption>Docker Compose</figcaption></figure>
<p><code>Docker compose</code> is designed for running multiple <code>containers</code> as a single service. It does so by running each <code>container</code> in isolation but allowing the <code>containers</code> to interact with one another. As noted earlier, you would write the compose environments using <code>YAML</code>.</p>
<p>So in what situations might you use <code>Docker compose</code>? An example would be if you are running an <code>Apache server</code> with a single database and you need to create additional containers to run additional services without having to start each one separately. you would write a set of files using <code>Docker compose</code> to do that.</p>
<h3>Docker Swarm</h3>
<figure><img src="/assets/images/store/devops/docker/introduction-to-docker/docker-swarm.webp" alt="Docker Swarm" tabindex="0" loading="lazy"><figcaption>Docker Swarm</figcaption></figure>
<p><code>Docker swarm</code> is a service for containers that allows IT administrators and developers to create and manage a cluster of swarm nodes within the <code>Docker platform</code>. Each node of <code>Docker swarm</code> is a <code>Docker daemon</code>, and all <code>Docker daemons</code> interact using the <code>Docker API</code>.</p>
<p><code>A swarm</code> consists of two types of <code>nodes</code>: a manager <code>node</code> and a <code>worker node</code>. A manager node maintains cluster management tasks. Worker nodes receive and execute tasks from the manager <code>node</code>.</p>
<h3>Docker Desktop</h3>
<figure><img src="/assets/images/store/devops/docker/introduction-to-docker/docker-desktop.webp" alt="Docker Desktop" tabindex="0" loading="lazy"><figcaption>Docker Desktop</figcaption></figure>
<p>It’s easy to get overwhelmed by terminology, and some people may wonder if <code>Docker</code> (also known as <code>Docker Engine</code>) and <code>Docker Desktop</code> are different things. However, the two entities aren’t the same. <code>Docker Desktop</code> is a free, easy-to-install, downstream application for a Mac or Windows environment. The application lets you build and share containerized applications and microservices. <code>Docker</code> consists of <a href="https://docs.docker.com/engine" target="_blank" rel="noopener noreferrer">Docker Engine</a>, <a href="https://docs.docker.com/compose" target="_blank" rel="noopener noreferrer">Docker Compose</a>, Docker CLI client, <a href="https://docs.docker.com/engine/security/trust" target="_blank" rel="noopener noreferrer">Docker Content Trust</a>,  <a href="https://github.com/kubernetes/kubernetes" target="_blank" rel="noopener noreferrer">Kubernetes</a>, and <a href="https://github.com/docker/docker-credential-helpers" target="_blank" rel="noopener noreferrer">Credential Helper</a>.</p>
<p><code>Docker Desktop</code> functions well with any developer’s choice of tools and languages and gives access to a massive library of certified images and templates residing in <code>Docker Hub</code>. These resources help development teams extend their environment to rapidly auto-build, continuously integrate, and collaborate with a secure repository.</p>
<p>So, to recap, <code>Docker Engine</code> is the client-server technology used to build and run containers and is often referred to as <code>“Docker.”</code></p>
<p>Additionally, people use <code>“Docker”</code> to refer to the company itself. On the other hand, <code>Docker Desktop</code> is a free application that bundles together numerous <code>Docker</code> resources.</p>
<h2>What is Docker used for?</h2>
<p>Thanks to its flexible nature, <code>Docker</code> has various use cases. Below are some example ways in which application developers use <code>Docker</code>:</p>
<ul>
<li>
<p><strong>Deploying</strong> microservices.<code>Docker</code> supports the microservice approach to app development by offering a simple way to connect components using its built-in container networking features.</p>
</li>
<li>
<p><strong>Software testing</strong>. <code>Docker containers</code> provide a quick way to start and stop the applications and allow quick iteration between different app versions.</p>
</li>
<li>
<p><strong>Deploying database containers</strong>. Running a database <code>container</code> alongside an app <code>container</code> simplifies database management. It ensures the app can create and use the database even if the relevant <code>DBMS</code> is not installed on the host system.</p>
</li>
<li>
<p><strong>Accessing tools without having to install them</strong>. App development often requires tools that are used only once in the process. Using a <code>containerized</code> version of a tool provides easy access to its functionality without installing it.</p>
</li>
<li>
<p><strong>Creating easily deployable app stacks</strong>. <code>Docker Compose</code> allows users to create a single file to deploy a set of <code>containerized</code> apps. This feature is particularly useful in development, where tool stacks are extensively used.</p>
</li>
</ul>
<h2>Docker FAQs</h2>
<p>The following section contains frequently asked questions regarding Docker's design and usage.</p>
<h3>What is the difference between containerd &amp; runc?</h3>
<p><code>containerd</code> is responsible for managing the <code>container</code> and <code>runc</code> is responsible for running the <code>containers</code> (create namespaces, cgroups and run commands inside the container) with the inputs from <code>containerd</code></p>
<h3>What is the difference between the Docker engine &amp; the Docker daemon?</h3>
<p><code>Docker engine</code> is composed of the <code>docker daemon</code>, <code>rest interface</code>, and the <code>docker CLI</code>. <code>Docker daemon</code> is the systemd <code>dockerd</code> service responsible for building the docker images and sending <code>docker</code> instructions to <code>containerd</code> runtime</p>
<h2>Conclusion</h2>
<p>By now, you should have a good understanding of what <code>Docker</code> is and how it works.</p>
<p>The best feature of <code>Docker</code> is collaboration. <code>Docker images</code> can be pushed to a repository and pulled down to any other host to run <code>containers</code> from that image.</p>
<p>Moreover, the <code>Docker hub</code> has thousands of images created by users, and you can pull those images down to your hosts based on your application requirements. Also, it is primarily used in container orchestration tools like <code>kubernetes</code></p>
]]></content:encoded>
      <enclosure url="https://blog.taleedevops.today/assets/images/devops/docker/introduction_to_docker/title.jpg" type="image/jpeg"/>
    </item>
    <item>
      <title>Apply conventional commit style on your project</title>
      <link>https://blog.taleedevops.today/devops/git/apply-conventional-commit-style.html</link>
      <guid>https://blog.taleedevops.today/devops/git/apply-conventional-commit-style.html</guid>
      <source url="https://blog.taleedevops.today/rss.xml">Apply conventional commit style on your project</source>
      <description>Adopt Conventional Commits on a real project: the type, scope, subject and footer fields, valid message examples, and the practices that stick.</description>
      <category>devops</category>
      <pubDate>Sat, 17 Aug 2024 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[
<p>Hello 🙋‍♂️, today I´m going to write about <code>Conventional Commits</code> (as you can see in the title). I've always wondered if there was a standardization with commits. I think this standardization is necessary and it can make our life easier</p>
<p><code>Git</code> is widely used across the software engineering world to build software because it helps to keep the history of changes in our codebase throughout the build of software by a team.</p>
<p>After performing some code changes (editing files, adding a new file, and deleting files), we must commit to adding our change in Git history. A commit is usually a message that summarizes what we did on the codebase.</p>
<h2>What is conventional commit?</h2>
<p>From the <a href="https://www.conventionalcommits.org/en/v1.0.0/" target="_blank" rel="noopener noreferrer">conventional commit specification website</a>:</p>
<p><em>The Conventional Commits specification is a lightweight convention on top of commit messages. It provides an easy set of rules for creating an explicit commit history; which makes it easier to write automated tools on top of.</em></p>
<p>Commits should have the following structure:</p>
<div class="language-bash line-numbers-mode" data-highlighter="shiki" data-ext="bash" data-title="bash" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">git</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> commit</span><span style="--shiki-light:#005CC5;--shiki-dark:#D19A66"> -m</span><span style="--shiki-light:#D73A49;--shiki-dark:#ABB2BF"> &lt;</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">typ</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">e</span><span style="--shiki-light:#D73A49;--shiki-dark:#ABB2BF">&gt;</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">[optional</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379"> scope]:</span><span style="--shiki-light:#D73A49;--shiki-dark:#ABB2BF"> &lt;</span><span style="--shiki-light:#032F62;--shiki-dark:#98C379">subjec</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">t</span><span style="--shiki-light:#D73A49;--shiki-dark:#ABB2BF">&gt;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">[optional description]</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">[optional footer(</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75">s</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">)]</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3>Type</h3>
<p>It indicates the type of commit. Is it a feature, a fix, a test, a refactoring, tooling, etc...</p>
<p>The recommended values are:</p>
<p>| Types                                        | Target                   | Description                                                                                                 |
|</p>
]]></content:encoded>
      <enclosure url="https://blog.taleedevops.today/assets/images/store/devops/git/apply-conventional-commit-style/title.jpg" type="image/jpeg"/>
    </item>
    <item>
      <title>What is Git</title>
      <link>https://blog.taleedevops.today/devops/git/git.html</link>
      <guid>https://blog.taleedevops.today/devops/git/git.html</guid>
      <source url="https://blog.taleedevops.today/rss.xml">What is Git</source>
      <description>What Git is: a distributed version control system, how it tracks changes, and why it lets many developers work without stepping on each other.</description>
      <category>devops</category>
      <pubDate>Sun, 23 Jun 2024 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[
<p>Git is a distributed version control system designed to handle everything from small to very large projects with speed and efficiency. It is free and open-source software that enables multiple developers to work on the same project without interfering with each other's changes. Git tracks changes in the source code, allowing developers to collaborate on non-linear development and maintain a historical record of modifications. Key features of Git include branch management, staging areas, and support for various workflows, making it a powerful tool for both individual and team-based projects.</p>
]]></content:encoded>
      <enclosure url="https://blog.taleedevops.today/assets/images/git/git_v1.jpg" type="image/jpeg"/>
    </item>
    <item>
      <title>1. Questions on OOP Core Concepts</title>
      <link>https://blog.taleedevops.today/interview-faq/java/oop-interview-questions.html</link>
      <guid>https://blog.taleedevops.today/interview-faq/java/oop-interview-questions.html</guid>
      <source url="https://blog.taleedevops.today/rss.xml">1. Questions on OOP Core Concepts</source>
      <description>Java OOP interview questions with worked answers: the four pillars, tight versus loose encapsulation, and coupling and cohesion.</description>
      <category>backend</category>
      <pubDate>Mon, 09 Sep 2024 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[<p>Java OOP interview questions guide lists some important and tricky questions and answers to help refresh the basic concepts with examples.</p>
<h1>1. Questions on OOP Core Concepts</h1>
<h2>1.1 What are the four major pillars of OOP?</h2>
<p>The major pillars on which OOP relies are <code>Encapsulation</code>, <code>Inheritance</code>, <code>Polymorphism</code> and <code>Abstraction</code>.</p>
<ul>
<li>
<p><code>Encapsulation</code> provides security to our application, it consists of private variable declarations (data hiding) and accessor methods (getters/setters) to access the variables.</p>
</li>
<li>
<p><code>Inheritance</code> reduces code redundancy by providing code reusability.</p>
</li>
<li>
<p><code>Polymorphism</code> provides flexibility any allowing to the declaration of methods with the same name for different purposes.</p>
</li>
<li>
<p><code>Abstraction</code> provides security by hiding the internal implementation of a class and only exposing the details necessary in the context.</p>
</li>
</ul>
<h2>1.2. Is Java a pure object-oriented programming language?</h2>
<p>No, Java is not a pure object-oriented programming langeuage because:</p>
<ul>
<li>
<p>Java does not provide multiple inheritance support for classes.</p>
</li>
<li>
<p>Java does not provide support for operator overloading.</p>
</li>
<li>
<p>We use primitive variables like byte, short, char, int, float, long and double these are not object.</p>
</li>
</ul>
<p>Because of the above reasons, we can't say Java is 100&amp; pure object-oriented.</p>
<h2>1.3. What are the tightly encapsulated and loosely encapsulated classes?</h2>
<p>A tightly encapsulated class does not allow public access to any of its data members and only allows accessors and mutator methods to modify them. In general, we can say a class is tightly encapsulated if and only if every variable indide the class is private scoped.</p>
<p>Note that an immutable class is always tightly encapsulated, but not every tightly encapsulation class is immutable.</p>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" data-title="java" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#E5C07B"> Student</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">	private</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> int</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75"> rollNo</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">	private</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> String</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75"> studentName</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">	private</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> String</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75"> collageName</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#7F848E;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic">	//Getters and Setters</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Characteristics of Tightly Encapsulated Classes:</p>
<ul>
<li>
<p><strong>Private Fields</strong>: All instance variables (fields) are deciared <code>private</code>.</p>
</li>
<li>
<p><strong>Controlled Access</strong>: Access to fields is provided through public getter and setter methods (or only getters for read-only fields).</p>
</li>
<li>
<p><strong>Data Hiding</strong>: Internal representation and state are hidden from other classes, making the class less prone to errors caused by unintended external modifications.</p>
</li>
<li>
<p><strong>Improved Security</strong>: Since the internal data cannot be directly accessed or modified from outside the class, in enhances security and protects the data from unauthorzized access.</p>
</li>
</ul>
<p>If an least one variable indide the class is not declared <code>private</code>. Instead, they may be <code>protected</code>, <code>public</code>, or package-private (default). This allows for more direct access to the fields from outside the class, which may be appropriate in some cases but can make the class less secure and more prone to errors then that class is known as a loosely encapsulation class.</p>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" data-title="java" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#E5C07B"> Student</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">	private</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> int</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75"> rollNo</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">	private</span><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B"> String</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75"> studentName</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">	String</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75"> collageName</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#7F848E;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic">       //Getters and Setters</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Characteristics of Loosely Encapsulated Classes:</p>
<ul>
<li>
<p><strong>Public or Protected Fields</strong>: Some or all fields are marked as public or protected, allowing direct access from other classes.</p>
</li>
<li>
<p><strong>Less Control</strong>: There is less control over how the fields are accessed or modified, leading to potential unintended side effects or errors.</p>
</li>
<li>
<p><strong>Reduced Data Hiding</strong>: Internal representation and state are exposed to other classes, which may reduce modularity and increase coupling.</p>
</li>
<li>
<p><strong>Flexibility Over Security</strong>: Loosely encapsulated classes offer more flexibility but at the cost of reduced security and data protection.</p>
</li>
</ul>
<h2>1.4. What are Coupling and Cohesion?</h2>
<p><strong>Coupling</strong> is the degree of dependency between the components.</p>
<p><strong>Tight coupling</strong> generally happens when a class knows too much the internal working of the dependent classes. Many times, we cannot change one component without changing the other.</p>
<p>In the following example, we use the <em>ReportService</em> class that prepares the data and writes a PDF report using the <em>PdfReportWriter</em> instance. Suppose we want to add the capability to write excel reports as well. Can we add the capability without changing the <em>ReportService</em>? NO</p>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" data-title="java" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#E5C07B"> ReportService</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">	public</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B"> Object</span><span style="--shiki-light:#24292E;--shiki-dark:#61AFEF">[][] </span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">createReportData</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">()</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> {...}</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">	private</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> writeReport</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B">Object</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">[][] </span><span style="--shiki-light:#E36209;--shiki-dark:#E06C75;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic">data</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">)</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">		new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> PdfReportWriter</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">writeData</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(data);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">	}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>In a <strong>loosely coupled</strong> system, components depend on each other to the least extent practically possible. This <strong>allows us to change individual components without affecting other parts of the software</strong>.</p>
<p>In the following code, we solved the previous problem using low coupling. Now the <em>ReportService</em> class only expects an <em>IReportWriter</em> implementation, and that class would be responsible for generating the report. We can inject as many supported report types, without touching any of the other classes.</p>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" data-title="java" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> interface</span><span style="--shiki-light:#6F42C1;--shiki-dark:#E5C07B"> IReportWriter</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">	public</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> writeData</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B">Object</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">[][] </span><span style="--shiki-light:#E36209;--shiki-dark:#E06C75;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic">data</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">}</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#E5C07B"> PdfReportWriter</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> implements</span><span style="--shiki-light:#6F42C1;--shiki-dark:#E5C07B"> IReportWriter</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">	public</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> writeData</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B">Object</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">[][] </span><span style="--shiki-light:#E36209;--shiki-dark:#E06C75;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic">data</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">)</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> {...}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">}</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#E5C07B"> ExcelReportWriter</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> implements</span><span style="--shiki-light:#6F42C1;--shiki-dark:#E5C07B"> IReportWriter</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">	public</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> writeData</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B">Object</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">[][] </span><span style="--shiki-light:#E36209;--shiki-dark:#E06C75;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic">data</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">)</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> {...}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">}</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#E5C07B"> ReportWriter</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> implements</span><span style="--shiki-light:#6F42C1;--shiki-dark:#E5C07B"> IReportWriter</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">	IReportWriter</span><span style="--shiki-light:#24292E;--shiki-dark:#E06C75"> writer</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">	public</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B"> Object</span><span style="--shiki-light:#24292E;--shiki-dark:#61AFEF">[][] </span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">createReportData</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">()</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> {...}</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">	private</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> writeReport</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#E5C07B">Object</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">[][] </span><span style="--shiki-light:#E36209;--shiki-dark:#E06C75;--shiki-light-font-style:inherit;--shiki-dark-font-style:italic">data</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">)</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E5C07B">		writer</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF">writeData</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(data);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">	}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>Cohesion</strong> is creating components with clear well-defined responsibilities. If we maintain only one component for all functionalities, then it's known as <strong>low cohesion</strong> and has several disadvantages.</p>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" data-title="java" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#E5C07B"> AppManager</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">	public</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> login</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(){...}</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">	public</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> register</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(){...}</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">	public</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> forgotPassword</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(){...}</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">	public</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> addToCart</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(){...}</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">	public</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> checkout</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(){...}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Maintaining high cohesion by creating defferent components for different functionality is always a good programming practice.</p>
<div class="language-java line-numbers-mode" data-highlighter="shiki" data-ext="java" data-title="java" style="--shiki-light:#24292e;--shiki-dark:#abb2bf;--shiki-light-bg:#fff;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes github-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#E5C07B"> LoginManager</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">	public</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> login</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(){...}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">}</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#E5C07B"> RegistrationManager</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD">	public</span><span style="--shiki-light:#D73A49;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#61AFEF"> register</span><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">(){...}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">...</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#ABB2BF">...</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>The above program follows low cohesion as every functionality is declared inside only one component. We can achieve low cohesion by following the <a href=""><strong>Single responsibility principle</strong></a>.</p>
<div class="hint-container note">
<p class="hint-container-title">Note</p>
<p>It is highly recommended to follow loose coupling and high cohesion always.</p>
</div>
]]></content:encoded>
      <enclosure url="https://blog.taleedevops.today/assets/images/store/interview-faq/java/oop-interview-questions/title.jpg" type="image/jpeg"/>
    </item>
    <item>
      <title>Claude Fable 5 vs Claude Opus 5: One Prompt, Two Models, One Excel File</title>
      <link>https://blog.taleedevops.today/youtube/ai-automation/claude-fable-5-vs-opus-5-agentic-coding.html</link>
      <guid>https://blog.taleedevops.today/youtube/ai-automation/claude-fable-5-vs-opus-5-agentic-coding.html</guid>
      <source url="https://blog.taleedevops.today/rss.xml">Claude Fable 5 vs Claude Opus 5: One Prompt, Two Models, One Excel File</source>
      <description>Same prompt, same 8-sheet Excel spec, two models. Which one planned, fixed its own errors, verified its work — and what the bill came to.</description>
      <category>YouTube</category>
      <category>AI</category>
      <pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[
<p>Anthropic's pricing page makes a specific claim: Claude Opus 5 costs half what Claude Fable 5
costs. Not "a bit less" — exactly half, on both sides of the meter.</p>
<p>| | Input / 1M tokens | Output / 1M tokens |
|</p>
]]></content:encoded>
      <enclosure url="https://blog.taleedevops.today/assets/images/youtube/ai-automation/claude-fable-5-vs-opus-5.jpg" type="image/jpeg"/>
    </item>
    <item>
      <title>A Second Brain That Maintains Itself: Claude Fable 5 + Obsidian</title>
      <link>https://blog.taleedevops.today/youtube/ai-automation/claude-obsidian-second-brain-wiki.html</link>
      <guid>https://blog.taleedevops.today/youtube/ai-automation/claude-obsidian-second-brain-wiki.html</guid>
      <source url="https://blog.taleedevops.today/rss.xml">A Second Brain That Maintains Itself: Claude Fable 5 + Obsidian</source>
      <description>A vault where the agent owns the wiki, may never touch the sources, and has to cite one for every claim it writes.</description>
      <category>YouTube</category>
      <category>AI</category>
      <pubDate>Mon, 17 Aug 2026 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[
<p>Hundreds of bookmarks you will never reopen. Dozens of AI conversations that scrolled away.
That is not accumulating knowledge — it is accumulating storage.</p>
<p>The difference is whether anything gets <em>compiled</em> on the way in. A folder holds what you put
in it. A wiki gets denser: every new source has to be reconciled against what is already there,
which is exactly the work nobody does on a Sunday evening.</p>
<p>This is the setup where that reconciliation is handed to an agent — an Obsidian vault whose
<code>wiki/</code> layer is written and maintained entirely by Claude Fable 5, following the
<a href="https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f" target="_blank" rel="noopener noreferrer">LLM Wiki pattern</a> Andrej Karpathy published as an idea file meant to be handed straight to
an agent.</p>
<h2>Why not just RAG</h2>
<p>Karpathy's framing is the sharpest part, and it is worth stating before any of the mechanics.</p>
<p>Upload files, retrieve relevant chunks at query time, generate an answer — that is how most
document setups work, and nothing accumulates. Ask a question that needs five documents
synthesised and the model finds and re-assembles those fragments <em>from scratch, every time</em>.</p>
<p>A wiki inverts the timing. The synthesis happens <strong>once, on the way in</strong>: the cross-references
are already written, the contradictions already flagged. Every later question reads a structure
that got denser with each source, instead of re-deriving one from raw text.</p>
<p>His own working arrangement is the one used here — agent on one side, Obsidian on the other,
watching the graph redraw as pages land:</p>
<blockquote>
<p>Obsidian is the IDE; the LLM is the programmer; the wiki is the codebase.</p>
<p>— Andrej Karpathy, <em>LLM Wiki</em></p>
</blockquote>
<div class="hint-container info">
<p class="hint-container-title">About this write-up</p>
<p>Written from my own vault, not from theory — the folder counts, the contract, and the log
entries quoted below are the real files. Where the system has limits, they are named.</p>
</div>
<h2>The one idea that makes it work</h2>
<p>Most "AI second brain" setups fail the same way: the agent keeps writing pages, nothing ever
gets merged, and six months later you have four pages about the same tool under four names.</p>
<p>The fix is not a better prompt. It is <strong>ownership</strong>, written down.</p>
<p>This is the written companion to the video, where the vault is built from an empty folder and
the first two sources are ingested end to end — including the graph view redrawing itself.</p>
]]></content:encoded>
      <enclosure url="https://blog.taleedevops.today/assets/images/youtube/ai-automation/claude-obsidian-wiki.jpg" type="image/jpeg"/>
    </item>
    <item>
      <title>OpenAI Codex: The Local Folder Is the Product</title>
      <link>https://blog.taleedevops.today/youtube/ai-automation/codex-local-folder-is-the-product.html</link>
      <guid>https://blog.taleedevops.today/youtube/ai-automation/codex-local-folder-is-the-product.html</guid>
      <source url="https://blog.taleedevops.today/rss.xml">OpenAI Codex: The Local Folder Is the Product</source>
      <description>Codex is not a coding tool with a chat window bolted on. Almost every feature that separates it from ChatGPT falls out of one decision: it works on your disk, not on a copy.</description>
      <category>YouTube</category>
      <category>AI</category>
      <pubDate>Sat, 22 Aug 2026 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[
<p>The common assumption about Codex is that it codes and fixes bugs, and that is the extent of it.
Watch the walkthrough and a different shape emerges: reading documents, analysing requirements,
planning work, remembering context, automating recurring jobs, connecting to third-party tools.
None of that is coding.</p>
<p>But listing features is the wrong way to understand this tool, because the features are not
independent. Nearly all of them are consequences of a single design decision:</p>
<blockquote>
<p><strong>A Codex project is a real folder on your machine, and Codex operates on it directly.</strong></p>
</blockquote>
<p>ChatGPT works on a copy you uploaded to the cloud. Codex works on the original. Once you accept
that one sentence, projects, the generated spreadsheet, the surprising behaviour of "delete", the
memory files and the two settings screens all stop being a feature list and start being one idea
with five faces.</p>
<div class="hint-container info">
<p class="hint-container-title">About this write-up</p>
<p>Written from the video on the channel. The walkthrough, the Linear integration and the scheduled
job are what happened on screen. Two things are labelled rather than asserted: the model name in
the auto-captions was garbled beyond reconstruction, so the model picker is described by
behaviour; and the subscription price quoted in the video is the creator's own figure, not
something verified against a pricing page.</p>
</div>
<h2>Getting in: three shapes, two billing models</h2>
<p>Codex ships in three forms, and which one you pick changes the mental model more than the
capability:</p>
<p>| Form | How you get it | Feels like |
|</p>
]]></content:encoded>
      <enclosure url="https://blog.taleedevops.today/assets/images/youtube/ai-automation/codex-agent.jpg" type="image/jpeg"/>
    </item>
    <item>
      <title>Claude Fable 5 Is Back: A Demo That Can Actually Be Wrong</title>
      <link>https://blog.taleedevops.today/youtube/ai-automation/fable-5-comeback-admissions-advisor.html</link>
      <guid>https://blog.taleedevops.today/youtube/ai-automation/fable-5-comeback-admissions-advisor.html</guid>
      <source url="https://blog.taleedevops.today/rss.xml">Claude Fable 5 Is Back: A Demo That Can Actually Be Wrong</source>
      <description>Most model demos cannot be wrong in a way you can see. This one can — the numbers either match the source files or they do not.</description>
      <category>YouTube</category>
      <category>AI</category>
      <pubDate>Fri, 21 Aug 2026 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[
<p>Most model demos are unfalsifiable. Build a landing page, write a slide deck, summarise a
report — the output looks impressive and nobody can point at a line and say <em>that is factually
incorrect</em>. Which means the demo proves the model can produce plausible shapes, and not much
else.</p>
<p>This one is different, and that is the only reason it is worth writing up.</p>
<p>The task: take five years of published university cutoff scores, take a student's exam result,
and tell them which programmes are realistic. Every number in the output traces to a specific
row in a specific file. If the model invents a cutoff, you can catch it by opening the file.</p>
<div class="hint-container info">
<p class="hint-container-title">About this write-up</p>
<p>Written from the video on the channel. The observations below — including the bug the demo
found in its own output — are what happened on screen. Where a claim comes from the vendor's
own material rather than the run, it is labelled as such.</p>
</div>
<h2>Why this task is a good test</h2>
<p>Vietnamese university admission works off a published cutoff score per programme per year. A
student finishes the national exam, gets three subject marks plus a regional bonus, and has to
guess which programmes are within reach.</p>
<p>That makes it an unusually honest benchmark for an agent:</p>
<ul>
<li><strong>There is a ground truth.</strong> The 2023 cutoff for a given programme is a fact in a file.</li>
<li><strong>The arithmetic is checkable.</strong> Three subjects plus a bonus, with rounding rules that matter.</li>
<li><strong>Being wrong is expensive.</strong> A student acting on a hallucinated cutoff makes a real decision
badly.</li>
</ul>
<p>The build was done in Claude Code with Fable 5 selected, in plan mode, against a folder holding
the score data as markdown and a separate file of the 2026 regional-bonus regulations.</p>
<p>This is the written companion to the video, where the whole run happens on screen — the plan,
the fifteen minutes of building, the self-test, and the filter that comes out wrong.</p>
]]></content:encoded>
      <enclosure url="https://blog.taleedevops.today/assets/images/youtube/ai-automation/fable-5-comeback.jpg" type="image/jpeg"/>
    </item>
    <item>
      <title>Fable Mode: Getting a Frontier Model to Write the Manual for Its Replacement</title>
      <link>https://blog.taleedevops.today/youtube/ai-automation/fable-mode-extracting-standing-instructions.html</link>
      <guid>https://blog.taleedevops.today/youtube/ai-automation/fable-mode-extracting-standing-instructions.html</guid>
      <source url="https://blog.taleedevops.today/rss.xml">Fable Mode: Getting a Frontier Model to Write the Manual for Its Replacement</source>
      <description>Ask the strongest model you have to write the operating orders for the cheaper one that replaces it — a succession letter, not a prompt.</description>
      <category>YouTube</category>
      <category>AI</category>
      <pubDate>Sun, 16 Aug 2026 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[
<p>Most people run a frontier model as a chatbot. You ask, it explains at length, you skim
the explanation and copy the one code block you needed. In an automation pipeline that
explanation is not a bonus — it is noise you pay for twice, once in tokens and once in the
step that has to parse around it.</p>
<p>The technique in this video starts from a sharper question. If the expensive model is
better at <em>deciding how to work</em>, and the cheap model is what you can actually afford to
run at volume — can you move the deciding out of the expensive model and into a document?</p>
<div class="hint-container info">
<p class="hint-container-title">About this write-up</p>
<p>This is the written companion to the Fable Mode video on the channel. The technique and
the prompt are mine; this article adds the reasoning behind the prompt's shape, and is
explicit about which parts of the demo are demonstrated and which are still claims.</p>
</div>
<h2>The move: a succession letter</h2>
<p>The prompt does not ask a model to be helpful. It tells the model it is about to be
switched off.</p>
<blockquote>
<p>You're the strongest model I have access to, and that access ends soon. What runs after
you may be Claude Opus 4.8, Sonnet 5, Haiku 4.5, or a smaller and cheaper model I have
not chosen yet. Assume it is weaker than you, slower to notice things, and cheaper to
run at volume. Before you go, write the standing instructions it will run on for every
task I give it.</p>
</blockquote>
<p>That framing does real work. "Write a good system prompt" produces advice. "Write the
orders your weaker replacement will run on, and you will not be here to correct it"
produces something written for an audience that cannot ask follow-up questions.</p>
<p>This is the written companion to the video, where the extraction runs end to end — the
document appearing, then being pasted into a cheaper model's project instructions.</p>
]]></content:encoded>
      <enclosure url="https://blog.taleedevops.today/assets/images/youtube/ai-automation/fable-mode.jpg" type="image/jpeg"/>
    </item>
    <item>
      <title>Google Antigravity 2.0: The Settings Screen Is the Story</title>
      <link>https://blog.taleedevops.today/youtube/ai-automation/google-antigravity-2-permissions.html</link>
      <guid>https://blog.taleedevops.today/youtube/ai-automation/google-antigravity-2-permissions.html</guid>
      <source url="https://blog.taleedevops.today/rss.xml">Google Antigravity 2.0: The Settings Screen Is the Story</source>
      <description>Two products share the name, and the settings screen matters more than the build demo — because this one runs at 8am when nobody is watching.</description>
      <category>YouTube</category>
      <category>AI</category>
      <pubDate>Fri, 21 Aug 2026 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[
<p>Google ships two different things under one name, and picking the wrong one quietly puts you
in the wrong workflow for weeks.</p>
<p>| | Antigravity 2.0 | Antigravity IDE |
|</p>
]]></content:encoded>
      <enclosure url="https://blog.taleedevops.today/assets/images/youtube/ai-automation/antigravity-2.jpg" type="image/jpeg"/>
    </item>
  </channel>
</rss>